@@ -107,17 +107,17 @@ Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted,
107107
108108 auto type = scope.exprStack .back ()->type ;
109109
110- if (type.size () == sizeHint) {
110+ if (type.size () == sizeHint || type. size () <= 1 ) {
111111 if (hoisted.get ) {
112112 packageAsBlock (type);
113113 }
114114 return Ok{};
115115 }
116116
117- // We need to break up the hoisted tuple. Create and push a block setting the
118- // tuple to a local and returning its first element, then push additional gets
119- // of each of its subsequent elements. Reuse the scratch local we used for
120- // hoisting, if it exists.
117+ // We need to break up the hoisted tuple. Create and push an expression
118+ // setting the tuple to a local and returning its first element, then push
119+ // additional gets of each of its subsequent elements. Reuse the scratch local
120+ // we used for hoisting, if it exists.
121121 Index scratchIdx;
122122 if (hoisted.get ) {
123123 // Update the get on top of the stack to just return the first element.
@@ -127,12 +127,8 @@ Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted,
127127 } else {
128128 auto scratch = addScratchLocal (type);
129129 CHECK_ERR (scratch);
130- auto * block = builder.makeSequence (
131- builder.makeLocalSet (*scratch, scope.exprStack .back ()),
132- builder.makeTupleExtract (builder.makeLocalGet (*scratch, type), 0 ),
133- type[0 ]);
134- scope.exprStack .pop_back ();
135- push (block);
130+ scope.exprStack .back () = builder.makeTupleExtract (
131+ builder.makeLocalTee (*scratch, scope.exprStack .back (), type), 0 );
136132 scratchIdx = *scratch;
137133 }
138134 for (Index i = 1 , size = type.size (); i < size; ++i) {
@@ -560,6 +556,33 @@ Result<> IRBuilder::visitStringEncode(StringEncode* curr) {
560556 WASM_UNREACHABLE (" unexpected op" );
561557}
562558
559+ Result<> IRBuilder::visitTupleMake (TupleMake* curr) {
560+ assert (curr->operands .size () >= 2 );
561+ for (size_t i = 0 , size = curr->operands .size (); i < size; ++i) {
562+ auto elem = pop ();
563+ CHECK_ERR (elem);
564+ curr->operands [size - 1 - i] = *elem;
565+ }
566+ return Ok{};
567+ }
568+
569+ Result<> IRBuilder::visitTupleExtract (TupleExtract* curr,
570+ std::optional<uint32_t > arity) {
571+ if (!arity) {
572+ if (curr->tuple ->type == Type::unreachable) {
573+ // Fallback to an arbitrary valid arity.
574+ arity = 2 ;
575+ } else {
576+ arity = curr->tuple ->type .size ();
577+ }
578+ }
579+ assert (*arity >= 2 );
580+ auto tuple = pop (*arity);
581+ CHECK_ERR (tuple);
582+ curr->tuple = *tuple;
583+ return Ok{};
584+ }
585+
563586Result<> IRBuilder::visitFunctionStart (Function* func) {
564587 if (!scopeStack.empty ()) {
565588 return Err{" unexpected start of function" };
@@ -1332,9 +1355,27 @@ Result<> IRBuilder::makeRethrow(Index label) {
13321355 return Ok{};
13331356}
13341357
1335- // Result<> IRBuilder::makeTupleMake() {}
1358+ Result<> IRBuilder::makeTupleMake (uint32_t arity) {
1359+ TupleMake curr (wasm.allocator );
1360+ curr.operands .resize (arity);
1361+ CHECK_ERR (visitTupleMake (&curr));
1362+ push (builder.makeTupleMake (curr.operands ));
1363+ return Ok{};
1364+ }
1365+
1366+ Result<> IRBuilder::makeTupleExtract (uint32_t arity, uint32_t index) {
1367+ TupleExtract curr;
1368+ CHECK_ERR (visitTupleExtract (&curr, arity));
1369+ push (builder.makeTupleExtract (curr.tuple , index));
1370+ return Ok{};
1371+ }
13361372
1337- // Result<> IRBuilder::makeTupleExtract() {}
1373+ Result<> IRBuilder::makeTupleDrop (uint32_t arity) {
1374+ Drop curr;
1375+ CHECK_ERR (visitDrop (&curr, arity));
1376+ push (builder.makeDrop (curr.value ));
1377+ return Ok{};
1378+ }
13381379
13391380Result<> IRBuilder::makeRefI31 () {
13401381 RefI31 curr;
0 commit comments