summaryrefslogtreecommitdiff
path: root/src/passes/SafeHeap.cpp
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2020-09-18 15:50:25 -0700
committerGitHub <noreply@github.com>2020-09-18 15:50:25 -0700
commit3b4cb935f83c7fabacbf61146e56dabc0d65a441 (patch)
tree9aaac74aad59fe2ff2b00ac6e6a77bb808b01747 /src/passes/SafeHeap.cpp
parent1a928bc3ff4b511e81b3f93db8aea872e88abaaf (diff)
downloadbinaryen-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.cpp102
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));
}