summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-s-parser.cpp143
1 files changed, 80 insertions, 63 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 1c3738f02..7ff946200 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -445,7 +445,8 @@ Name SExpressionWasmBuilder::getFunctionName(Element& s) {
// index
size_t offset = atoi(s.str().c_str());
if (offset >= functionNames.size()) {
- throw ParseException("unknown function in getFunctionName");
+ throw ParseException(
+ "unknown function in getFunctionName", s.line, s.col);
}
return functionNames[offset];
}
@@ -455,14 +456,16 @@ Signature SExpressionWasmBuilder::getFunctionSignature(Element& s) {
if (s.dollared()) {
auto it = signatureIndices.find(s.str().str);
if (it == signatureIndices.end()) {
- throw ParseException("unknown function type in getFunctionSignature");
+ throw ParseException(
+ "unknown function type in getFunctionSignature", s.line, s.col);
}
return signatures[it->second];
} else {
// index
size_t offset = atoi(s.str().c_str());
if (offset >= signatures.size()) {
- throw ParseException("unknown function type in getFunctionSignature");
+ throw ParseException(
+ "unknown function type in getFunctionSignature", s.line, s.col);
}
return signatures[offset];
}
@@ -475,7 +478,7 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) {
// index
size_t offset = atoi(s.str().c_str());
if (offset >= globalNames.size()) {
- throw ParseException("unknown global in getGlobalName");
+ throw ParseException("unknown global in getGlobalName", s.line, s.col);
}
return globalNames[offset];
}
@@ -488,7 +491,7 @@ Name SExpressionWasmBuilder::getEventName(Element& s) {
// index
size_t offset = atoi(s.str().c_str());
if (offset >= eventNames.size()) {
- throw ParseException("unknown event in getEventName");
+ throw ParseException("unknown event in getEventName", s.line, s.col);
}
return eventNames[offset];
}
@@ -744,10 +747,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");
+ throw ParseException("module but no base for import", s.line, s.col);
}
if (!preParseImport) {
- throw ParseException("!preParseImport in func");
+ throw ParseException("!preParseImport in func", s.line, s.col);
}
auto im = make_unique<Function>();
im->name = name;
@@ -760,14 +763,14 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
}
wasm.addFunction(im.release());
if (currFunction) {
- throw ParseException("import module inside function dec");
+ throw ParseException("import module inside function dec", s.line, s.col);
}
nameMapper.clear();
return;
}
// at this point this not an import but a real function definition.
if (preParseImport) {
- throw ParseException("preParseImport in func");
+ throw ParseException("preParseImport in func", s.line, s.col);
}
size_t localIndex = params.size(); // local index for params and locals
@@ -968,11 +971,11 @@ Expression* SExpressionWasmBuilder::makeHost(Element& s, HostOp op) {
parseCallOperands(s, 1, s.size(), ret);
if (ret->op == HostOp::MemoryGrow) {
if (ret->operands.size() != 1) {
- throw ParseException("memory.grow needs one operand");
+ throw ParseException("memory.grow needs one operand", s.line, s.col);
}
} else {
if (ret->operands.size() != 0) {
- throw ParseException("host needs zero operands");
+ throw ParseException("host needs zero operands", s.line, s.col);
}
}
ret->finalize();
@@ -1048,7 +1051,8 @@ Expression* SExpressionWasmBuilder::makeGlobalSet(Element& s) {
Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
if (!currFunction) {
- throw ParseException("block is unallowed outside of functions");
+ throw ParseException(
+ "block is unallowed outside of functions", s.line, s.col);
}
// special-case Block, because Block nesting (in their first element) can be
// incredibly deep
@@ -1140,7 +1144,8 @@ 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");
+ throw ParseException(
+ "Could not parse v128 lane", s[i + 2]->line, s[i + 2]->col);
}
}
return Literal(lanes);
@@ -1150,7 +1155,7 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) {
if (type != v128) {
auto ret = parseConst(s[1]->str(), type, allocator);
if (!ret) {
- throw ParseException("bad const");
+ throw ParseException("bad const", s[1]->line, s[1]->col);
}
return ret;
}
@@ -1161,34 +1166,39 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) {
switch (lanes) {
case 2: {
if (lane_t != i64 && lane_t != f64) {
- throw ParseException("Unexpected v128 literal lane type");
+ throw ParseException(
+ "Unexpected v128 literal lane type", s[1]->line, s[1]->col);
}
ret->value = makeLanes<2>(s, allocator, lane_t);
break;
}
case 4: {
if (lane_t != i32 && lane_t != f32) {
- throw ParseException("Unexpected v128 literal lane type");
+ throw ParseException(
+ "Unexpected v128 literal lane type", s[1]->line, s[1]->col);
}
ret->value = makeLanes<4>(s, allocator, lane_t);
break;
}
case 8: {
if (lane_t != i32) {
- throw ParseException("Unexpected v128 literal lane type");
+ throw ParseException(
+ "Unexpected v128 literal lane type", s[1]->line, s[1]->col);
}
ret->value = makeLanes<8>(s, allocator, lane_t);
break;
}
case 16: {
if (lane_t != i32) {
- throw ParseException("Unexpected v128 literal lane type");
+ throw ParseException(
+ "Unexpected v128 literal lane type", s[1]->line, s[1]->col);
}
ret->value = makeLanes<16>(s, allocator, lane_t);
break;
}
default:
- throw ParseException("Unexpected number of lanes in v128 literal");
+ throw ParseException(
+ "Unexpected number of lanes in v128 literal", s[1]->line, s[1]->col);
}
ret->finalize();
return ret;
@@ -1201,13 +1211,13 @@ static uint8_t parseMemBytes(const char*& s, uint8_t fallback) {
s++;
} else if (s[0] == '1') {
if (s[1] != '6') {
- throw ParseException("expected 16 for memop size");
+ throw ParseException(std::string("expected 16 for memop size: ") + s);
}
ret = 2;
s += 2;
} else if (s[0] == '3') {
if (s[1] != '2') {
- throw ParseException("expected 32 for memop size");
+ throw ParseException(std::string("expected 32 for memop size: ") + s);
};
ret = 4;
s += 2;
@@ -1228,29 +1238,32 @@ static size_t parseMemAttributes(Element& s,
const char* str = s[i]->c_str();
const char* eq = strchr(str, '=');
if (!eq) {
- throw ParseException("missing = in memory attribute");
+ throw ParseException(
+ "missing = in memory attribute", s[i]->line, s[i]->col);
}
eq++;
if (*eq == 0) {
- throw ParseException("missing value in memory attribute", s.line, s.col);
+ throw ParseException(
+ "missing value in memory attribute", s[i]->line, s[i]->col);
}
char* endptr;
uint64_t value = strtoll(eq, &endptr, 10);
if (*endptr != 0) {
- throw ParseException("bad memory attribute immediate", s.line, s.col);
+ throw ParseException(
+ "bad memory attribute immediate", s[i]->line, s[i]->col);
}
if (str[0] == 'a') {
if (value > std::numeric_limits<uint32_t>::max()) {
- throw ParseException("bad align", s.line, s.col);
+ throw ParseException("bad align", s[i]->line, s[i]->col);
}
align = value;
} else if (str[0] == 'o') {
if (value > std::numeric_limits<uint32_t>::max()) {
- throw ParseException("bad offset", s.line, s.col);
+ throw ParseException("bad offset", s[i]->line, s[i]->col);
}
offset = value;
} else {
- throw ParseException("bad memory attribute");
+ throw ParseException("bad memory attribute", s[i]->line, s[i]->col);
}
i++;
}
@@ -1309,7 +1322,7 @@ Expression* SExpressionWasmBuilder::makeAtomicRMWOrCmpxchg(Element& s,
auto bytes = parseMemBytes(extra, type.getByteSize());
extra = strchr(extra, '.'); // after the optional '_u' and before the opcode
if (!extra) {
- throw ParseException("malformed atomic rmw instruction");
+ throw ParseException("malformed atomic rmw instruction", s.line, s.col);
}
extra++; // after the '.'
if (!strncmp(extra, "cmpxchg", 7)) {
@@ -1338,12 +1351,12 @@ Expression* SExpressionWasmBuilder::makeAtomicRMW(Element& s,
} else if (!strncmp(extra, "xchg", 4)) {
ret->op = Xchg;
} else {
- throw ParseException("bad atomic rmw operator");
+ throw ParseException("bad atomic rmw operator", s.line, s.col);
}
Address align;
size_t i = parseMemAttributes(s, ret->offset, align, ret->bytes);
if (align != ret->bytes) {
- throw ParseException("Align of Atomic RMW must match size");
+ throw ParseException("Align of Atomic RMW must match size", s.line, s.col);
}
ret->ptr = parseExpression(s[i]);
ret->value = parseExpression(s[i + 1]);
@@ -1361,7 +1374,8 @@ Expression* SExpressionWasmBuilder::makeAtomicCmpxchg(Element& s,
Address align;
size_t i = parseMemAttributes(s, ret->offset, align, ret->bytes);
if (align != ret->bytes) {
- throw ParseException("Align of Atomic Cmpxchg must match size");
+ throw ParseException(
+ "Align of Atomic Cmpxchg must match size", s.line, s.col);
}
ret->ptr = parseExpression(s[i]);
ret->expected = parseExpression(s[i + 1]);
@@ -1417,11 +1431,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");
+ throw ParseException("Expected lane index", s->line, s->col);
}
if (n > lanes) {
- throw ParseException("lane index must be less than " +
- std::to_string(lanes));
+ throw ParseException(
+ "lane index must be less than " + std::to_string(lanes), s->line, s->col);
}
return uint8_t(n);
}
@@ -1662,7 +1676,7 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s, bool isReturn) {
Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s,
bool isReturn) {
if (!wasm.table.exists) {
- throw ParseException("no table");
+ throw ParseException("no table", s.line, s.col);
}
Index i = 1;
auto ret = allocator.alloc<CallIndirect>();
@@ -1683,9 +1697,9 @@ Name SExpressionWasmBuilder::getLabel(Element& s) {
try {
offset = std::stoll(s.c_str(), nullptr, 0);
} catch (std::invalid_argument&) {
- throw ParseException("invalid break offset");
+ throw ParseException("invalid break offset", s.line, s.col);
} catch (std::out_of_range&) {
- throw ParseException("out of range break offset");
+ throw ParseException("out of range break offset", s.line, s.col);
}
if (offset > nameMapper.labelStack.size()) {
throw ParseException("invalid label", s.line, s.col);
@@ -1728,7 +1742,7 @@ Expression* SExpressionWasmBuilder::makeBreakTable(Element& s) {
ret->targets.push_back(getLabel(*s[i++]));
}
if (ret->targets.size() == 0) {
- throw ParseException("switch with no targets");
+ throw ParseException("switch with no targets", s.line, s.col);
}
ret->default_ = ret->targets.back();
ret->targets.pop_back();
@@ -1923,17 +1937,17 @@ Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
wasm.memory.max = Memory::kUnlimitedSize;
return i;
}
- uint64_t max = atoll(s[i++]->c_str());
+ uint64_t max = atoll(s[i]->c_str());
if (max > Memory::kMaxSize) {
- throw ParseException("total memory must be <= 4GB");
+ throw ParseException("total memory must be <= 4GB", s[i]->line, s[i]->col);
}
wasm.memory.max = max;
- return i;
+ return ++i;
}
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (wasm.memory.exists) {
- throw ParseException("too many memories");
+ throw ParseException("too many memories", s.line, s.col);
}
wasm.memory.exists = true;
wasm.memory.shared = false;
@@ -1950,7 +1964,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
ex->value = wasm.memory.name;
ex->kind = ExternalKind::Memory;
if (wasm.getExportOrNull(ex->name)) {
- throw ParseException("duplicate export", s.line, s.col);
+ throw ParseException("duplicate export", inner.line, inner.col);
}
wasm.addExport(ex.release());
i++;
@@ -1964,7 +1978,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
i++;
} else {
if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true)) {
- throw ParseException("bad import ending");
+ throw ParseException("bad import ending", inner.line, inner.col);
}
// (memory (data ..)) format
auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
@@ -2004,7 +2018,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
void SExpressionWasmBuilder::parseData(Element& s) {
if (!wasm.memory.exists) {
- throw ParseException("data but no memory");
+ throw ParseException("data but no memory", s.line, s.col);
}
bool isPassive = false;
Expression* offset = nullptr;
@@ -2020,7 +2034,7 @@ void SExpressionWasmBuilder::parseData(Element& s) {
offset = parseExpression(s[i]);
}
if (s.size() != 3 && s.size() != 4) {
- throw ParseException("Unexpected data items");
+ throw ParseException("Unexpected data items", s.line, s.col);
}
parseInnerData(s, s.size() - 1, offset, isPassive);
}
@@ -2057,7 +2071,7 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
} else if (inner[0]->str() == EVENT) {
ex->kind = ExternalKind::Event;
} else {
- throw ParseException("invalid export");
+ throw ParseException("invalid export", inner.line, inner.col);
}
} else {
// function
@@ -2081,13 +2095,13 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
} else if (elementStartsWith(*s[3], MEMORY)) {
kind = ExternalKind::Memory;
if (wasm.memory.exists) {
- throw ParseException("more than one memory");
+ throw ParseException("more than one memory", s[3]->line, s[3]->col);
}
wasm.memory.exists = true;
} else if (elementStartsWith(*s[3], TABLE)) {
kind = ExternalKind::Table;
if (wasm.table.exists) {
- throw ParseException("more than one table");
+ throw ParseException("more than one table", s[3]->line, s[3]->col);
}
wasm.table.exists = true;
} else if (elementStartsWith(*s[3], GLOBAL)) {
@@ -2121,7 +2135,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
name = Name("import$event" + std::to_string(eventCounter++));
eventNames.push_back(name);
} else {
- throw ParseException("invalid import");
+ throw ParseException("invalid import", s[3]->line, s[3]->col);
}
}
if (!newStyle) {
@@ -2129,12 +2143,14 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
}
auto module = s[i++]->str();
if (!s[i]->isStr()) {
- throw ParseException("no name for import");
+ throw ParseException("no name for import", s[i]->line, s[i]->col);
}
- auto base = s[i++]->str();
+ auto base = s[i]->str();
if (!module.size() || !base.size()) {
- throw ParseException("imports must have module and base");
+ throw ParseException(
+ "imports must have module and base", s[i]->line, s[i]->col);
}
+ i++;
// parse internals
Element& inner = newStyle ? *s[3] : s;
Index j = newStyle ? newStyleInner : i;
@@ -2155,7 +2171,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
} else {
auto& inner2 = *inner[j++];
if (inner2[0]->str() != MUT) {
- throw ParseException("expected mut");
+ throw ParseException("expected mut", inner2.line, inner2.col);
}
type = stringToType(inner2[1]->str());
mutable_ = true;
@@ -2188,7 +2204,8 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
if (inner[j]->isList()) {
auto& limits = *inner[j];
if (!elementStartsWith(limits, SHARED)) {
- throw ParseException("bad memory limit declaration");
+ throw ParseException(
+ "bad memory limit declaration", inner[j]->line, inner[j]->col);
}
wasm.memory.shared = true;
j = parseMemoryLimits(limits, 1);
@@ -2265,10 +2282,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");
+ throw ParseException("module but no base for import", s.line, s.col);
}
if (!preParseImport) {
- throw ParseException("!preParseImport in global");
+ throw ParseException("!preParseImport in global", s.line, s.col);
}
auto im = make_unique<Global>();
im->name = global->name;
@@ -2283,7 +2300,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
return;
}
if (preParseImport) {
- throw ParseException("preParseImport in global");
+ throw ParseException("preParseImport in global", s.line, s.col);
}
global->type = type;
if (i < s.size()) {
@@ -2293,7 +2310,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
}
global->mutable_ = mutable_;
if (i != s.size()) {
- throw ParseException("extra import elements");
+ throw ParseException("extra import elements", s.line, s.col);
}
if (wasm.getGlobalOrNull(global->name)) {
throw ParseException("duplicate import", s.line, s.col);
@@ -2303,7 +2320,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
if (wasm.table.exists) {
- throw ParseException("more than one table");
+ throw ParseException("more than one table", s.line, s.col);
}
wasm.table.exists = true;
Index i = 1;
@@ -2325,19 +2342,19 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
ex->value = wasm.table.name;
ex->kind = ExternalKind::Table;
if (wasm.getExportOrNull(ex->name)) {
- throw ParseException("duplicate export", s.line, s.col);
+ throw ParseException("duplicate export", inner.line, inner.col);
}
wasm.addExport(ex.release());
i++;
} else if (elementStartsWith(inner, IMPORT)) {
if (!preParseImport) {
- throw ParseException("!preParseImport in table");
+ throw ParseException("!preParseImport in table", inner.line, inner.col);
}
wasm.table.module = inner[1]->str();
wasm.table.base = inner[2]->str();
i++;
} else {
- throw ParseException("invalid table");
+ throw ParseException("invalid table", inner.line, inner.col);
}
}
if (i == s.size()) {