@@ -330,6 +330,7 @@ static const Name START_REWIND = "start_rewind";
330330static const Name STOP_REWIND = " stop_rewind" ;
331331static const Name ASYNCIFY_GET_CALL_INDEX = " __asyncify_get_call_index" ;
332332static const Name ASYNCIFY_CHECK_CALL_INDEX = " __asyncify_check_call_index" ;
333+ static const Name ASYNCIFY_BUFFER_TABLE = " __asyncify_buffer_table" ;
333334
334335// TODO: having just normal/unwind_or_rewind would decrease code
335336// size, but make debugging harder
@@ -1368,32 +1369,48 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
13681369 if (!relevantLiveLocals.count (i)) {
13691370 continue ;
13701371 }
1371- total += getByteSize (func->getLocalType (i));
1372+ auto localType = func->getLocalType (i);
1373+ // TODO[doe]: I'm not sure about tuple unpacking here, revisit, verify
1374+ for (const auto & type : localType) {
1375+ if (type.hasByteSize ()) {
1376+ total += type.getByteSize ();
1377+ }
1378+ }
13721379 }
13731380 auto * block = builder->makeBlock ();
13741381 block->list .push_back (builder->makeIncStackPos (-total));
13751382 auto tempIndex = builder->addVar (func, Type::i32 );
13761383 block->list .push_back (
13771384 builder->makeLocalSet (tempIndex, builder->makeGetStackPos ()));
13781385 Index offset = 0 ;
1386+ Index table_idx = 0 ;
13791387 for (Index i = 0 ; i < numLocals; i++) {
13801388 if (!relevantLiveLocals.count (i)) {
13811389 continue ;
13821390 }
13831391 auto localType = func->getLocalType (i);
13841392 SmallVector<Expression*, 1 > loads;
13851393 for (const auto & type : localType) {
1386- auto size = getByteSize (type);
1387- assert (size % STACK_ALIGN == 0 );
1388- // TODO: higher alignment?
1389- loads.push_back (
1390- builder->makeLoad (size,
1391- true ,
1392- offset,
1393- STACK_ALIGN,
1394- builder->makeLocalGet (tempIndex, Type::i32 ),
1395- type));
1396- offset += size;
1394+ if (type.hasByteSize ()) {
1395+ auto size = type.getByteSize ();
1396+ assert (size % STACK_ALIGN == 0 );
1397+ // TODO: higher alignment?
1398+ loads.push_back (
1399+ builder->makeLoad (size,
1400+ true ,
1401+ offset,
1402+ STACK_ALIGN,
1403+ builder->makeLocalGet (tempIndex, Type::i32 ),
1404+ type));
1405+ offset += size;
1406+ } else {
1407+ // TODO[doe]: revisit, verify
1408+ loads.push_back (
1409+ builder->makeTableGet (ASYNCIFY_BUFFER_TABLE,
1410+ builder->makeConst (Index (table_idx)),
1411+ type));
1412+ ++table_idx;
1413+ }
13971414 }
13981415 Expression* load;
13991416 if (loads.size () == 1 ) {
@@ -1420,28 +1437,38 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
14201437 block->list .push_back (
14211438 builder->makeLocalSet (tempIndex, builder->makeGetStackPos ()));
14221439 Index offset = 0 ;
1440+ Index table_idx = 0 ;
14231441 for (Index i = 0 ; i < numLocals; i++) {
14241442 if (!relevantLiveLocals.count (i)) {
14251443 continue ;
14261444 }
14271445 auto localType = func->getLocalType (i);
14281446 size_t j = 0 ;
14291447 for (const auto & type : localType) {
1430- auto size = getByteSize (type);
14311448 Expression* localGet = builder->makeLocalGet (i, localType);
14321449 if (localType.size () > 1 ) {
14331450 localGet = builder->makeTupleExtract (localGet, j);
14341451 }
1435- assert (size % STACK_ALIGN == 0 );
1436- // TODO: higher alignment?
1437- block->list .push_back (
1438- builder->makeStore (size,
1439- offset,
1440- STACK_ALIGN,
1441- builder->makeLocalGet (tempIndex, Type::i32 ),
1442- localGet,
1443- type));
1444- offset += size;
1452+ if (type.hasByteSize ()) {
1453+ auto size = type.getByteSize ();
1454+ assert (size % STACK_ALIGN == 0 );
1455+ // TODO: higher alignment?
1456+ block->list .push_back (
1457+ builder->makeStore (size,
1458+ offset,
1459+ STACK_ALIGN,
1460+ builder->makeLocalGet (tempIndex, Type::i32 ),
1461+ localGet,
1462+ type));
1463+ offset += size;
1464+ } else {
1465+ // TODO[doe]: revisit, verify
1466+ block->list .push_back (
1467+ builder->makeTableSet (ASYNCIFY_BUFFER_TABLE,
1468+ builder->makeConst (Index (table_idx)),
1469+ localGet));
1470+ ++table_idx;
1471+ }
14451472 ++j;
14461473 }
14471474 }
@@ -1461,15 +1488,6 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
14611488 Type::i32 ),
14621489 builder->makeIncStackPos (4 ));
14631490 }
1464-
1465- unsigned getByteSize (Type type) {
1466- if (!type.hasByteSize ()) {
1467- Fatal () << " Asyncify does not yet support non-number types, like "
1468- " references (see "
1469- " https://github.com/WebAssembly/binaryen/issues/3739)" ;
1470- }
1471- return type.getByteSize ();
1472- }
14731491};
14741492
14751493} // anonymous namespace
@@ -1561,6 +1579,9 @@ struct Asyncify : public Pass {
15611579 // Add necessary globals before we emit code to use them.
15621580 addGlobals (module , relocatable);
15631581
1582+ // TODO[doe]: revisit, not sure if it's a good place to add the table
1583+ addTable (module );
1584+
15641585 // Instrument the flow of code, adding code instrumentation and
15651586 // skips for when rewinding. We do this on flat IR so that it is
15661587 // practical to add code around each call, without affecting
@@ -1638,6 +1659,16 @@ struct Asyncify : public Pass {
16381659 module ->addGlobal (std::move (asyncifyData));
16391660 }
16401661
1662+ // TODO[doe]: Revisit: name, initial, max
1663+ void addTable (Module* module ) {
1664+ Builder builder (*module );
1665+ auto buffer_table = builder.makeTable (ASYNCIFY_BUFFER_TABLE,
1666+ Type::anyref,
1667+ 0 ,
1668+ 0 );
1669+ module ->addTable (std::move (buffer_table));
1670+ }
1671+
16411672 void addFunctions (Module* module ) {
16421673 Builder builder (*module );
16431674 auto makeFunction = [&](Name name, bool setData, State state) {
0 commit comments