@@ -2173,17 +2173,36 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
21732173}
21742174
21752175void WasmBinaryBuilder::pushBlockElements (Block* curr, size_t start, size_t end) {
2176+ // the first dropped element may be consumed by code later - it was on the stack first,
2177+ // and is the only thing left on the stack. there must be just one thing on the stack
2178+ // since we are at the end of a block context. note that we may need to drop more than
2179+ // one thing, since a bunch of concrete values may be all "consumed" by an unreachable
2180+ // (in which case, the first value can't be consumed anyhow, so it doesn't matter)
2181+ const Index NONE = -1 ;
2182+ Index consumable = NONE;
21762183 for (size_t i = start; i < end; i++) {
21772184 auto * item = expressionStack[i];
21782185 curr->list .push_back (item);
21792186 if (i < end - 1 ) {
21802187 // stacky&unreachable code may introduce elements that need to be dropped in non-final positions
21812188 if (isConcreteWasmType (item->type )) {
2182- curr->list .back () = Builder (wasm).makeDrop (curr->list .back ());
2189+ curr->list .back () = Builder (wasm).makeDrop (item);
2190+ if (consumable == NONE) {
2191+ // this is the first, and hence consumable value. note the location
2192+ consumable = curr->list .size () - 1 ;
2193+ }
21832194 }
21842195 }
21852196 }
21862197 expressionStack.resize (start);
2198+ // if we have a consumable item and need it, use it
2199+ if (consumable != NONE && curr->list .back ()->type == none) {
2200+ Builder builder (wasm);
2201+ auto * item = curr->list [consumable]->cast <Drop>()->value ;
2202+ auto temp = builder.addVar (currFunction, item->type );
2203+ curr->list [consumable] = builder.makeSetLocal (temp, item);
2204+ curr->list .push_back (builder.makeGetLocal (temp, item->type ));
2205+ }
21872206}
21882207
21892208void WasmBinaryBuilder::visitBlock (Block *curr) {
0 commit comments