@@ -2539,6 +2539,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
25392539
25402540 auto top = allocator.alloc <Block>();
25412541 if (canSwitch) {
2542+
2543+ // we may need a break for the case where the condition doesn't match
2544+ // any of the cases. it should go to the default, if we have one, or
2545+ // outside if not
2546+ Break* breakWhenNotMatching = nullptr ;
2547+
25422548 if (br->condition ->type == i32 ) {
25432549 Binary* offsetor = allocator.alloc <Binary>();
25442550 offsetor->op = BinaryOp::SubInt32;
@@ -2554,7 +2560,28 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
25542560 offsetor->left = br->condition ;
25552561 offsetor->right = builder.makeConst (Literal (int64_t (min)));
25562562 offsetor->type = i64 ;
2557- br->condition = builder.makeUnary (UnaryOp::WrapInt64, offsetor); // TODO: check this fits in 32 bits
2563+ // the switch itself can be 32-bit, as the range is in a reasonable range. so after
2564+ // offsetting, we need to make sure there are no high bits, then we can just look
2565+ // at the lower 32 bits
2566+ auto temp = Builder::addVar (function, i64 );
2567+ auto * block = builder.makeBlock ();
2568+ block->list .push_back (builder.makeSetLocal (temp, offsetor));
2569+ // if high bits, we can break to the default (we'll fill in the name later)
2570+ breakWhenNotMatching = builder.makeBreak (Name (), nullptr ,
2571+ builder.makeUnary (
2572+ UnaryOp::WrapInt64,
2573+ builder.makeBinary (BinaryOp::ShrUInt64,
2574+ builder.makeGetLocal (temp, i64 ),
2575+ builder.makeConst (Literal (int64_t (32 )))
2576+ )
2577+ )
2578+ );
2579+ block->list .push_back (breakWhenNotMatching);
2580+ block->list .push_back (
2581+ builder.makeGetLocal (temp, i64 )
2582+ );
2583+ block->finalize ();
2584+ br->condition = builder.makeUnary (UnaryOp::WrapInt64, block);
25582585 }
25592586
25602587 top->list .push_back (br);
@@ -2595,6 +2622,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
25952622 if (br->default_ .isNull ()) {
25962623 br->default_ = top->name ;
25972624 }
2625+ if (breakWhenNotMatching) {
2626+ breakWhenNotMatching->name = br->default_ ;
2627+ }
25982628 for (size_t i = 0 ; i < br->targets .size (); i++) {
25992629 if (br->targets [i].isNull ()) br->targets [i] = br->default_ ;
26002630 }
0 commit comments