diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2020-09-18 15:50:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-18 15:50:25 -0700 |
commit | 3b4cb935f83c7fabacbf61146e56dabc0d65a441 (patch) | |
tree | 9aaac74aad59fe2ff2b00ac6e6a77bb808b01747 /src/passes/SafeHeap.cpp | |
parent | 1a928bc3ff4b511e81b3f93db8aea872e88abaaf (diff) | |
download | binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.tar.gz binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.tar.bz2 binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.zip |
Initial implementation of "Memory64" proposal (#3130)
Also includes a lot of new spec tests that eventually need to go into the spec repo
Diffstat (limited to 'src/passes/SafeHeap.cpp')
-rw-r--r-- | src/passes/SafeHeap.cpp | 102 |
1 files changed, 55 insertions, 47 deletions
diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index 108739d66..0335c174e 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -85,10 +85,7 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> { Builder builder(*getModule()); replaceCurrent( builder.makeCall(getLoadName(curr), - { - curr->ptr, - builder.makeConst(Literal(int32_t(curr->offset))), - }, + {curr->ptr, builder.makeConstPtr(curr->offset.addr)}, curr->type)); } @@ -97,14 +94,10 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> { return; } Builder builder(*getModule()); - replaceCurrent( - builder.makeCall(getStoreName(curr), - { - curr->ptr, - builder.makeConst(Literal(int32_t(curr->offset))), - curr->value, - }, - Type::none)); + replaceCurrent(builder.makeCall( + getStoreName(curr), + {curr->ptr, builder.makeConstPtr(curr->offset.addr), curr->value}, + Type::none)); } }; @@ -125,6 +118,7 @@ struct SafeHeap : public Pass { void addImports(Module* module) { ImportInfo info(*module); + auto indexType = module->memory.indexType; // Older emscripten imports env.DYNAMICTOP_PTR. // Newer emscripten imports or exports emscripten_get_sbrk_ptr(). if (auto* existing = info.getImportedGlobal(ENV, DYNAMICTOP_PTR_IMPORT)) { @@ -140,7 +134,7 @@ struct SafeHeap : public Pass { import->name = getSbrkPtr = GET_SBRK_PTR; import->module = ENV; import->base = GET_SBRK_PTR; - import->sig = Signature(Type::none, Type::i32); + import->sig = Signature(Type::none, indexType); module->addFunction(import); } if (auto* existing = info.getImportedFunction(ENV, SEGFAULT_IMPORT)) { @@ -251,25 +245,27 @@ struct SafeHeap : public Pass { auto* func = new Function; func->name = name; // pointer, offset - func->sig = Signature({Type::i32, Type::i32}, style.type); - func->vars.push_back(Type::i32); // pointer + offset + auto indexType = module->memory.indexType; + func->sig = Signature({indexType, indexType}, style.type); + func->vars.push_back(indexType); // pointer + offset Builder builder(*module); auto* block = builder.makeBlock(); block->list.push_back(builder.makeLocalSet( 2, - builder.makeBinary(AddInt32, - builder.makeLocalGet(0, Type::i32), - builder.makeLocalGet(1, Type::i32)))); + builder.makeBinary(module->memory.is64() ? AddInt64 : AddInt32, + builder.makeLocalGet(0, indexType), + builder.makeLocalGet(1, indexType)))); // check for reading past valid memory: if pointer + offset + bytes - block->list.push_back(makeBoundsCheck(style.type, builder, 2, style.bytes)); + block->list.push_back( + makeBoundsCheck(style.type, builder, 2, style.bytes, module)); // check proper alignment if (style.align > 1) { - block->list.push_back(makeAlignCheck(style.align, builder, 2)); + block->list.push_back(makeAlignCheck(style.align, builder, 2, module)); } // do the load auto* load = module->allocator.alloc<Load>(); *load = style; // basically the same as the template we are given! - load->ptr = builder.makeLocalGet(2, Type::i32); + load->ptr = builder.makeLocalGet(2, indexType); Expression* last = load; if (load->isAtomic && load->signed_) { // atomic loads cannot be signed, manually sign it @@ -291,26 +287,27 @@ struct SafeHeap : public Pass { auto* func = new Function; func->name = name; // pointer, offset, value - func->sig = Signature({Type::i32, Type::i32, style.valueType}, Type::none); - func->vars.push_back(Type::i32); // pointer + offset + auto indexType = module->memory.indexType; + func->sig = Signature({indexType, indexType, style.valueType}, Type::none); + func->vars.push_back(indexType); // pointer + offset Builder builder(*module); auto* block = builder.makeBlock(); block->list.push_back(builder.makeLocalSet( 3, - builder.makeBinary(AddInt32, - builder.makeLocalGet(0, Type::i32), - builder.makeLocalGet(1, Type::i32)))); + builder.makeBinary(module->memory.is64() ? AddInt64 : AddInt32, + builder.makeLocalGet(0, indexType), + builder.makeLocalGet(1, indexType)))); // check for reading past valid memory: if pointer + offset + bytes block->list.push_back( - makeBoundsCheck(style.valueType, builder, 3, style.bytes)); + makeBoundsCheck(style.valueType, builder, 3, style.bytes, module)); // check proper alignment if (style.align > 1) { - block->list.push_back(makeAlignCheck(style.align, builder, 3)); + block->list.push_back(makeAlignCheck(style.align, builder, 3, module)); } // do the store auto* store = module->allocator.alloc<Store>(); *store = style; // basically the same as the template we are given! - store->ptr = builder.makeLocalGet(3, Type::i32); + store->ptr = builder.makeLocalGet(3, indexType); store->value = builder.makeLocalGet(2, style.valueType); block->list.push_back(store); block->finalize(Type::none); @@ -318,42 +315,53 @@ struct SafeHeap : public Pass { module->addFunction(func); } - Expression* makeAlignCheck(Address align, Builder& builder, Index local) { + Expression* + makeAlignCheck(Address align, Builder& builder, Index local, Module* module) { + auto indexType = module->memory.indexType; + Expression* ptrBits = builder.makeLocalGet(local, indexType); + if (module->memory.is64()) { + ptrBits = builder.makeUnary(WrapInt64, ptrBits); + } return builder.makeIf( - builder.makeBinary(AndInt32, - builder.makeLocalGet(local, Type::i32), - builder.makeConst(Literal(int32_t(align - 1)))), + builder.makeBinary( + AndInt32, ptrBits, builder.makeConst(int32_t(align - 1))), builder.makeCall(alignfault, {}, Type::none)); } - Expression* - makeBoundsCheck(Type type, Builder& builder, Index local, Index bytes) { - auto upperOp = options.lowMemoryUnused ? LtUInt32 : EqInt32; + Expression* makeBoundsCheck( + Type type, Builder& builder, Index local, Index bytes, Module* module) { + auto indexType = module->memory.indexType; + auto upperOp = module->memory.is64() + ? options.lowMemoryUnused ? LtUInt64 : EqInt64 + : options.lowMemoryUnused ? LtUInt32 : EqInt32; auto upperBound = options.lowMemoryUnused ? PassOptions::LowMemoryBound : 0; Expression* brkLocation; if (sbrk.is()) { - brkLocation = builder.makeCall( - sbrk, {builder.makeConst(Literal(int32_t(0)))}, Type::i32); + brkLocation = + builder.makeCall(sbrk, {builder.makeConstPtr(0)}, indexType); } else { Expression* sbrkPtr; if (dynamicTopPtr.is()) { - sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, Type::i32); + sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, indexType); } else { - sbrkPtr = builder.makeCall(getSbrkPtr, {}, Type::i32); + sbrkPtr = builder.makeCall(getSbrkPtr, {}, indexType); } - brkLocation = builder.makeLoad(4, false, 0, 4, sbrkPtr, Type::i32); + auto size = module->memory.is64() ? 8 : 4; + brkLocation = builder.makeLoad(size, false, 0, size, sbrkPtr, indexType); } + auto gtuOp = module->memory.is64() ? GtUInt64 : GtUInt32; + auto addOp = module->memory.is64() ? AddInt64 : AddInt32; return builder.makeIf( builder.makeBinary( OrInt32, builder.makeBinary(upperOp, - builder.makeLocalGet(local, Type::i32), - builder.makeConst(Literal(int32_t(upperBound)))), + builder.makeLocalGet(local, indexType), + builder.makeConstPtr(upperBound)), builder.makeBinary( - GtUInt32, - builder.makeBinary(AddInt32, - builder.makeLocalGet(local, Type::i32), - builder.makeConst(Literal(int32_t(bytes)))), + gtuOp, + builder.makeBinary(addOp, + builder.makeLocalGet(local, indexType), + builder.makeConstPtr(bytes)), brkLocation)), builder.makeCall(segfault, {}, Type::none)); } |