diff options
author | Alon Zakai <azakai@google.com> | 2021-07-15 10:26:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-15 10:26:59 -0700 |
commit | 27831cba47722c10a8a6f412d56665a4e7074540 (patch) | |
tree | f93c1909477ad3ee1dd2dd612732d722b7ff77a3 /src | |
parent | a3d6930e59114196f29cb3318e96843dbd0b413c (diff) | |
download | binaryen-27831cba47722c10a8a6f412d56665a4e7074540.tar.gz binaryen-27831cba47722c10a8a6f412d56665a4e7074540.tar.bz2 binaryen-27831cba47722c10a8a6f412d56665a4e7074540.zip |
[Wasm GC] Add Wasm GC support to InstrumentMemory (#3976)
This adds calls to imports around every struct load and store, to
note their values, and also to arrays (where it also notes the
index).
This has been very useful in debugging LowerGC (lowering of Wasm
GC to wasm MVP).
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/InstrumentMemory.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp index 38a23a658..073c78822 100644 --- a/src/passes/InstrumentMemory.cpp +++ b/src/passes/InstrumentMemory.cpp @@ -51,6 +51,11 @@ // (i32.const 4) // ) // ) +// +// GC struct and array operations are similarly instrumented, but without their +// pointers (which are references), and we only log MVP wasm types (i.e., not +// references or rtts). +// #include "asmjs/shared-constants.h" #include "shared-constants.h" @@ -70,6 +75,24 @@ static Name store_val_i32("store_val_i32"); static Name store_val_i64("store_val_i64"); static Name store_val_f32("store_val_f32"); static Name store_val_f64("store_val_f64"); +static Name struct_get_val_i32("struct_get_val_i32"); +static Name struct_get_val_i64("struct_get_val_i64"); +static Name struct_get_val_f32("struct_get_val_f32"); +static Name struct_get_val_f64("struct_get_val_f64"); +static Name struct_set_val_i32("struct_set_val_i32"); +static Name struct_set_val_i64("struct_set_val_i64"); +static Name struct_set_val_f32("struct_set_val_f32"); +static Name struct_set_val_f64("struct_set_val_f64"); +static Name array_get_val_i32("array_get_val_i32"); +static Name array_get_val_i64("array_get_val_i64"); +static Name array_get_val_f32("array_get_val_f32"); +static Name array_get_val_f64("array_get_val_f64"); +static Name array_set_val_i32("array_set_val_i32"); +static Name array_set_val_i64("array_set_val_i64"); +static Name array_set_val_f32("array_set_val_f32"); +static Name array_set_val_f64("array_set_val_f64"); +static Name array_get_index("array_get_index"); +static Name array_set_index("array_set_index"); // TODO: Add support for atomicRMW/cmpxchg @@ -138,20 +161,132 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> { target, {builder.makeConst(int32_t(id)), curr->value}, curr->value->type); } + void visitStructGet(StructGet* curr) { + Builder builder(*getModule()); + Name target; + if (curr->type == Type::i32) { + target = struct_get_val_i32; + } else if (curr->type == Type::i64) { + target = struct_get_val_i64; + } else if (curr->type == Type::f32) { + target = struct_get_val_f32; + } else if (curr->type == Type::f64) { + target = struct_get_val_f64; + } else { + return; // TODO: other types, unreachable, etc. + } + replaceCurrent(builder.makeCall( + target, {builder.makeConst(int32_t(id++)), curr}, curr->type)); + } + + void visitStructSet(StructSet* curr) { + Builder builder(*getModule()); + Name target; + if (curr->value->type == Type::i32) { + target = struct_set_val_i32; + } else if (curr->value->type == Type::i64) { + target = struct_set_val_i64; + } else if (curr->value->type == Type::f32) { + target = struct_set_val_f32; + } else if (curr->value->type == Type::f64) { + target = struct_set_val_f64; + } else { + return; // TODO: other types, unreachable, etc. + } + curr->value = + builder.makeCall(target, + {builder.makeConst(int32_t(id++)), curr->value}, + curr->value->type); + } + + void visitArrayGet(ArrayGet* curr) { + Builder builder(*getModule()); + curr->index = + builder.makeCall(array_get_index, + {builder.makeConst(int32_t(id++)), curr->index}, + Type::i32); + Name target; + if (curr->type == Type::i32) { + target = array_get_val_i32; + } else if (curr->type == Type::i64) { + target = array_get_val_i64; + } else if (curr->type == Type::f32) { + target = array_get_val_f32; + } else if (curr->type == Type::f64) { + target = array_get_val_f64; + } else { + return; // TODO: other types, unreachable, etc. + } + replaceCurrent(builder.makeCall( + target, {builder.makeConst(int32_t(id++)), curr}, curr->type)); + } + + void visitArraySet(ArraySet* curr) { + Builder builder(*getModule()); + curr->index = + builder.makeCall(array_set_index, + {builder.makeConst(int32_t(id++)), curr->index}, + Type::i32); + Name target; + if (curr->value->type == Type::i32) { + target = array_set_val_i32; + } else if (curr->value->type == Type::i64) { + target = array_set_val_i64; + } else if (curr->value->type == Type::f32) { + target = array_set_val_f32; + } else if (curr->value->type == Type::f64) { + target = array_set_val_f64; + } else { + return; // TODO: other types, unreachable, etc. + } + curr->value = + builder.makeCall(target, + {builder.makeConst(int32_t(id++)), curr->value}, + curr->value->type); + } + void visitModule(Module* curr) { auto indexType = curr->memory.indexType; + + // Load. addImport( curr, load_ptr, {Type::i32, Type::i32, indexType, indexType}, indexType); addImport(curr, load_val_i32, {Type::i32, Type::i32}, Type::i32); addImport(curr, load_val_i64, {Type::i32, Type::i64}, Type::i64); addImport(curr, load_val_f32, {Type::i32, Type::f32}, Type::f32); addImport(curr, load_val_f64, {Type::i32, Type::f64}, Type::f64); + + // Store. addImport( curr, store_ptr, {Type::i32, Type::i32, indexType, indexType}, indexType); addImport(curr, store_val_i32, {Type::i32, Type::i32}, Type::i32); addImport(curr, store_val_i64, {Type::i32, Type::i64}, Type::i64); addImport(curr, store_val_f32, {Type::i32, Type::f32}, Type::f32); addImport(curr, store_val_f64, {Type::i32, Type::f64}, Type::f64); + + if (curr->features.hasGC()) { + // Struct get/set. + addImport(curr, struct_get_val_i32, {Type::i32, Type::i32}, Type::i32); + addImport(curr, struct_get_val_i64, {Type::i32, Type::i64}, Type::i64); + addImport(curr, struct_get_val_f32, {Type::i32, Type::f32}, Type::f32); + addImport(curr, struct_get_val_f64, {Type::i32, Type::f64}, Type::f64); + addImport(curr, struct_set_val_i32, {Type::i32, Type::i32}, Type::i32); + addImport(curr, struct_set_val_i64, {Type::i32, Type::i64}, Type::i64); + addImport(curr, struct_set_val_f32, {Type::i32, Type::f32}, Type::f32); + addImport(curr, struct_set_val_f64, {Type::i32, Type::f64}, Type::f64); + + // Array get/set. + addImport(curr, array_get_val_i32, {Type::i32, Type::i32}, Type::i32); + addImport(curr, array_get_val_i64, {Type::i32, Type::i64}, Type::i64); + addImport(curr, array_get_val_f32, {Type::i32, Type::f32}, Type::f32); + addImport(curr, array_get_val_f64, {Type::i32, Type::f64}, Type::f64); + addImport(curr, array_set_val_i32, {Type::i32, Type::i32}, Type::i32); + addImport(curr, array_set_val_i64, {Type::i32, Type::i64}, Type::i64); + addImport(curr, array_set_val_f32, {Type::i32, Type::f32}, Type::f32); + addImport(curr, array_set_val_f64, {Type::i32, Type::f64}, Type::f64); + addImport(curr, array_get_index, {Type::i32, Type::i32}, Type::i32); + addImport(curr, array_set_index, {Type::i32, Type::i32}, Type::i32); + } } private: |