@@ -890,14 +890,23 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
890890 value.type .getHeapType ().isMaybeShared (HeapType::i31));
891891 }
892892
893- // GC data (structs and arrays) must be handled with the special global-
894- // creating logic later down. But MVP types as well as i31s (even
895- // externalized i31s) can be handled by the general makeConstantExpression
896- // logic (which knows how to handle externalization, for i31s; and it also
897- // can handle string constants).
898- if (!value.isData () || value.isString ()) {
893+ // GC data (structs and arrays) and waitqueues must be handled with the
894+ // special global-creating logic later down. But MVP types as well as i31s
895+ // (even externalized i31s) can be handled by the general
896+ // makeConstantExpression logic (which knows how to handle externalization,
897+ // for i31s; and it also can handle string constants).
898+ bool isWaitqueue =
899+ value.type .isRef () &&
900+ value.type .getHeapType ().isMaybeShared (HeapType::waitqueue);
901+ if ((!value.isData () && !isWaitqueue) || value.isString ()) {
899902 return builder.makeConstantExpression (original);
900903 }
904+ if (isWaitqueue && !wasm->features .hasGC ()) {
905+ // Without GC we cannot refer to a defining global in another global's
906+ // initializer, and waitqueue identity cannot be observed without
907+ // struct.wait.
908+ return builder.makeWaitqueueNew ();
909+ }
901910
902911 // This is GC data, which we must handle in a more careful way.
903912 auto * data = value.getGCData ().get ();
@@ -911,7 +920,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
911920 definingGlobalName = it->second .name ;
912921 } else {
913922 // This is the first usage of this data. Generate a struct.new /
914- // array.new for it.
923+ // array.new / waitqueue.new for it.
915924 std::vector<Expression*> args;
916925
917926 // The initial values for this allocation may themselves be GC
@@ -933,31 +942,35 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
933942 definingGlobals[data] = DefiningGlobalInfo{definingGlobalName, type};
934943 }
935944
936- for (size_t i = 0 ; i < value.getNumElements (); i++) {
937- auto * serialized = getSerialization (value.getElement (i));
938- if (!serialized) {
939- return nullptr ;
945+ Expression* init;
946+ auto heapType = type.getHeapType ();
947+ if (heapType.isMaybeShared (HeapType::waitqueue)) {
948+ init = builder.makeWaitqueueNew ();
949+ } else {
950+ for (size_t i = 0 ; i < value.getNumElements (); i++) {
951+ auto * serialized = getSerialization (value.getElement (i));
952+ if (!serialized) {
953+ return nullptr ;
954+ }
955+ args.push_back (serialized);
940956 }
941- args.push_back (serialized);
942- }
943957
944- Expression* desc = nullptr ;
945- if (data->desc .getGCData ()) {
946- desc = getSerialization (data->desc );
947- if (!desc) {
948- return nullptr ;
958+ Expression* desc = nullptr ;
959+ if (data->desc .getGCData ()) {
960+ desc = getSerialization (data->desc );
961+ if (!desc) {
962+ return nullptr ;
963+ }
949964 }
950- }
951965
952- Expression* init;
953- auto heapType = type.getHeapType ();
954- if (heapType.isStruct ()) {
955- init = builder.makeStructNew (heapType, args, desc);
956- } else if (heapType.isArray ()) {
957- // TODO: for repeated identical values, can use ArrayNew
958- init = builder.makeArrayNewFixed (heapType, args);
959- } else {
960- WASM_UNREACHABLE (" bad gc type" );
966+ if (heapType.isStruct ()) {
967+ init = builder.makeStructNew (heapType, args, desc);
968+ } else if (heapType.isArray ()) {
969+ // TODO: for repeated identical values, can use ArrayNew
970+ init = builder.makeArrayNewFixed (heapType, args);
971+ } else {
972+ WASM_UNREACHABLE (" bad gc type" );
973+ }
961974 }
962975
963976 if (possibleDefiningGlobal.is ()) {
0 commit comments