summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/wasm-ctor-eval.cpp29
-rw-r--r--src/wasm-builder.h4
2 files changed, 29 insertions, 4 deletions
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index 00bceac8f..195a5350f 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -572,13 +572,28 @@ public:
// If |possibleDefiningGlobal| is provided, it is the name of a global that we
// are in the init expression of, and which can be reused as defining global,
// if the other conditions are suitable.
- Expression* getSerialization(const Literal& value,
+ Expression* getSerialization(Literal value,
Name possibleDefiningGlobal = Name()) {
Builder builder(*wasm);
+ // If this is externalized then we want to inspect the inner data, handle
+ // that, and emit a ref.externalize around it as needed. To simplify the
+ // logic here, we save the original (possible externalized) value, and then
+ // look at the internals from here on out.
+ Literal original = value;
+ if (value.type.isRef() && value.type.getHeapType() == HeapType::ext) {
+ value = value.internalize();
+
+ // We cannot serialize truly external things, only data and i31s.
+ assert(value.isData() || value.type.getHeapType() == HeapType::i31);
+ }
+
+ // GC data (structs and arrays) must be handled with the special global-
+ // creating logic later down. But MVP types as well as i31s (even
+ // externalized i31s) can be handled by the general makeConstantExpression
+ // logic (which knows how to handle externalization, for i31s).
if (!value.isData()) {
- // This can be handled normally.
- return builder.makeConstantExpression(value);
+ return builder.makeConstantExpression(original);
}
// This is GC data, which we must handle in a more careful way.
@@ -637,7 +652,13 @@ public:
// Refer to this GC allocation by reading from the global that is
// designated to contain it.
- return builder.makeGlobalGet(definingGlobal, value.type);
+ Expression* ret = builder.makeGlobalGet(definingGlobal, value.type);
+ if (original != value) {
+ // The original is externalized.
+ assert(original.type.getHeapType() == HeapType::ext);
+ ret = builder.makeRefAs(ExternExternalize, ret);
+ }
+ return ret;
}
Expression* getSerialization(const Literals& values,
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index cbdd7abf7..8b34d6933 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -1155,6 +1155,10 @@ public:
}
return makeStringConst(string);
}
+ if (type.isRef() && type.getHeapType() == HeapType::ext) {
+ return makeRefAs(ExternExternalize,
+ makeConstantExpression(value.internalize()));
+ }
TODO_SINGLE_COMPOUND(type);
WASM_UNREACHABLE("unsupported constant expression");
}