summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r--src/wasm/wasm-s-parser.cpp54
1 files changed, 46 insertions, 8 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 47ef33371..c5296aec3 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -23,6 +23,7 @@
#include "ir/branch-utils.h"
#include "shared-constants.h"
#include "wasm-binary.h"
+#include "wasm-builder.h"
#define abort_on(str) \
{ throw ParseException(std::string("abort_on ") + str); }
@@ -48,6 +49,8 @@ int unhex(char c) {
namespace wasm {
+static Name STRUCT("struct"), FIELD("field"), ARRAY("array");
+
static Address getAddress(const Element* s) { return atoll(s->c_str()); }
static void
@@ -61,6 +64,10 @@ static bool elementStartsWith(Element& s, IString str) {
return s.isList() && s.size() > 0 && s[0]->isStr() && s[0]->str() == str;
}
+static bool elementStartsWith(Element* s, IString str) {
+ return elementStartsWith(*s, str);
+}
+
Element::List& Element::list() {
if (!isList()) {
throw ParseException("expected list", line, col);
@@ -908,7 +915,7 @@ Type SExpressionWasmBuilder::elementToType(Element& s) {
}
auto& list = s.list();
auto size = list.size();
- if (size > 0 && elementStartsWith(s, REF)) {
+ if (elementStartsWith(s, REF)) {
// It's a reference. It should be in the form
// (ref $name)
// or
@@ -2129,13 +2136,6 @@ Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) {
return ret;
}
-Expression* SExpressionWasmBuilder::makeStructGet(Element& s) {
- auto ret = allocator.alloc<StructGet>();
- WASM_UNREACHABLE("TODO (gc): struct.get");
- ret->finalize();
- return ret;
-}
-
Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) {
auto ret = allocator.alloc<StructGet>();
WASM_UNREACHABLE("TODO (gc): struct.get_s/u");
@@ -2790,6 +2790,44 @@ HeapType SExpressionWasmBuilder::parseHeapType(Element& s) {
}
return Signature(Type(params), Type(results));
}
+ // It's a struct or an array.
+ auto parseField = [&](Element* t) {
+ bool mutable_ = false;
+ if (t->isStr()) {
+ // t is a simple string name like "i32"
+ return Field(elementToType(*t), mutable_);
+ }
+ // t is a list, containing either
+ // TYPE
+ // or
+ // (field TYPE)
+ // or
+ // (field $name TYPE)
+ Name name;
+ if (elementStartsWith(t, FIELD)) {
+ if (t->size() == 3) {
+ name = (*t)[1]->str();
+ }
+ t = (*t)[t->size() - 1];
+ }
+ // The element may also be (mut (..)).
+ if (elementStartsWith(t, MUT)) {
+ mutable_ = true;
+ t = (*t)[1];
+ }
+ // Otherwise it's an arbitrary type.
+ return Field(elementToType(*t), mutable_, name);
+ };
+ if (elementStartsWith(s, STRUCT)) {
+ FieldList fields;
+ for (size_t k = 1; k < s.size(); k++) {
+ fields.emplace_back(parseField(s[k]));
+ }
+ return Struct(fields);
+ }
+ if (elementStartsWith(s, ARRAY)) {
+ return Array(parseField(s[1]));
+ }
throw ParseException("invalid heap type", s.line, s.col);
}