diff options
author | Alon Zakai <azakai@google.com> | 2023-09-28 12:07:39 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-28 12:07:39 -0700 |
commit | d49f518eee07d9c267a32ca9443069255b4cbd1f (patch) | |
tree | ea90214ad6dbc56f6b5f20735fff9e07105547c7 /src/wasm/wasm-s-parser.cpp | |
parent | 7fe2773010a5be824ac2b75cf8ee5dac90368aaf (diff) | |
download | binaryen-d49f518eee07d9c267a32ca9443069255b4cbd1f.tar.gz binaryen-d49f518eee07d9c267a32ca9443069255b4cbd1f.tar.bz2 binaryen-d49f518eee07d9c267a32ca9443069255b4cbd1f.zip |
wasm-s-parser: Add context in validation errors (#5981)
Instead of just reporting the reason and line + column, also log out the element
the error occurred at.
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 389 |
1 files changed, 188 insertions, 201 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index dec9249c3..215d349e1 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -27,6 +27,8 @@ #include "wasm-binary.h" #include "wasm-builder.h" +using namespace std::string_literals; + #define abort_on(str) \ { throw ParseException(std::string("abort_on ") + str); } #define element_assert(condition) \ @@ -49,6 +51,19 @@ int unhex(char c) { namespace wasm { +// Similar to ParseException but built from an Element. +struct SParseException : public ParseException { + // Receive an element and report its contents, line and column. + SParseException(std::string text, const Element& s) + : ParseException(text + ": " + s.forceString(), s.line, s.col) {} + + // Receive a parent and child element. We print out the full parent for + // context, but report the child line and column inside it. + SParseException(std::string text, const Element& parent, const Element& child) + : ParseException( + text + ": " + parent.forceString(), child.line, child.col) {} +}; + static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), REC("rec"), I8("i8"), I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"), SUB("sub"), FINAL("final"); @@ -60,7 +75,7 @@ static Address getAddress(const Element* s) { static void checkAddress(Address a, const char* errorText, const Element* errorElem) { if (a > std::numeric_limits<Address::address32_t>::max()) { - throw ParseException(errorText, errorElem->line, errorElem->col); + throw SParseException(errorText, *errorElem); } } @@ -74,35 +89,42 @@ static bool elementStartsWith(Element* s, IString str) { Element::List& Element::list() { if (!isList()) { - throw ParseException("expected list", line, col); + throw SParseException("expected list", *this); } return list_; } Element* Element::operator[](unsigned i) { if (!isList()) { - throw ParseException("expected list", line, col); + throw SParseException("expected list", *this); } if (i >= list().size()) { - throw ParseException("expected more elements in list", line, col); + throw SParseException("expected more elements in list", *this); } return list()[i]; } IString Element::str() const { if (!isStr()) { - throw ParseException("expected string", line, col); + throw SParseException("expected string", *this); } return str_; } std::string Element::toString() const { if (!isStr()) { - throw ParseException("expected string", line, col); + throw SParseException("expected string", *this); } return str_.toString(); } +std::string Element::forceString() const { + std::stringstream ss; + ss << *this; + // Limit the size to something reasonable for printing out. + return ss.str().substr(0, 80); +} + Element* Element::setString(IString str__, bool dollared__, bool quoted__) { isList_ = false; str_ = str__; @@ -119,7 +141,7 @@ Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) { return this; } -std::ostream& operator<<(std::ostream& o, Element& e) { +std::ostream& operator<<(std::ostream& o, const Element& e) { if (e.isList_) { o << '('; for (auto item : e.list_) { @@ -182,7 +204,7 @@ Element* SExpressionParser::parse() { } } if (stack.size() != 0) { - throw ParseException("stack is not empty", curr->line, curr->col); + throw SParseException("stack is not empty", *curr); } return curr; } @@ -416,8 +438,7 @@ void SExpressionWasmBuilder::preParseImports(Element& curr) { } else if (id == TAG) { parseTag(curr, true /* preParseImport */); } else { - throw ParseException( - "fancy import we don't support yet", curr.line, curr.col); + throw SParseException("fancy import we don't support yet", curr); } } } @@ -471,14 +492,14 @@ void SExpressionWasmBuilder::parseModuleElement(Element& curr) { return parseTag(curr); } std::cerr << "bad module element " << id.str << '\n'; - throw ParseException("unknown module element", curr.line, curr.col); + throw SParseException("unknown module element", curr); } int SExpressionWasmBuilder::parseIndex(Element& s) { try { return std::stoi(s.toString()); } catch (...) { - throw ParseException("expected integer", s.line, s.col); + throw SParseException("expected integer", s); } } @@ -489,8 +510,7 @@ Name SExpressionWasmBuilder::getFunctionName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= functionNames.size()) { - throw ParseException( - "unknown function in getFunctionName", s.line, s.col); + throw SParseException("unknown function in getFunctionName", s); } return functionNames[offset]; } @@ -503,7 +523,7 @@ Name SExpressionWasmBuilder::getTableName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= tableNames.size()) { - throw ParseException("unknown table in getTableName", s.line, s.col); + throw SParseException("unknown table in getTableName", s); } return tableNames[offset]; } @@ -516,7 +536,7 @@ Name SExpressionWasmBuilder::getElemSegmentName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= elemSegmentNames.size()) { - throw ParseException("unknown elem segment", s.line, s.col); + throw SParseException("unknown elem segment", s); } return elemSegmentNames[offset]; } @@ -525,14 +545,16 @@ Name SExpressionWasmBuilder::getElemSegmentName(Element& s) { bool SExpressionWasmBuilder::isMemory64(Name memoryName) { auto* memory = wasm.getMemoryOrNull(memoryName); if (!memory) { - throw ParseException("invalid memory name in isMemory64"); + throw ParseException("invalid memory name in isMemory64: "s + + memoryName.toString()); } return memory->is64(); } Name SExpressionWasmBuilder::getMemoryNameAtIdx(Index i) { if (i >= memoryNames.size()) { - throw ParseException("unknown memory in getMemoryName"); + throw ParseException("unknown memory in getMemoryName: "s + + std::to_string(i)); } return memoryNames[i]; } @@ -554,7 +576,7 @@ Name SExpressionWasmBuilder::getDataSegmentName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= dataSegmentNames.size()) { - throw ParseException("unknown data segment", s.line, s.col); + throw SParseException("unknown data segment", s); } return dataSegmentNames[offset]; } @@ -567,7 +589,7 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= globalNames.size()) { - throw ParseException("unknown global in getGlobalName", s.line, s.col); + throw SParseException("unknown global in getGlobalName", s); } return globalNames[offset]; } @@ -580,7 +602,7 @@ Name SExpressionWasmBuilder::getTagName(Element& s) { // index size_t offset = parseIndex(s); if (offset >= tagNames.size()) { - throw ParseException("unknown tag in getTagName", s.line, s.col); + throw SParseException("unknown tag in getTagName", s); } return tagNames[offset]; } @@ -616,10 +638,10 @@ SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) { IString name; if (s[i]->dollared()) { if (i != 1) { - throw ParseException("invalid wasm type", s[i]->line, s[i]->col); + throw SParseException("invalid wasm type", *s[i]); } if (i + 1 >= s.size()) { - throw ParseException("invalid param entry", s.line, s.col); + throw SParseException("invalid param entry", s); } name = s[i]->str(); i++; @@ -630,8 +652,7 @@ SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) { Type type; type = elementToType(*s[i]); if (elementStartsWith(s, PARAM) && type.isTuple()) { - throw ParseException( - "params may not have tuple types", s[i]->line, s[i]->col); + throw SParseException("params may not have tuple types", *s[i]); } namedParams.emplace_back(name, type); } @@ -654,11 +675,11 @@ std::vector<Type> SExpressionWasmBuilder::parseResults(Element& s) { HeapType SExpressionWasmBuilder::parseTypeRef(Element& s) { assert(elementStartsWith(s, TYPE)); if (s.size() != 2) { - throw ParseException("invalid type reference", s.line, s.col); + throw SParseException("invalid type reference", s); } auto heapType = parseHeapType(*s[1]); if (!heapType.isSignature()) { - throw ParseException("expected signature type", s.line, s.col); + throw SParseException("expected signature type", s); } return heapType; } @@ -715,9 +736,7 @@ SExpressionWasmBuilder::parseTypeUse(Element& s, } else if (paramsOrResultsExist) { // verify that (type) and (params)/(result) match if (inlineSig != functionType.getSignature()) { - throw ParseException("type and param/result don't match", - s[paramPos]->line, - s[paramPos]->col); + throw SParseException("type and param/result don't match", *s[paramPos]); } } @@ -774,7 +793,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { if (elem[1]->dollared()) { std::string name = elem[1]->toString(); if (!typeIndices.insert({name, numTypes}).second) { - throw ParseException("duplicate function type", elem.line, elem.col); + throw SParseException("duplicate function type", elem); } } ++numTypes; @@ -809,7 +828,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } else if (String::isNumber(name)) { size_t index = parseIndex(referent); if (index >= numTypes) { - throw ParseException("invalid type index", elem.line, elem.col); + throw SParseException("invalid type index", elem); } return builder.getTempRefType(builder[index], nullable); } else { @@ -823,7 +842,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } else if (*elem[0] == REF) { return parseRefType(elem); } else { - throw ParseException("unknown valtype kind", elem[0]->line, elem[0]->col); + throw SParseException("unknown valtype kind", elem); } }; @@ -937,11 +956,10 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } Element& subtype = *def[i++]; if (i != def.size()) { - throw ParseException("invalid 'sub' form", kind.line, kind.col); + throw SParseException("invalid 'sub' form", kind); } if (!subtype.isList() || subtype.size() < 1) { - throw ParseException( - "invalid subtype definition", subtype.line, subtype.col); + throw SParseException("invalid subtype definition", subtype); } Element& subtypeKind = *subtype[0]; if (subtypeKind == FUNC) { @@ -951,8 +969,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } else if (subtypeKind == ARRAY) { builder[index] = parseArrayDef(subtype); } else { - throw ParseException( - "unknown subtype kind", subtypeKind.line, subtypeKind.col); + throw SParseException("unknown subtype kind", subtypeKind); } } else { if (kind == FUNC) { @@ -962,13 +979,13 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } else if (kind == ARRAY) { builder[index] = parseArrayDef(def); } else { - throw ParseException("unknown heaptype kind", kind.line, kind.col); + throw SParseException("unknown heaptype kind", kind); } } if (super) { auto it = typeIndices.find(super->toString()); if (!super->dollared() || it == typeIndices.end()) { - throw ParseException("unknown supertype", super->line, super->col); + throw SParseException("unknown supertype", elem, *super); } builder[index].subTypeOf(builder[it->second]); } @@ -1079,7 +1096,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { ex->value = name; ex->kind = ExternalKind::Function; if (wasm.getExportOrNull(ex->name)) { - throw ParseException("duplicate export", s.line, s.col); + throw SParseException("duplicate export", s); } wasm.addExport(ex.release()); } @@ -1102,10 +1119,10 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { // but an import. if (importModule.is()) { if (!importBase.size()) { - throw ParseException("module but no base for import", s.line, s.col); + throw SParseException("module but no base for import", s); } if (!preParseImport) { - throw ParseException("!preParseImport in func", s.line, s.col); + throw SParseException("!preParseImport in func", s); } auto im = std::make_unique<Function>(); im->setName(name, hasExplicitName); @@ -1114,18 +1131,18 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { im->type = type; functionTypes[name] = type; if (wasm.getFunctionOrNull(im->name)) { - throw ParseException("duplicate import", s.line, s.col); + throw SParseException("duplicate import", s); } wasm.addFunction(std::move(im)); if (currFunction) { - throw ParseException("import module inside function dec", s.line, s.col); + throw SParseException("import module inside function dec", s); } nameMapper.clear(); return; } // at this point this not an import but a real function definition. if (preParseImport) { - throw ParseException("preParseImport in func", s.line, s.col); + throw SParseException("preParseImport in func", s); } size_t localIndex = params.size(); // local index for params and locals @@ -1178,7 +1195,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { currFunction->epilogLocation.insert(getDebugLocation(*s.endLoc)); } if (wasm.getFunctionOrNull(currFunction->name)) { - throw ParseException("duplicate function", s.line, s.col); + throw SParseException("duplicate function", s); } wasm.addFunction(currFunction.release()); nameMapper.clear(); @@ -1324,12 +1341,10 @@ Type SExpressionWasmBuilder::elementToType(Element& s) { // and also $name can be the expanded structure of the type and not a name, // so something like (ref (func (result i32))), etc. if (size != 2 && size != 3) { - throw ParseException( - std::string("invalid reference type size"), s.line, s.col); + throw SParseException(std::string("invalid reference type size"), s); } if (size == 3 && *list[1] != NULL_) { - throw ParseException( - std::string("invalid reference type qualifier"), s.line, s.col); + throw SParseException(std::string("invalid reference type qualifier"), s); } Nullability nullable = NonNullable; size_t i = 1; @@ -1372,8 +1387,7 @@ Type SExpressionWasmBuilder::stringToLaneType(const char* str) { HeapType SExpressionWasmBuilder::getFunctionType(Name name, Element& s) { auto iter = functionTypes.find(name); if (iter == functionTypes.end()) { - throw ParseException( - "invalid call target: " + std::string(name.str), s.line, s.col); + throw SParseException("invalid call target: " + std::string(name.str), s); } return iter->second; } @@ -1487,19 +1501,19 @@ Expression* SExpressionWasmBuilder::makeMemoryGrow(Element& s) { Index SExpressionWasmBuilder::getLocalIndex(Element& s) { if (!currFunction) { - throw ParseException("local access in non-function scope", s.line, s.col); + throw SParseException("local access in non-function scope", s); } if (s.dollared()) { auto ret = s.str(); if (currFunction->localIndices.count(ret) == 0) { - throw ParseException("bad local name", s.line, s.col); + throw SParseException("bad local name", s); } return currFunction->getLocalIndex(ret); } // this is a numeric index Index ret = parseIndex(s); if (ret >= currFunction->getNumLocals()) { - throw ParseException("bad local index", s.line, s.col); + throw SParseException("bad local index", s); } return ret; } @@ -1534,7 +1548,7 @@ Expression* SExpressionWasmBuilder::makeGlobalGet(Element& s) { ret->name = getGlobalName(*s[1]); auto* global = wasm.getGlobalOrNull(ret->name); if (!global) { - throw ParseException("bad global.get name", s.line, s.col); + throw SParseException("bad global.get name", s); } ret->type = global->type; return ret; @@ -1545,7 +1559,7 @@ Expression* SExpressionWasmBuilder::makeGlobalSet(Element& s) { ret->name = getGlobalName(*s[1]); if (wasm.getGlobalOrNull(ret->name) && !wasm.getGlobalOrNull(ret->name)->mutable_) { - throw ParseException("global.set of immutable", s.line, s.col); + throw SParseException("global.set of immutable", s); } ret->value = parseExpression(s[2]); ret->finalize(); @@ -1554,8 +1568,7 @@ Expression* SExpressionWasmBuilder::makeGlobalSet(Element& s) { Expression* SExpressionWasmBuilder::makeBlock(Element& s) { if (!currFunction) { - throw ParseException( - "block is unallowed outside of functions", s.line, s.col); + throw SParseException("block is unallowed outside of functions", s); } // special-case Block, because Block nesting (in their first element) can be // incredibly deep @@ -1713,7 +1726,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { if (positive[0] == 'n' && positive[1] == 'a' && positive[2] == 'n') { const char* modifier = positive[3] == ':' ? positive + 4 : nullptr; if (!(modifier ? positive[4] == '0' && positive[5] == 'x' : 1)) { - throw ParseException("bad nan input"); + throw ParseException("bad nan input: "s + str); } switch (type.getBasic()) { case Type::f32: { @@ -1722,7 +1735,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { std::istringstream istr(modifier); istr >> std::hex >> pattern; if (istr.fail()) { - throw ParseException("invalid f32 format"); + throw ParseException("invalid f32 format: "s + str); } pattern |= 0x7f800000U; } else { @@ -1743,7 +1756,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { std::istringstream istr(modifier); istr >> std::hex >> pattern; if (istr.fail()) { - throw ParseException("invalid f64 format"); + throw ParseException("invalid f64 format: "s + str); } pattern |= 0x7ff0000000000000ULL; } else { @@ -1791,7 +1804,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { uint32_t temp; istr >> std::hex >> temp; if (istr.fail()) { - throw ParseException("invalid i32 format"); + throw ParseException("invalid i32 format: "s + str); } ret->value = Literal(negative ? -temp : temp); } else { @@ -1799,7 +1812,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { uint32_t temp; istr >> temp; if (istr.fail()) { - throw ParseException("invalid i32 format"); + throw ParseException("invalid i32 format: "s + str); } ret->value = Literal(str[0] == '-' ? -temp : temp); } @@ -1816,7 +1829,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { uint64_t temp; istr >> std::hex >> temp; if (istr.fail()) { - throw ParseException("invalid i64 format"); + throw ParseException("invalid i64 format: "s + str); } ret->value = Literal(negative ? -temp : temp); } else { @@ -1824,7 +1837,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { uint64_t temp; istr >> temp; if (istr.fail()) { - throw ParseException("invalid i64 format"); + throw ParseException("invalid i64 format: "s + str); } ret->value = Literal(str[0] == '-' ? -temp : temp); } @@ -1848,7 +1861,7 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { } } if (ret->value.type != type) { - throw ParseException("parsed type does not match expected type"); + throw ParseException("parsed type does not match expected type: "s + str); } return ret; } @@ -1861,8 +1874,7 @@ static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) { if (lane) { lanes[i] = lane->cast<Const>()->value; } else { - throw ParseException( - "Could not parse v128 lane", s[i + 2]->line, s[i + 2]->col); + throw SParseException("Could not parse v128 lane", s, *s[i + 2]); } } return Literal(lanes); @@ -1872,7 +1884,7 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) { if (type != Type::v128) { auto ret = parseConst(s[1]->str(), type, allocator); if (!ret) { - throw ParseException("bad const", s[1]->line, s[1]->col); + throw SParseException("bad const", s, *s[1]); } return ret; } @@ -1883,39 +1895,34 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) { switch (lanes) { case 2: { if (lane_t != Type::i64 && lane_t != Type::f64) { - throw ParseException( - "Unexpected v128 literal lane type", s[1]->line, s[1]->col); + throw SParseException("Unexpected v128 literal lane type", s); } ret->value = makeLanes<2>(s, allocator, lane_t); break; } case 4: { if (lane_t != Type::i32 && lane_t != Type::f32) { - throw ParseException( - "Unexpected v128 literal lane type", s[1]->line, s[1]->col); + throw SParseException("Unexpected v128 literal lane type", s); } ret->value = makeLanes<4>(s, allocator, lane_t); break; } case 8: { if (lane_t != Type::i32) { - throw ParseException( - "Unexpected v128 literal lane type", s[1]->line, s[1]->col); + throw SParseException("Unexpected v128 literal lane type", s); } ret->value = makeLanes<8>(s, allocator, lane_t); break; } case 16: { if (lane_t != Type::i32) { - throw ParseException( - "Unexpected v128 literal lane type", s[1]->line, s[1]->col); + throw SParseException("Unexpected v128 literal lane type", s); } ret->value = makeLanes<16>(s, allocator, lane_t); break; } default: - throw ParseException( - "Unexpected number of lanes in v128 literal", s[1]->line, s[1]->col); + throw SParseException("Unexpected number of lanes in v128 literal", s); } ret->finalize(); return ret; @@ -1934,32 +1941,29 @@ static size_t parseMemAttributes(size_t i, } const char* eq = strchr(str, '='); if (!eq) { - throw ParseException( - "missing = in memory attribute", s[i]->line, s[i]->col); + throw SParseException("missing = in memory attribute", s); } eq++; if (*eq == 0) { - throw ParseException( - "missing value in memory attribute", s[i]->line, s[i]->col); + throw SParseException("missing value in memory attribute", s); } char* endptr; uint64_t value = strtoll(eq, &endptr, 10); if (*endptr != 0) { - throw ParseException( - "bad memory attribute immediate", s[i]->line, s[i]->col); + throw SParseException("bad memory attribute immediate", s); } if (str[0] == 'a') { if (value > std::numeric_limits<uint32_t>::max()) { - throw ParseException("bad align", s[i]->line, s[i]->col); + throw SParseException("bad align", s); } align = value; } else if (str[0] == 'o') { if (!memory64 && value > std::numeric_limits<uint32_t>::max()) { - throw ParseException("bad offset", s[i]->line, s[i]->col); + throw SParseException("bad offset", s); } offset = value; } else { - throw ParseException("bad memory attribute", s[i]->line, s[i]->col); + throw SParseException("bad memory attribute", s); } i++; } @@ -2051,7 +2055,7 @@ Expression* SExpressionWasmBuilder::makeAtomicRMW(Element& s, Address align = bytes; i = parseMemAttributes(i, s, ret->offset, align, isMemory64(memory)); if (align != ret->bytes) { - throw ParseException("Align of Atomic RMW must match size", s.line, s.col); + throw SParseException("Align of Atomic RMW must match size", s); } ret->ptr = parseExpression(s[i]); ret->value = parseExpression(s[i + 1]); @@ -2079,8 +2083,7 @@ Expression* SExpressionWasmBuilder::makeAtomicCmpxchg(Element& s, Address align = ret->bytes; i = parseMemAttributes(i, s, ret->offset, align, isMemory64(memory)); if (align != ret->bytes) { - throw ParseException( - "Align of Atomic Cmpxchg must match size", s.line, s.col); + throw SParseException("Align of Atomic Cmpxchg must match size", s); } ret->ptr = parseExpression(s[i]); ret->expected = parseExpression(s[i + 1]); @@ -2108,8 +2111,7 @@ Expression* SExpressionWasmBuilder::makeAtomicWait(Element& s, Type type) { Address align = expectedAlign; i = parseMemAttributes(i, s, ret->offset, align, isMemory64(memory)); if (align != expectedAlign) { - throw ParseException( - "Align of memory.atomic.wait must match size", s.line, s.col); + throw SParseException("Align of memory.atomic.wait must match size", s); } ret->ptr = parseExpression(s[i]); ret->expected = parseExpression(s[i + 1]); @@ -2135,8 +2137,7 @@ Expression* SExpressionWasmBuilder::makeAtomicNotify(Element& s) { Address align = 4; i = parseMemAttributes(i, s, ret->offset, align, isMemory64(memory)); if (align != 4) { - throw ParseException( - "Align of memory.atomic.notify must be 4", s.line, s.col); + throw SParseException("Align of memory.atomic.notify must be 4", s); } ret->ptr = parseExpression(s[i]); ret->notifyCount = parseExpression(s[i + 1]); @@ -2153,11 +2154,11 @@ static uint8_t parseLaneIndex(const Element* s, size_t lanes) { char* end; auto n = static_cast<unsigned long long>(strtoll(str, &end, 10)); if (end == str || *end != '\0') { - throw ParseException("Expected lane index", s->line, s->col); + throw SParseException("Expected lane index", *s); } if (n > lanes) { - throw ParseException( - "lane index must be less than " + std::to_string(lanes), s->line, s->col); + throw SParseException( + "lane index must be less than " + std::to_string(lanes), *s); } return uint8_t(n); } @@ -2459,7 +2460,7 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s, bool isReturn) { Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s, bool isReturn) { if (wasm.tables.empty()) { - throw ParseException("no tables", s.line, s.col); + throw SParseException("no tables", s); } Index i = 1; auto ret = allocator.alloc<CallIndirect>(); @@ -2487,12 +2488,12 @@ Name SExpressionWasmBuilder::getLabel(Element& s, LabelType labelType) { try { offset = std::stoll(s.toString(), nullptr, 0); } catch (std::invalid_argument&) { - throw ParseException("invalid break offset", s.line, s.col); + throw SParseException("invalid break offset", s); } catch (std::out_of_range&) { - throw ParseException("out of range break offset", s.line, s.col); + throw SParseException("out of range break offset", s); } if (offset > nameMapper.labelStack.size()) { - throw ParseException("invalid label", s.line, s.col); + throw SParseException("invalid label", s); } if (offset == nameMapper.labelStack.size()) { if (labelType == LabelType::Break) { @@ -2536,7 +2537,7 @@ Expression* SExpressionWasmBuilder::makeBreakTable(Element& s) { ret->targets.push_back(getLabel(*s[i++])); } if (ret->targets.size() == 0) { - throw ParseException("switch with no targets", s.line, s.col); + throw SParseException("switch with no targets", s); } ret->default_ = ret->targets.back(); ret->targets.pop_back(); @@ -2558,7 +2559,7 @@ Expression* SExpressionWasmBuilder::makeReturn(Element& s) { Expression* SExpressionWasmBuilder::makeRefNull(Element& s) { if (s.size() != 2) { - throw ParseException("invalid heap type reference", s.line, s.col); + throw SParseException("invalid heap type reference", s); } auto ret = allocator.alloc<RefNull>(); // The heap type may be just "func", that is, the whole thing is just @@ -2602,7 +2603,7 @@ Expression* SExpressionWasmBuilder::makeTableGet(Element& s) { auto* index = parseExpression(s[2]); auto* table = wasm.getTableOrNull(tableName); if (!table) { - throw ParseException("invalid table name in table.get", s.line, s.col); + throw SParseException("invalid table name in table.get", s); } return Builder(wasm).makeTableGet(tableName, index, table->type); } @@ -2611,7 +2612,7 @@ Expression* SExpressionWasmBuilder::makeTableSet(Element& s) { auto tableName = s[1]->str(); auto* table = wasm.getTableOrNull(tableName); if (!table) { - throw ParseException("invalid table name in table.set", s.line, s.col); + throw SParseException("invalid table name in table.set", s); } auto* index = parseExpression(s[2]); auto* value = parseExpression(s[3]); @@ -2622,7 +2623,7 @@ Expression* SExpressionWasmBuilder::makeTableSize(Element& s) { auto tableName = s[1]->str(); auto* table = wasm.getTableOrNull(tableName); if (!table) { - throw ParseException("invalid table name in table.size", s.line, s.col); + throw SParseException("invalid table name in table.size", s); } return Builder(wasm).makeTableSize(tableName); } @@ -2631,11 +2632,11 @@ Expression* SExpressionWasmBuilder::makeTableGrow(Element& s) { auto tableName = s[1]->str(); auto* table = wasm.getTableOrNull(tableName); if (!table) { - throw ParseException("invalid table name in table.grow", s.line, s.col); + throw SParseException("invalid table name in table.grow", s); } auto* value = parseExpression(s[2]); if (!value->type.isRef()) { - throw ParseException("only reference types are valid for tables"); + throw SParseException("only reference types are valid for tables", s); } auto* delta = parseExpression(s[3]); return Builder(wasm).makeTableGrow(tableName, value, delta); @@ -2645,7 +2646,7 @@ Expression* SExpressionWasmBuilder::makeTableFill(Element& s) { auto tableName = s[1]->str(); auto* table = wasm.getTableOrNull(tableName); if (!table) { - throw ParseException("invalid table name in table.fill", s.line, s.col); + throw SParseException("invalid table name in table.fill", s); } auto* dest = parseExpression(s[2]); auto* value = parseExpression(s[3]); @@ -2692,19 +2693,18 @@ Expression* SExpressionWasmBuilder::makeTry(Element& s) { Type type = parseOptionalResultType(s, i); // signature if (!elementStartsWith(*s[i], "do")) { - throw ParseException( - "try body should start with 'do'", s[i]->line, s[i]->col); + throw SParseException("try body should start with 'do'", s, *s[i]); } ret->body = makeMaybeBlock(*s[i++], 1, type); while (i < s.size() && elementStartsWith(*s[i], "catch")) { Element& inner = *s[i++]; if (inner.size() < 2) { - throw ParseException("invalid catch block", inner.line, inner.col); + throw SParseException("invalid catch block", s, inner); } Name tag = getTagName(*inner[1]); if (!wasm.getTagOrNull(tag)) { - throw ParseException("bad tag name", inner[1]->line, inner[1]->col); + throw SParseException("bad tag name", s, inner); } ret->catchTags.push_back(getTagName(*inner[1])); ret->catchBodies.push_back(makeMaybeBlock(inner, 2, type)); @@ -2720,14 +2720,14 @@ Expression* SExpressionWasmBuilder::makeTry(Element& s) { if (i < s.size() && elementStartsWith(*s[i], "delegate")) { Element& inner = *s[i++]; if (inner.size() != 2) { - throw ParseException("invalid delegate", inner.line, inner.col); + throw SParseException("invalid delegate", s, inner); } ret->delegateTarget = getLabel(*inner[1], LabelType::Exception); } if (i != s.size()) { - throw ParseException( - "there should be at most one catch_all block at the end", s.line, s.col); + throw SParseException( + "there should be at most one catch_all block at the end", s); } ret->finalize(type); @@ -2755,7 +2755,7 @@ Expression* SExpressionWasmBuilder::makeThrow(Element& s) { ret->tag = getTagName(*s[i++]); if (!wasm.getTagOrNull(ret->tag)) { - throw ParseException("bad tag name", s[1]->line, s[1]->col); + throw SParseException("bad tag name", s, *s[i]); } for (; i < s.size(); i++) { ret->operands.push_back(parseExpression(s[i])); @@ -2784,7 +2784,7 @@ Expression* SExpressionWasmBuilder::makeTupleExtract(Element& s) { ret->tuple = parseExpression(s[2]); if (ret->tuple->type != Type::unreachable && ret->index >= ret->tuple->type.size()) { - throw ParseException("Bad index on tuple.extract", s[1]->line, s[1]->col); + throw SParseException("Bad index on tuple.extract", s, *s[1]); } ret->finalize(); return ret; @@ -2797,18 +2797,16 @@ Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { auto* target = parseExpression(s[s.size() - 1]); if (!sigType.isSignature()) { - throw ParseException( + throw SParseException( std::string(isReturn ? "return_call_ref" : "call_ref") + " type annotation should be a signature", - s.line, - s.col); + s); } if (!Type::isSubType(target->type, Type(sigType, Nullable))) { - throw ParseException( + throw SParseException( std::string(isReturn ? "return_call_ref" : "call_ref") + " target should match expected type", - s.line, - s.col); + s); } return Builder(wasm).makeCallRef( target, operands, sigType.getSignature().results, isReturn); @@ -2855,15 +2853,13 @@ Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s, bool onFail) { auto inputType = elementToType(*s[i++]); auto castType = elementToType(*s[i++]); if (!Type::isSubType(castType, inputType)) { - throw ParseException( - "br_on_cast* cast type must be a subtype of its input type", - s.line, - s.col); + throw SParseException( + "br_on_cast* cast type must be a subtype of its input type", s); } auto* ref = parseExpression(*s[i]); if (!Type::isSubType(ref->type, inputType)) { - throw ParseException( - "br_on_cast* ref type does not match expected type", s.line, s.col); + throw SParseException("br_on_cast* ref type does not match expected type", + s); } auto op = onFail ? BrOnCastFail : BrOnCast; return Builder(wasm).makeBrOn(op, name, ref, castType); @@ -2873,7 +2869,7 @@ Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); auto numOperands = s.size() - 2; if (default_ && numOperands > 0) { - throw ParseException("arguments provided for struct.new", s.line, s.col); + throw SParseException("arguments provided for struct.new", s); } std::vector<Expression*> operands; operands.resize(numOperands); @@ -2896,7 +2892,7 @@ Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) { return i; } } - throw ParseException("bad struct field name", field.line, field.col); + throw SParseException("bad struct field name", field); } // this is a numeric index return parseIndex(field); @@ -2905,7 +2901,7 @@ Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) { Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { auto heapType = parseHeapType(*s[1]); if (!heapType.isStruct()) { - throw ParseException("bad struct heap type", s.line, s.col); + throw SParseException("bad struct heap type", s); } auto index = getStructIndex(*s[1], *s[2]); auto type = heapType.getStruct().fields[index].type; @@ -2917,7 +2913,7 @@ Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { auto heapType = parseHeapType(*s[1]); if (!heapType.isStruct()) { - throw ParseException("bad struct heap type", s.line, s.col); + throw SParseException("bad struct heap type", s); } auto index = getStructIndex(*s[1], *s[2]); auto ref = parseExpression(*s[3]); @@ -2961,7 +2957,7 @@ Expression* SExpressionWasmBuilder::makeArrayNewFixed(Element& s) { // With the standard syntax one should specify explicitly the size // of the array if ((size_t)parseIndex(*s[i]) != s.size() - 3) { - throw ParseException("wrong number of elements in array", s.line, s.col); + throw SParseException("wrong number of elements in array", s); } i++; } @@ -2974,7 +2970,7 @@ Expression* SExpressionWasmBuilder::makeArrayNewFixed(Element& s) { Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) { auto heapType = parseHeapType(*s[1]); if (!heapType.isArray()) { - throw ParseException("bad array heap type", s.line, s.col); + throw SParseException("bad array heap type", s); } auto ref = parseExpression(*s[2]); auto type = heapType.getArray().element.type; @@ -3053,7 +3049,7 @@ Expression* SExpressionWasmBuilder::makeArrayInitElem(Element& s) { Expression* SExpressionWasmBuilder::makeRefAs(Element& s, RefAsOp op) { auto* value = parseExpression(s[1]); if (!value->type.isRef() && value->type != Type::unreachable) { - throw ParseException("ref.as child must be a ref", s.line, s.col); + throw SParseException("ref.as child must be a ref", s); } return Builder(wasm).makeRefAs(op, value); } @@ -3073,7 +3069,7 @@ SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op, bool try_) { } else if (str == "replace") { op = StringNewLossyUTF8; } else { - throw ParseException("bad string.new op", s.line, s.col); + throw SParseException("bad string.new op", s); } } length = parseExpression(s[i + 1]); @@ -3093,7 +3089,7 @@ SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op, bool try_) { } else if (str == "replace") { op = StringNewLossyUTF8Array; } else { - throw ParseException("bad string.new op", s.line, s.col); + throw SParseException("bad string.new op", s); } } auto* start = parseExpression(s[i + 1]); @@ -3110,7 +3106,7 @@ SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op, bool try_) { return Builder(wasm).makeStringNew( op, parseExpression(s[i]), nullptr, try_); } else { - throw ParseException("bad string.new op", s.line, s.col); + throw SParseException("bad string.new op", s); } } @@ -3132,7 +3128,7 @@ Expression* SExpressionWasmBuilder::makeStringMeasure(Element& s, } else if (str == "wtf8") { op = StringMeasureWTF8; } else { - throw ParseException("bad string.measure op", s.line, s.col); + throw SParseException("bad string.measure op", s); } } return Builder(wasm).makeStringMeasure(op, parseExpression(s[i])); @@ -3153,7 +3149,7 @@ Expression* SExpressionWasmBuilder::makeStringEncode(Element& s, } else if (str == "wtf8") { op = StringEncodeWTF8; } else { - throw ParseException("bad string.new op", s.line, s.col); + throw SParseException("bad string.new op", s); } } } else if (op == StringEncodeWTF8Array) { @@ -3167,7 +3163,7 @@ Expression* SExpressionWasmBuilder::makeStringEncode(Element& s, } else if (str == "wtf8") { op = StringEncodeWTF8Array; } else { - throw ParseException("bad string.new op", s.line, s.col); + throw SParseException("bad string.new op", s); } } start = parseExpression(s[i + 2]); @@ -3237,7 +3233,7 @@ void SExpressionWasmBuilder::stringToBinary(Element& s, for (const char* input = str.data(); input < end;) { if (input[0] == '\\') { if (input + 1 >= end) { - throw ParseException("Unterminated escape sequence", s.line, s.col); + throw SParseException("Unterminated escape sequence", s); } if (input[1] == 't') { *write++ = '\t'; @@ -3265,7 +3261,7 @@ void SExpressionWasmBuilder::stringToBinary(Element& s, continue; } else { if (input + 2 >= end) { - throw ParseException("Unterminated escape sequence", s.line, s.col); + throw SParseException("Unterminated escape sequence", s); } *write++ = (char)(unhex(input[1]) * 16 + unhex(input[2])); input += 3; @@ -3299,7 +3295,7 @@ Index SExpressionWasmBuilder::parseMemoryLimits( Element& s, Index i, std::unique_ptr<Memory>& memory) { i = parseMemoryIndex(s, i, memory); if (i == s.size()) { - throw ParseException("missing memory limits", s.line, s.col); + throw SParseException("missing memory limits", s); } auto initElem = s[i++]; memory->initial = getAddress(initElem); @@ -3312,8 +3308,7 @@ Index SExpressionWasmBuilder::parseMemoryLimits( auto maxElem = s[i++]; memory->max = getAddress(maxElem); if (!memory->is64() && memory->max > Memory::kMaxSize32) { - throw ParseException( - "total memory must be <= 4GB", maxElem->line, maxElem->col); + throw SParseException("total memory must be <= 4GB", s, *maxElem); } } return i; @@ -3340,7 +3335,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { ex->value = memory->name; ex->kind = ExternalKind::Memory; if (wasm.getExportOrNull(ex->name)) { - throw ParseException("duplicate export", inner.line, inner.col); + throw SParseException("duplicate export", inner); } wasm.addExport(ex.release()); i++; @@ -3354,7 +3349,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { i++; } else { if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true)) { - throw ParseException("bad import ending", inner.line, inner.col); + throw SParseException("bad import ending", inner); } // (memory (data ..)) format auto j = parseMemoryIndex(inner, 1, memory); @@ -3495,7 +3490,7 @@ void SExpressionWasmBuilder::parseExport(Element& s) { ex->kind = ExternalKind::Tag; ex->value = getTagName(*inner[1]); } else { - throw ParseException("invalid export", inner.line, inner.col); + throw SParseException("invalid export", inner); } } else { // function @@ -3503,7 +3498,7 @@ void SExpressionWasmBuilder::parseExport(Element& s) { ex->kind = ExternalKind::Function; } if (wasm.getExportOrNull(ex->name)) { - throw ParseException("duplicate export", s.line, s.col); + throw SParseException("duplicate export", s); } wasm.addExport(ex.release()); } @@ -3551,7 +3546,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) { name = Name("eimport$" + std::to_string(tagCounter++)); tagNames.push_back(name); } else { - throw ParseException("invalid import", s[3]->line, s[3]->col); + throw SParseException("invalid import", s); } } if (!newStyle) { @@ -3559,12 +3554,11 @@ void SExpressionWasmBuilder::parseImport(Element& s) { } auto module = s[i++]->str(); if (!s[i]->isStr()) { - throw ParseException("no name for import", s[i]->line, s[i]->col); + throw SParseException("no name for import", s, *s[i]); } auto base = s[i]->str(); if (!module.size() || !base.size()) { - throw ParseException( - "imports must have module and base", s[i]->line, s[i]->col); + throw SParseException("imports must have module and base", s, *s[i]); } i++; // parse internals @@ -3619,8 +3613,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) { if (inner[j]->isList()) { auto& limits = *inner[j]; if (!elementStartsWith(limits, SHARED)) { - throw ParseException( - "bad memory limit declaration", inner[j]->line, inner[j]->col); + throw SParseException("bad memory limit declaration", inner, *inner[j]); } memory->shared = true; j = parseMemoryLimits(limits, 1, memory); @@ -3641,7 +3634,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) { } // If there are more elements, they are invalid if (j < inner.size()) { - throw ParseException("invalid element", inner[j]->line, inner[j]->col); + throw SParseException("invalid element", inner, *inner[j]); } } @@ -3668,7 +3661,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { ex->value = global->name; ex->kind = ExternalKind::Global; if (wasm.getExportOrNull(ex->name)) { - throw ParseException("duplicate export", s.line, s.col); + throw SParseException("duplicate export", s); } wasm.addExport(ex.release()); } else if (elementStartsWith(inner, IMPORT)) { @@ -3689,10 +3682,10 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { if (importModule.is()) { // this is an import, actually if (!importBase.size()) { - throw ParseException("module but no base for import", s.line, s.col); + throw SParseException("module but no base for import", s); } if (!preParseImport) { - throw ParseException("!preParseImport in global", s.line, s.col); + throw SParseException("!preParseImport in global", s); } auto im = std::make_unique<Global>(); im->name = global->name; @@ -3701,7 +3694,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { im->type = type; im->mutable_ = mutable_; if (wasm.getGlobalOrNull(im->name)) { - throw ParseException("duplicate import", s.line, s.col); + throw SParseException("duplicate import", s); } wasm.addGlobal(im.release()); return; @@ -3710,14 +3703,14 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { if (i < s.size()) { global->init = parseExpression(s[i++]); } else if (!preParseImport) { - throw ParseException("global without init", s.line, s.col); + throw SParseException("global without init", s); } global->mutable_ = mutable_; if (i != s.size()) { - throw ParseException("extra import elements", s.line, s.col); + throw SParseException("extra import elements", s); } if (wasm.getGlobalOrNull(global->name)) { - throw ParseException("duplicate import", s.line, s.col); + throw SParseException("duplicate import", s); } wasm.addGlobal(global.release()); } @@ -3741,19 +3734,19 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { ex->value = table->name; ex->kind = ExternalKind::Table; if (wasm.getExportOrNull(ex->name)) { - throw ParseException("duplicate export", inner.line, inner.col); + throw SParseException("duplicate export", inner); } wasm.addExport(ex.release()); i++; } else if (elementStartsWith(inner, IMPORT)) { if (!preParseImport) { - throw ParseException("!preParseImport in table", inner.line, inner.col); + throw SParseException("!preParseImport in table", inner); } table->module = inner[1]->str(); table->base = inner[2]->str(); i++; } else if (!elementStartsWith(inner, REF)) { - throw ParseException("invalid table", inner.line, inner.col); + throw SParseException("invalid table", inner); } } @@ -3769,13 +3762,13 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { table->type = elementToType(*s[i++]); if (!table->type.isRef()) { - throw ParseException("Only reference types are valid for tables"); + throw SParseException("Only reference types are valid for tables", s); } if (i < s.size() && s[i]->isList()) { if (hasExplicitLimit) { - throw ParseException( - "Table cannot have both explicit limits and an inline (elem ...)"); + throw SParseException( + "Table cannot have both explicit limits and an inline (elem ...)", s); } // (table type (elem ..)) parseElem(*s[i], table.get()); @@ -3848,8 +3841,8 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) { auto& inner = *s[i++]; if (elementStartsWith(inner, OFFSET)) { if (inner.size() > 2) { - throw ParseException( - "Invalid offset for an element segment.", s.line, s.col); + throw SParseException( + "Invalid offset for an element segment.", s, *s[i]); } segment->offset = parseExpression(inner[1]); } else { @@ -3873,7 +3866,7 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) { if (!isPassive && segment->table.isNull()) { if (wasm.tables.empty()) { - throw ParseException("active element without table", s.line, s.col); + throw SParseException("active element without table", s); } table = wasm.tables.front().get(); segment->table = table->name; @@ -3902,7 +3895,7 @@ ElementSegment* SExpressionWasmBuilder::parseElemFinish( continue; } if (!usesExpressions) { - throw ParseException("expected an MVP-style $funcname in elem."); + throw SParseException("expected an MVP-style $funcname in elem.", s); } auto& inner = *s[i]; if (elementStartsWith(inner, ITEM)) { @@ -3927,7 +3920,7 @@ HeapType SExpressionWasmBuilder::parseHeapType(Element& s) { if (s.dollared()) { auto it = typeIndices.find(s.toString()); if (it == typeIndices.end()) { - throw ParseException("unknown dollared function type", s.line, s.col); + throw SParseException("unknown dollared function type", s); } return types[it->second]; } else { @@ -3937,14 +3930,14 @@ HeapType SExpressionWasmBuilder::parseHeapType(Element& s) { if (String::isNumber(str)) { size_t offset = parseIndex(s); if (offset >= types.size()) { - throw ParseException("unknown indexed function type", s.line, s.col); + throw SParseException("unknown indexed function type", s); } return types[offset]; } return stringToHeapType(s.str(), /* prefix = */ false); } } - throw ParseException("invalid heap type", s.line, s.col); + throw SParseException("invalid heap type", s); } void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { @@ -3956,7 +3949,7 @@ void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { auto& inner = *s[i++]; tag->setExplicitName(inner.str()); if (wasm.getTagOrNull(tag->name)) { - throw ParseException("duplicate tag", inner.line, inner.col); + throw SParseException("duplicate tag", inner); } } else { tag->name = Name::fromInt(tagCounter); @@ -3970,15 +3963,13 @@ void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { assert(preParseImport && "import element in non-preParseImport mode"); auto& importElem = *s[i++]; if (importElem.size() != 3) { - throw ParseException("invalid import", importElem.line, importElem.col); + throw SParseException("invalid import", importElem); } if (!importElem[1]->isStr() || importElem[1]->dollared()) { - throw ParseException( - "invalid import module name", importElem[1]->line, importElem[1]->col); + throw SParseException("invalid import module name", importElem); } if (!importElem[2]->isStr() || importElem[2]->dollared()) { - throw ParseException( - "invalid import base name", importElem[2]->line, importElem[2]->col); + throw SParseException("invalid import base name", importElem); } tag->module = importElem[1]->str(); tag->base = importElem[2]->str(); @@ -3988,22 +3979,19 @@ void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { if (i < s.size() && elementStartsWith(*s[i], EXPORT)) { auto& exportElem = *s[i++]; if (tag->module.is()) { - throw ParseException("import and export cannot be specified together", - exportElem.line, - exportElem.col); + throw SParseException("import and export cannot be specified together", + exportElem); } if (exportElem.size() != 2) { - throw ParseException("invalid export", exportElem.line, exportElem.col); + throw SParseException("invalid export", exportElem); } if (!exportElem[1]->isStr() || exportElem[1]->dollared()) { - throw ParseException( - "invalid export name", exportElem[1]->line, exportElem[1]->col); + throw SParseException("invalid export name", exportElem); } auto ex = std::make_unique<Export>(); ex->name = exportElem[1]->str(); if (wasm.getExportOrNull(ex->name)) { - throw ParseException( - "duplicate export", exportElem[1]->line, exportElem[1]->col); + throw SParseException("duplicate export", exportElem); } ex->value = tag->name; ex->kind = ExternalKind::Tag; @@ -4017,7 +4005,7 @@ void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { // If there are more elements, they are invalid if (i < s.size()) { - throw ParseException("invalid element", s[i]->line, s[i]->col); + throw SParseException("invalid element", *s[i]); } wasm.addTag(tag.release()); @@ -4031,10 +4019,9 @@ void SExpressionWasmBuilder::validateHeapTypeUsingChild(Expression* child, } if (!child->type.isRef() || !HeapType::isSubType(child->type.getHeapType(), heapType)) { - throw ParseException("bad heap type: expected " + heapType.toString() + - " but found " + child->type.toString(), - s.line, - s.col); + throw SParseException("bad heap type: expected " + heapType.toString() + + " but found " + child->type.toString(), + s); } } |