summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-09-28 12:07:39 -0700
committerGitHub <noreply@github.com>2023-09-28 12:07:39 -0700
commitd49f518eee07d9c267a32ca9443069255b4cbd1f (patch)
treeea90214ad6dbc56f6b5f20735fff9e07105547c7 /src/wasm/wasm-s-parser.cpp
parent7fe2773010a5be824ac2b75cf8ee5dac90368aaf (diff)
downloadbinaryen-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.cpp389
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);
}
}