diff options
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: |