summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-07-26 12:11:33 -0700
committerGitHub <noreply@github.com>2017-07-26 12:11:33 -0700
commitc8218452f1048449dff6c54a3f2d910538fe8f4e (patch)
tree27dc0ff56994d5df22f6873fd8cfd994c96dbf44 /src
parentcfe0fa129be2022ba9521bbd9355bd4b0aa1f01d (diff)
downloadbinaryen-c8218452f1048449dff6c54a3f2d910538fe8f4e.tar.gz
binaryen-c8218452f1048449dff6c54a3f2d910538fe8f4e.tar.bz2
binaryen-c8218452f1048449dff6c54a3f2d910538fe8f4e.zip
fix asm2wasm wasm-only i64 switches with a large (>32 bit) offset #1109 (#1111)
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 9abfe7432..153839065 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -2539,6 +2539,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
auto top = allocator.alloc<Block>();
if (canSwitch) {
+
+ // we may need a break for the case where the condition doesn't match
+ // any of the cases. it should go to the default, if we have one, or
+ // outside if not
+ Break* breakWhenNotMatching = nullptr;
+
if (br->condition->type == i32) {
Binary* offsetor = allocator.alloc<Binary>();
offsetor->op = BinaryOp::SubInt32;
@@ -2554,7 +2560,28 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
offsetor->left = br->condition;
offsetor->right = builder.makeConst(Literal(int64_t(min)));
offsetor->type = i64;
- br->condition = builder.makeUnary(UnaryOp::WrapInt64, offsetor); // TODO: check this fits in 32 bits
+ // the switch itself can be 32-bit, as the range is in a reasonable range. so after
+ // offsetting, we need to make sure there are no high bits, then we can just look
+ // at the lower 32 bits
+ auto temp = Builder::addVar(function, i64);
+ auto* block = builder.makeBlock();
+ block->list.push_back(builder.makeSetLocal(temp, offsetor));
+ // if high bits, we can break to the default (we'll fill in the name later)
+ breakWhenNotMatching = builder.makeBreak(Name(), nullptr,
+ builder.makeUnary(
+ UnaryOp::WrapInt64,
+ builder.makeBinary(BinaryOp::ShrUInt64,
+ builder.makeGetLocal(temp, i64),
+ builder.makeConst(Literal(int64_t(32)))
+ )
+ )
+ );
+ block->list.push_back(breakWhenNotMatching);
+ block->list.push_back(
+ builder.makeGetLocal(temp, i64)
+ );
+ block->finalize();
+ br->condition = builder.makeUnary(UnaryOp::WrapInt64, block);
}
top->list.push_back(br);
@@ -2595,6 +2622,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
if (br->default_.isNull()) {
br->default_ = top->name;
}
+ if (breakWhenNotMatching) {
+ breakWhenNotMatching->name = br->default_;
+ }
for (size_t i = 0; i < br->targets.size(); i++) {
if (br->targets[i].isNull()) br->targets[i] = br->default_;
}