summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r--src/wasm/wasm-s-parser.cpp672
1 files changed, 439 insertions, 233 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 3ba8e0622..bb498329f 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -16,8 +16,8 @@
#include "wasm-s-parser.h"
-#include <cmath>
#include <cctype>
+#include <cmath>
#include <limits>
#include "asm_v_wasm.h"
@@ -28,19 +28,24 @@
#include "wasm-binary.h"
#include "wasm-builder.h"
-#define abort_on(str) { throw ParseException(std::string("abort_on ") + str); }
-#define element_assert(condition) assert((condition) ? true : (std::cerr << "on: " << *this << '\n' && 0));
+#define abort_on(str) \
+ { throw ParseException(std::string("abort_on ") + str); }
+#define element_assert(condition) \
+ assert((condition) ? true : (std::cerr << "on: " << *this << '\n' && 0));
using cashew::IString;
namespace {
int unhex(char c) {
- if (c >= '0' && c <= '9') return c - '0';
- if (c >= 'a' && c <= 'f') return c - 'a' + 10;
- if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
throw wasm::ParseException("invalid hexadecimal");
}
-}
+} // namespace
namespace wasm {
@@ -53,23 +58,28 @@ static Address getCheckedAddress(const Element* s, const char* errorText) {
}
Element::List& Element::list() {
- if (!isList()) throw ParseException("expected list", line, col);
+ if (!isList())
+ throw ParseException("expected list", line, col);
return list_;
}
Element* Element::operator[](unsigned i) {
- if (!isList()) throw ParseException("expected list", line, col);
- if (i >= list().size()) throw ParseException("expected more elements in list", line, col);
+ if (!isList())
+ throw ParseException("expected list", line, col);
+ if (i >= list().size())
+ throw ParseException("expected more elements in list", line, col);
return list()[i];
}
IString Element::str() const {
- if (!isStr()) throw ParseException("expected string", line, col);
+ if (!isStr())
+ throw ParseException("expected string", line, col);
return str_;
}
const char* Element::c_str() const {
- if (!isStr()) throw ParseException("expected string", line, col);
+ if (!isStr())
+ throw ParseException("expected string", line, col);
return str_.str;
}
@@ -81,7 +91,8 @@ Element* Element::setString(IString str__, bool dollared__, bool quoted__) {
return this;
}
-Element* Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) {
+Element*
+Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) {
line = line_;
col = col_;
startLoc = startLoc_;
@@ -91,7 +102,8 @@ Element* Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLo
std::ostream& operator<<(std::ostream& o, Element& e) {
if (e.isList_) {
o << '(';
- for (auto item : e.list_) o << ' ' << *item;
+ for (auto item : e.list_)
+ o << ' ' << *item;
o << " )";
} else {
o << e.str_.str;
@@ -103,7 +115,6 @@ void Element::dump() {
std::cout << "dumping " << this << " : " << *this << ".\n";
}
-
SExpressionParser::SExpressionParser(char* input) : input(input) {
root = nullptr;
line = 1;
@@ -114,16 +125,18 @@ SExpressionParser::SExpressionParser(char* input) : input(input) {
}
Element* SExpressionParser::parse() {
- std::vector<Element *> stack;
+ std::vector<Element*> stack;
std::vector<SourceLocation*> stackLocs;
- Element *curr = allocator.alloc<Element>();
+ Element* curr = allocator.alloc<Element>();
while (1) {
skipWhitespace();
- if (input[0] == 0) break;
+ if (input[0] == 0)
+ break;
if (input[0] == '(') {
input++;
stack.push_back(curr);
- curr = allocator.alloc<Element>()->setMetadata(line, input - lineStart - 1, loc);
+ curr = allocator.alloc<Element>()->setMetadata(
+ line, input - lineStart - 1, loc);
stackLocs.push_back(loc);
assert(stack.size() == stackLocs.size());
} else if (input[0] == ')') {
@@ -143,31 +156,38 @@ Element* SExpressionParser::parse() {
curr->list().push_back(parseString());
}
}
- if (stack.size() != 0) throw ParseException("stack is not empty", curr->line, curr->col);
+ if (stack.size() != 0)
+ throw ParseException("stack is not empty", curr->line, curr->col);
return curr;
}
void SExpressionParser::parseDebugLocation() {
// Extracting debug location (if valid)
char* debugLoc = input + 3; // skipping ";;@"
- while (debugLoc[0] && debugLoc[0] == ' ') debugLoc++;
+ while (debugLoc[0] && debugLoc[0] == ' ')
+ debugLoc++;
char* debugLocEnd = debugLoc;
- while (debugLocEnd[0] && debugLocEnd[0] != '\n') debugLocEnd++;
+ while (debugLocEnd[0] && debugLocEnd[0] != '\n')
+ debugLocEnd++;
char* pos = debugLoc;
- while (pos < debugLocEnd && pos[0] != ':') pos++;
+ while (pos < debugLocEnd && pos[0] != ':')
+ pos++;
if (pos >= debugLocEnd) {
return; // no line number
}
std::string name(debugLoc, pos);
char* lineStart = ++pos;
- while (pos < debugLocEnd && pos[0] != ':') pos++;
+ while (pos < debugLocEnd && pos[0] != ':')
+ pos++;
std::string lineStr(lineStart, pos);
if (pos >= debugLocEnd) {
return; // no column number
}
std::string colStr(++pos, debugLocEnd);
- void* buf = allocator.allocSpace(sizeof(SourceLocation), alignof(SourceLocation));
- loc = new (buf) SourceLocation(IString(name.c_str(), false), atoi(lineStr.c_str()), atoi(colStr.c_str()));
+ void* buf =
+ allocator.allocSpace(sizeof(SourceLocation), alignof(SourceLocation));
+ loc = new (buf) SourceLocation(
+ IString(name.c_str(), false), atoi(lineStr.c_str()), atoi(colStr.c_str()));
}
void SExpressionParser::skipWhitespace() {
@@ -183,16 +203,19 @@ void SExpressionParser::skipWhitespace() {
if (input[2] == '@') {
parseDebugLocation();
}
- while (input[0] && input[0] != '\n') input++;
+ while (input[0] && input[0] != '\n')
+ input++;
line++;
- if (!input[0]) return;
+ if (!input[0])
+ return;
lineStart = ++input;
} else if (input[0] == '(' && input[1] == ';') {
// Skip nested block comments.
input += 2;
int depth = 1;
while (1) {
- if (!input[0]) return;
+ if (!input[0])
+ return;
if (input[0] == '(' && input[1] == ';') {
input += 2;
depth++;
@@ -222,17 +245,22 @@ Element* SExpressionParser::parseString() {
input++;
dollared = true;
}
- char *start = input;
+ char* start = input;
if (input[0] == '"') {
- // parse escaping \", but leave code escaped - we'll handle escaping in memory segments specifically
+ // parse escaping \", but leave code escaped - we'll handle escaping in
+ // memory segments specifically
input++;
std::string str;
while (1) {
- if (input[0] == 0) throw ParseException("unterminated string", line, start - lineStart);
- if (input[0] == '"') break;
+ if (input[0] == 0)
+ throw ParseException("unterminated string", line, start - lineStart);
+ if (input[0] == '"')
+ break;
if (input[0] == '\\') {
str += input[0];
- if (input[1] == 0) throw ParseException("unterminated string escape", line, start - lineStart);
+ if (input[1] == 0)
+ throw ParseException(
+ "unterminated string escape", line, start - lineStart);
str += input[1];
input += 2;
continue;
@@ -241,21 +269,34 @@ Element* SExpressionParser::parseString() {
input++;
}
input++;
- return allocator.alloc<Element>()->setString(IString(str.c_str(), false), dollared, true)->setMetadata(line, start - lineStart, loc);
+ return allocator.alloc<Element>()
+ ->setString(IString(str.c_str(), false), dollared, true)
+ ->setMetadata(line, start - lineStart, loc);
}
- while (input[0] && !isspace(input[0]) && input[0] != ')' && input[0] != '(' && input[0] != ';') input++;
- if (start == input) throw ParseException("expected string", line, input - lineStart);
+ while (input[0] && !isspace(input[0]) && input[0] != ')' && input[0] != '(' &&
+ input[0] != ';')
+ input++;
+ if (start == input)
+ throw ParseException("expected string", line, input - lineStart);
char temp = input[0];
input[0] = 0;
- auto ret = allocator.alloc<Element>()->setString(IString(start, false), dollared, false)->setMetadata(line, start - lineStart, loc);
+ auto ret = allocator.alloc<Element>()
+ ->setString(IString(start, false), dollared, false)
+ ->setMetadata(line, start - lineStart, loc);
input[0] = temp;
return ret;
}
-SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm, Element& module, Name* moduleName) : wasm(wasm), allocator(wasm.allocator) {
- if (module.size() == 0) throw ParseException("empty toplevel, expected module");
- if (module[0]->str() != MODULE) throw ParseException("toplevel does not start with module");
- if (module.size() == 1) return;
+SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm,
+ Element& module,
+ Name* moduleName)
+ : wasm(wasm), allocator(wasm.allocator) {
+ if (module.size() == 0)
+ throw ParseException("empty toplevel, expected module");
+ if (module[0]->str() != MODULE)
+ throw ParseException("toplevel does not start with module");
+ if (module.size() == 1)
+ return;
Index i = 1;
if (module[i]->dollared()) {
if (moduleName) {
@@ -286,7 +327,9 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm, Element& module, Na
implementedFunctions++;
}
}
- functionCounter -= implementedFunctions; // we go through the functions again, now parsing them, and the counter begins from where imports ended
+ // we go through the functions again, now parsing them, and the counter begins
+ // from where imports ended
+ functionCounter -= implementedFunctions;
for (unsigned j = i; j < module.size(); j++) {
parseModuleElement(*module[j]);
}
@@ -295,36 +338,55 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm, Element& module, Na
bool SExpressionWasmBuilder::isImport(Element& curr) {
for (Index i = 0; i < curr.size(); i++) {
auto& x = *curr[i];
- if (x.isList() && x.size() > 0 && x[0]->isStr() && x[0]->str() == IMPORT) return true;
+ if (x.isList() && x.size() > 0 && x[0]->isStr() && x[0]->str() == IMPORT)
+ return true;
}
return false;
}
void SExpressionWasmBuilder::preParseImports(Element& curr) {
IString id = curr[0]->str();
- if (id == IMPORT) parseImport(curr);
+ if (id == IMPORT)
+ parseImport(curr);
if (isImport(curr)) {
- if (id == FUNC) parseFunction(curr, true /* preParseImport */);
- else if (id == GLOBAL) parseGlobal(curr, true /* preParseImport */);
- else if (id == TABLE) parseTable(curr, true /* preParseImport */);
- else if (id == MEMORY) parseMemory(curr, true /* preParseImport */);
- else throw ParseException("fancy import we don't support yet", curr.line, curr.col);
+ if (id == FUNC)
+ parseFunction(curr, true /* preParseImport */);
+ else if (id == GLOBAL)
+ parseGlobal(curr, true /* preParseImport */);
+ else if (id == TABLE)
+ parseTable(curr, true /* preParseImport */);
+ else if (id == MEMORY)
+ parseMemory(curr, true /* preParseImport */);
+ else
+ throw ParseException(
+ "fancy import we don't support yet", curr.line, curr.col);
}
}
void SExpressionWasmBuilder::parseModuleElement(Element& curr) {
- if (isImport(curr)) return; // already done
+ if (isImport(curr))
+ return; // already done
IString id = curr[0]->str();
- if (id == START) return parseStart(curr);
- if (id == FUNC) return parseFunction(curr);
- if (id == MEMORY) return parseMemory(curr);
- if (id == DATA) return parseData(curr);
- if (id == EXPORT) return parseExport(curr);
- if (id == IMPORT) return; // already done
- if (id == GLOBAL) return parseGlobal(curr);
- if (id == TABLE) return parseTable(curr);
- if (id == ELEM) return parseElem(curr);
- if (id == TYPE) return; // already done
+ if (id == START)
+ return parseStart(curr);
+ if (id == FUNC)
+ return parseFunction(curr);
+ if (id == MEMORY)
+ return parseMemory(curr);
+ if (id == DATA)
+ return parseData(curr);
+ if (id == EXPORT)
+ return parseExport(curr);
+ if (id == IMPORT)
+ return; // already done
+ if (id == GLOBAL)
+ return parseGlobal(curr);
+ if (id == TABLE)
+ return parseTable(curr);
+ if (id == ELEM)
+ return parseElem(curr);
+ if (id == TYPE)
+ return; // already done
std::cerr << "bad module element " << id.str << '\n';
throw ParseException("unknown module element", curr.line, curr.col);
}
@@ -335,7 +397,8 @@ Name SExpressionWasmBuilder::getFunctionName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= functionNames.size()) throw ParseException("unknown function in getFunctionName");
+ if (offset >= functionNames.size())
+ throw ParseException("unknown function in getFunctionName");
return functionNames[offset];
}
}
@@ -346,7 +409,8 @@ Name SExpressionWasmBuilder::getFunctionTypeName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= functionTypeNames.size()) throw ParseException("unknown function type in getFunctionTypeName");
+ if (offset >= functionTypeNames.size())
+ throw ParseException("unknown function type in getFunctionTypeName");
return functionTypeNames[offset];
}
}
@@ -357,16 +421,18 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= globalNames.size()) throw ParseException("unknown global in getGlobalName");
+ if (offset >= globalNames.size())
+ throw ParseException("unknown global in getGlobalName");
return globalNames[offset];
}
}
-
void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
IString id = s[0]->str();
- if (id == TYPE) return parseType(s);
- if (id != FUNC) return;
+ if (id == TYPE)
+ return parseType(s);
+ if (id != FUNC)
+ return;
size_t i = 1;
Name name, exportName;
i = parseFunctionNames(s, name, exportName);
@@ -379,15 +445,17 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
FunctionType* type = nullptr;
functionTypes[name] = none;
std::vector<Type> params;
- for (;i < s.size(); i++) {
+ for (; i < s.size(); i++) {
Element& curr = *s[i];
IString id = curr[0]->str();
if (id == RESULT) {
- if (curr.size() > 2) throw ParseException("invalid result arity", curr.line, curr.col);
+ if (curr.size() > 2)
+ throw ParseException("invalid result arity", curr.line, curr.col);
functionTypes[name] = stringToType(curr[1]->str());
} else if (id == TYPE) {
Name typeName = getFunctionTypeName(*curr[1]);
- if (!wasm.getFunctionTypeOrNull(typeName)) throw ParseException("unknown function type", curr.line, curr.col);
+ if (!wasm.getFunctionTypeOrNull(typeName))
+ throw ParseException("unknown function type", curr.line, curr.col);
type = wasm.getFunctionType(typeName);
functionTypes[name] = type->result;
} else if (id == PARAM && curr.size() > 1) {
@@ -403,8 +471,8 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
}
}
if (!type) {
- // if no function type provided, generate one, but reuse a previous one with the
- // right structure if there is one.
+ // if no function type provided, generate one, but reuse a previous one with
+ // the right structure if there is one.
// see https://github.com/WebAssembly/spec/pull/301
bool need = true;
std::unique_ptr<FunctionType> functionType = make_unique<FunctionType>();
@@ -419,13 +487,16 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
if (need) {
functionType->name = Name::fromInt(wasm.functionTypes.size());
functionTypeNames.push_back(functionType->name);
- if (wasm.getFunctionTypeOrNull(functionType->name)) throw ParseException("duplicate function type", s.line, s.col);
+ if (wasm.getFunctionTypeOrNull(functionType->name))
+ throw ParseException("duplicate function type", s.line, s.col);
wasm.addFunctionType(std::move(functionType));
}
}
}
-size_t SExpressionWasmBuilder::parseFunctionNames(Element& s, Name& name, Name& exportName) {
+size_t SExpressionWasmBuilder::parseFunctionNames(Element& s,
+ Name& name,
+ Name& exportName) {
size_t i = 1;
while (i < s.size() && i < 3 && s[i]->isStr()) {
if (s[i]->quoted()) {
@@ -476,27 +547,26 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
ex->name = exportName;
ex->value = name;
ex->kind = ExternalKind::Function;
- if (wasm.getExportOrNull(ex->name)) throw ParseException("duplicate export", s.line, s.col);
+ if (wasm.getExportOrNull(ex->name))
+ throw ParseException("duplicate export", s.line, s.col);
wasm.addExport(ex.release());
}
Expression* body = nullptr;
localIndex = 0;
otherIndex = 0;
brokeToAutoBlock = false;
- std::vector<NameType> typeParams; // we may have both params and a type. store the type info here
+ // we may have both params and a type. store the type info here
+ std::vector<NameType> typeParams;
std::vector<NameType> params;
std::vector<NameType> vars;
Type result = none;
Name type;
- Block* autoBlock = nullptr; // we may need to add a block for the very top level
+ // we may need to add a block for the very top level
+ Block* autoBlock = nullptr;
Name importModule, importBase;
auto makeFunction = [&]() {
currFunction = std::unique_ptr<Function>(Builder(wasm).makeFunction(
- name,
- std::move(params),
- result,
- std::move(vars)
- ));
+ name, std::move(params), result, std::move(vars)));
};
auto ensureAutoBlock = [&]() {
if (!autoBlock) {
@@ -505,7 +575,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
body = autoBlock;
}
};
- for (;i < s.size(); i++) {
+ for (; i < s.size(); i++) {
Element& curr = *s[i];
IString id = curr[0]->str();
if (id == PARAM || id == LOCAL) {
@@ -521,7 +591,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
name = Name::fromInt(localIndex);
} else {
name = curr[j]->str();
- type = stringToType(curr[j+1]->str());
+ type = stringToType(curr[j + 1]->str());
j++;
}
j++;
@@ -534,12 +604,14 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
currLocalTypes[name] = type;
}
} else if (id == RESULT) {
- if (curr.size() > 2) throw ParseException("invalid result arity", curr.line, curr.col);
+ if (curr.size() > 2)
+ throw ParseException("invalid result arity", curr.line, curr.col);
result = stringToType(curr[1]->str());
} else if (id == TYPE) {
Name name = getFunctionTypeName(*curr[1]);
type = name;
- if (!wasm.getFunctionTypeOrNull(name)) throw ParseException("unknown function type");
+ if (!wasm.getFunctionTypeOrNull(name))
+ throw ParseException("unknown function type");
FunctionType* type = wasm.getFunctionType(name);
result = type->result;
for (size_t j = 0; j < type->params.size(); j++) {
@@ -556,7 +628,8 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
if (typeParams.size() > 0 && params.size() == 0) {
params = typeParams;
}
- if (!currFunction) makeFunction();
+ if (!currFunction)
+ makeFunction();
Expression* ex = parseExpression(curr);
if (!body) {
body = ex;
@@ -569,19 +642,23 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
// see https://github.com/WebAssembly/spec/pull/301
if (type.isNull()) {
// if no function type name provided, then we generated one
- auto functionType = make_unique<FunctionType>(sigToFunctionType(getSigFromStructs(result, params)));
+ auto functionType = make_unique<FunctionType>(
+ sigToFunctionType(getSigFromStructs(result, params)));
for (auto& existing : wasm.functionTypes) {
if (existing->structuralComparison(*functionType)) {
type = existing->name;
break;
}
}
- if (!type.is()) throw ParseException("no function type [internal error?]", s.line, s.col);
+ if (!type.is())
+ throw ParseException("no function type [internal error?]", s.line, s.col);
}
if (importModule.is()) {
// this is an import, actually
- if (!importBase.size()) throw ParseException("module but no base for import");
- if (!preParseImport) throw ParseException("!preParseImport in func");
+ if (!importBase.size())
+ throw ParseException("module but no base for import");
+ if (!preParseImport)
+ throw ParseException("!preParseImport in func");
auto im = make_unique<Function>();
im->name = name;
im->module = importModule;
@@ -589,14 +666,17 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
im->type = type;
FunctionTypeUtils::fillFunction(im.get(), wasm.getFunctionType(type));
functionTypes[name] = im->result;
- if (wasm.getFunctionOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
+ if (wasm.getFunctionOrNull(im->name))
+ throw ParseException("duplicate import", s.line, s.col);
wasm.addFunction(im.release());
- if (currFunction) throw ParseException("import module inside function dec");
+ if (currFunction)
+ throw ParseException("import module inside function dec");
currLocalTypes.clear();
nameMapper.clear();
return;
}
- if (preParseImport) throw ParseException("preParseImport in func");
+ if (preParseImport)
+ throw ParseException("preParseImport in func");
if (brokeToAutoBlock) {
ensureAutoBlock();
autoBlock->name = FAKE_RETURN;
@@ -608,7 +688,8 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
makeFunction();
body = allocator.alloc<Nop>();
}
- if (currFunction->result != result) throw ParseException("bad func declaration", s.line, s.col);
+ if (currFunction->result != result)
+ throw ParseException("bad func declaration", s.line, s.col);
currFunction->body = body;
currFunction->type = type;
if (s.startLoc) {
@@ -617,41 +698,57 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
if (s.endLoc) {
currFunction->epilogLocation.insert(getDebugLocation(*s.endLoc));
}
- if (wasm.getFunctionOrNull(currFunction->name)) throw ParseException("duplicate function", s.line, s.col);
+ if (wasm.getFunctionOrNull(currFunction->name))
+ throw ParseException("duplicate function", s.line, s.col);
wasm.addFunction(currFunction.release());
currLocalTypes.clear();
nameMapper.clear();
}
-Type SExpressionWasmBuilder::stringToType(const char* str, bool allowError, bool prefix) {
+Type SExpressionWasmBuilder::stringToType(const char* str,
+ bool allowError,
+ bool prefix) {
if (str[0] == 'i') {
- if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) return i32;
- if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) return i64;
+ if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0))
+ return i32;
+ if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0))
+ return i64;
}
if (str[0] == 'f') {
- if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) return f32;
- if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) return f64;
+ if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0))
+ return f32;
+ if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0))
+ return f64;
}
if (str[0] == 'v') {
- if (str[1] == '1' && str[2] == '2' && str[3] == '8' && (prefix || str[4] == 0)) {
+ if (str[1] == '1' && str[2] == '2' && str[3] == '8' &&
+ (prefix || str[4] == 0)) {
return v128;
}
}
- if (allowError) return none;
+ if (allowError)
+ return none;
throw ParseException("invalid wasm type");
}
Type SExpressionWasmBuilder::stringToLaneType(const char* str) {
- if (strcmp(str, "i8x16") == 0) return i32;
- if (strcmp(str, "i16x8") == 0) return i32;
- if (strcmp(str, "i32x4") == 0) return i32;
- if (strcmp(str, "i64x2") == 0) return i64;
- if (strcmp(str, "f32x4") == 0) return f32;
- if (strcmp(str, "f64x2") == 0) return f64;
+ if (strcmp(str, "i8x16") == 0)
+ return i32;
+ if (strcmp(str, "i16x8") == 0)
+ return i32;
+ if (strcmp(str, "i32x4") == 0)
+ return i32;
+ if (strcmp(str, "i64x2") == 0)
+ return i64;
+ if (strcmp(str, "f32x4") == 0)
+ return f32;
+ if (strcmp(str, "f64x2") == 0)
+ return f64;
return none;
}
-Function::DebugLocation SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) {
+Function::DebugLocation
+SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) {
IString file = loc.filename;
auto& debugInfoFileNames = wasm.debugInfoFileNames;
auto iter = debugInfoFileIndices.find(file);
@@ -672,7 +769,7 @@ Expression* SExpressionWasmBuilder::parseExpression(Element& s) {
return result;
}
-Expression* SExpressionWasmBuilder::makeExpression(Element& s) {
+Expression* SExpressionWasmBuilder::makeExpression(Element& s){
#define INSTRUCTION_PARSER
#include "gen-s-parser.inc"
}
@@ -681,9 +778,7 @@ Expression* SExpressionWasmBuilder::makeUnreachable() {
return allocator.alloc<Unreachable>();
}
-Expression* SExpressionWasmBuilder::makeNop() {
- return allocator.alloc<Nop>();
-}
+Expression* SExpressionWasmBuilder::makeNop() { return allocator.alloc<Nop>(); }
Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op) {
auto ret = allocator.alloc<Binary>();
@@ -694,7 +789,6 @@ Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op) {
return ret;
}
-
Expression* SExpressionWasmBuilder::makeUnary(Element& s, UnaryOp op) {
auto ret = allocator.alloc<Unary>();
ret->op = op;
@@ -737,15 +831,18 @@ Expression* SExpressionWasmBuilder::makeHost(Element& s, HostOp op) {
}
Index SExpressionWasmBuilder::getLocalIndex(Element& s) {
- if (!currFunction) throw ParseException("local access in non-function scope", s.line, s.col);
+ if (!currFunction)
+ throw ParseException("local access in non-function scope", s.line, s.col);
if (s.dollared()) {
auto ret = s.str();
- if (currFunction->localIndices.count(ret) == 0) throw ParseException("bad local name", s.line, s.col);
+ if (currFunction->localIndices.count(ret) == 0)
+ throw ParseException("bad local name", s.line, s.col);
return currFunction->getLocalIndex(ret);
}
// this is a numeric index
Index ret = atoi(s.c_str());
- if (ret >= currFunction->getNumLocals()) throw ParseException("bad local index", s.line, s.col);
+ if (ret >= currFunction->getNumLocals())
+ throw ParseException("bad local index", s.line, s.col);
return ret;
}
@@ -788,16 +885,19 @@ Expression* SExpressionWasmBuilder::makeGetGlobal(Element& s) {
Expression* SExpressionWasmBuilder::makeSetGlobal(Element& s) {
auto ret = allocator.alloc<SetGlobal>();
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);
+ if (wasm.getGlobalOrNull(ret->name) &&
+ !wasm.getGlobalOrNull(ret->name)->mutable_)
+ throw ParseException("global.set of immutable", s.line, s.col);
ret->value = parseExpression(s[2]);
ret->finalize();
return ret;
}
-
Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
- if (!currFunction) throw ParseException("block is unallowed outside of functions");
- // special-case Block, because Block nesting (in their first element) can be incredibly deep
+ if (!currFunction)
+ throw ParseException("block is unallowed outside of functions");
+ // special-case Block, because Block nesting (in their first element) can be
+ // incredibly deep
auto curr = allocator.alloc<Block>();
auto* sp = &s;
std::vector<std::pair<Element*, Block*>> stack;
@@ -808,7 +908,8 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
Name sName;
if (i < s.size() && s[i]->isStr()) {
// could be a name or a type
- if (s[i]->dollared() || stringToType(s[i]->str(), true /* allowError */) == none) {
+ if (s[i]->dollared() ||
+ stringToType(s[i]->str(), true /* allowError */) == none) {
sName = s[i++]->str();
} else {
sName = "block";
@@ -819,7 +920,8 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
curr->name = nameMapper.pushLabelName(sName);
// block signature
curr->type = parseOptionalResultType(s, i);
- if (i >= s.size()) break; // empty block
+ if (i >= s.size())
+ break; // empty block
auto& first = *s[i];
if (first[0]->str() == BLOCK) {
// recurse
@@ -860,7 +962,8 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
return stack[0].second;
}
-// Similar to block, but the label is handled by the enclosing if (since there might not be a then or else, ick)
+// Similar to block, but the label is handled by the enclosing if (since there
+// might not be a then or else, ick)
Expression* SExpressionWasmBuilder::makeThenOrElse(Element& s) {
auto ret = allocator.alloc<Block>();
size_t i = 1;
@@ -878,7 +981,7 @@ template<int Lanes>
static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) {
std::array<Literal, Lanes> lanes;
for (size_t i = 0; i < Lanes; ++i) {
- Expression* lane = parseConst(s[i+2]->str(), lane_t, allocator);
+ Expression* lane = parseConst(s[i + 2]->str(), lane_t, allocator);
if (lane) {
lanes[i] = lane->cast<Const>()->value;
} else {
@@ -891,7 +994,8 @@ static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) {
Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) {
if (type != v128) {
auto ret = parseConst(s[1]->str(), type, allocator);
- if (!ret) throw ParseException("bad const");
+ if (!ret)
+ throw ParseException("bad const");
return ret;
}
@@ -927,7 +1031,8 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) {
ret->value = makeLanes<16>(s, allocator, lane_t);
break;
}
- default: throw ParseException("Unexpected number of lanes in v128 literal");
+ default:
+ throw ParseException("Unexpected number of lanes in v128 literal");
}
ret->finalize();
return ret;
@@ -939,11 +1044,14 @@ static uint8_t parseMemBytes(const char*& s, uint8_t fallback) {
ret = 1;
s++;
} else if (s[0] == '1') {
- if (s[1] != '6') throw ParseException("expected 16 for memop size");
+ if (s[1] != '6')
+ throw ParseException("expected 16 for memop size");
ret = 2;
s += 2;
} else if (s[0] == '3') {
- if (s[1] != '2') throw ParseException("expected 32 for memop size");;
+ if (s[1] != '2')
+ throw ParseException("expected 32 for memop size");
+ ;
ret = 4;
s += 2;
} else {
@@ -952,28 +1060,36 @@ static uint8_t parseMemBytes(const char*& s, uint8_t fallback) {
return ret;
}
-static size_t parseMemAttributes(Element& s, Address* offset, Address* align, Address fallback) {
+static size_t parseMemAttributes(Element& s,
+ Address* offset,
+ Address* align,
+ Address fallback) {
size_t i = 1;
*offset = 0;
*align = fallback;
while (!s[i]->isList()) {
- const char *str = s[i]->c_str();
- const char *eq = strchr(str, '=');
- if (!eq) throw ParseException("missing = in memory attribute");
+ const char* str = s[i]->c_str();
+ const char* eq = strchr(str, '=');
+ if (!eq)
+ throw ParseException("missing = in memory attribute");
eq++;
- if (*eq == 0) throw ParseException("missing value in memory attribute", s.line, s.col);
+ if (*eq == 0)
+ throw ParseException("missing value in memory attribute", s.line, s.col);
char* endptr;
uint64_t value = strtoll(eq, &endptr, 10);
if (*endptr != 0) {
throw ParseException("bad memory attribute immediate", s.line, s.col);
}
if (str[0] == 'a') {
- if (value > std::numeric_limits<uint32_t>::max()) throw ParseException("bad align", s.line, s.col);
+ if (value > std::numeric_limits<uint32_t>::max())
+ throw ParseException("bad align", s.line, s.col);
*align = value;
} else if (str[0] == 'o') {
- if (value > std::numeric_limits<uint32_t>::max()) throw ParseException("bad offset", s.line, s.col);
+ if (value > std::numeric_limits<uint32_t>::max())
+ throw ParseException("bad offset", s.line, s.col);
*offset = value;
- } else throw ParseException("bad memory attribute");
+ } else
+ throw ParseException("bad memory attribute");
i++;
}
return i;
@@ -983,14 +1099,18 @@ static const char* findMemExtra(const Element& s, size_t skip, bool isAtomic) {
auto* str = s.c_str();
auto size = strlen(str);
auto* ret = strchr(str, '.');
- if (!ret) throw ParseException("missing '.' in memory access", s.line, s.col);
+ if (!ret)
+ throw ParseException("missing '.' in memory access", s.line, s.col);
ret += skip;
- if (isAtomic) ret += 7; // after "type.atomic.load"
- if (ret > str + size) throw ParseException("memory access ends abruptly", s.line, s.col);
+ if (isAtomic)
+ ret += 7; // after "type.atomic.load"
+ if (ret > str + size)
+ throw ParseException("memory access ends abruptly", s.line, s.col);
return ret;
}
-Expression* SExpressionWasmBuilder::makeLoad(Element& s, Type type, bool isAtomic) {
+Expression*
+SExpressionWasmBuilder::makeLoad(Element& s, Type type, bool isAtomic) {
const char* extra = findMemExtra(*s[0], 5 /* after "type.load" */, isAtomic);
auto* ret = allocator.alloc<Load>();
ret->isAtomic = isAtomic;
@@ -1003,7 +1123,8 @@ Expression* SExpressionWasmBuilder::makeLoad(Element& s, Type type, bool isAtomi
return ret;
}
-Expression* SExpressionWasmBuilder::makeStore(Element& s, Type type, bool isAtomic) {
+Expression*
+SExpressionWasmBuilder::makeStore(Element& s, Type type, bool isAtomic) {
const char* extra = findMemExtra(*s[0], 6 /* after "type.store" */, isAtomic);
auto ret = allocator.alloc<Store>();
ret->isAtomic = isAtomic;
@@ -1011,51 +1132,70 @@ Expression* SExpressionWasmBuilder::makeStore(Element& s, Type type, bool isAtom
ret->bytes = parseMemBytes(extra, getTypeSize(type));
size_t i = parseMemAttributes(s, &ret->offset, &ret->align, ret->bytes);
ret->ptr = parseExpression(s[i]);
- ret->value = parseExpression(s[i+1]);
+ ret->value = parseExpression(s[i + 1]);
ret->finalize();
return ret;
}
-Expression* SExpressionWasmBuilder::makeAtomicRMWOrCmpxchg(Element& s, Type type) {
- const char* extra = findMemExtra(*s[0], 11 /* after "type.atomic.rmw" */, /* isAtomic = */ false);
+Expression* SExpressionWasmBuilder::makeAtomicRMWOrCmpxchg(Element& s,
+ Type type) {
+ const char* extra = findMemExtra(
+ *s[0], 11 /* after "type.atomic.rmw" */, /* isAtomic = */ false);
auto bytes = parseMemBytes(extra, getTypeSize(type));
extra = strchr(extra, '.'); // after the optional '_u' and before the opcode
- if (!extra) throw ParseException("malformed atomic rmw instruction");
+ if (!extra)
+ throw ParseException("malformed atomic rmw instruction");
extra++; // after the '.'
- if (!strncmp(extra, "cmpxchg", 7)) return makeAtomicCmpxchg(s, type, bytes, extra);
+ if (!strncmp(extra, "cmpxchg", 7))
+ return makeAtomicCmpxchg(s, type, bytes, extra);
return makeAtomicRMW(s, type, bytes, extra);
}
-Expression* SExpressionWasmBuilder::makeAtomicRMW(Element& s, Type type, uint8_t bytes, const char* extra) {
+Expression* SExpressionWasmBuilder::makeAtomicRMW(Element& s,
+ Type type,
+ uint8_t bytes,
+ const char* extra) {
auto ret = allocator.alloc<AtomicRMW>();
ret->type = type;
ret->bytes = bytes;
- if (!strncmp(extra, "add", 3)) ret->op = Add;
- else if (!strncmp(extra, "and", 3)) ret->op = And;
- else if (!strncmp(extra, "or", 2)) ret->op = Or;
- else if (!strncmp(extra, "sub", 3)) ret->op = Sub;
- else if (!strncmp(extra, "xor", 3)) ret->op = Xor;
- else if (!strncmp(extra, "xchg", 4)) ret->op = Xchg;
- else throw ParseException("bad atomic rmw operator");
+ if (!strncmp(extra, "add", 3))
+ ret->op = Add;
+ else if (!strncmp(extra, "and", 3))
+ ret->op = And;
+ else if (!strncmp(extra, "or", 2))
+ ret->op = Or;
+ else if (!strncmp(extra, "sub", 3))
+ ret->op = Sub;
+ else if (!strncmp(extra, "xor", 3))
+ ret->op = Xor;
+ else if (!strncmp(extra, "xchg", 4))
+ ret->op = Xchg;
+ else
+ throw ParseException("bad atomic rmw operator");
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");
+ if (align != ret->bytes)
+ throw ParseException("Align of Atomic RMW must match size");
ret->ptr = parseExpression(s[i]);
- ret->value = parseExpression(s[i+1]);
+ ret->value = parseExpression(s[i + 1]);
ret->finalize();
return ret;
}
-Expression* SExpressionWasmBuilder::makeAtomicCmpxchg(Element& s, Type type, uint8_t bytes, const char* extra) {
+Expression* SExpressionWasmBuilder::makeAtomicCmpxchg(Element& s,
+ Type type,
+ uint8_t bytes,
+ const char* extra) {
auto ret = allocator.alloc<AtomicCmpxchg>();
ret->type = type;
ret->bytes = bytes;
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");
+ if (align != ret->bytes)
+ throw ParseException("Align of Atomic Cmpxchg must match size");
ret->ptr = parseExpression(s[i]);
- ret->expected = parseExpression(s[i+1]);
- ret->replacement = parseExpression(s[i+2]);
+ ret->expected = parseExpression(s[i + 1]);
+ ret->replacement = parseExpression(s[i + 2]);
ret->finalize();
return ret;
}
@@ -1081,15 +1221,20 @@ Expression* SExpressionWasmBuilder::makeAtomicNotify(Element& s) {
}
static uint8_t parseLaneIndex(const Element* s, size_t lanes) {
- const char *str = s->c_str();
- char *end;
+ const char* str = s->c_str();
+ char* end;
auto n = static_cast<unsigned long long>(strtoll(str, &end, 10));
- if (end == str || *end != '\0') throw ParseException("Expected lane index");
- if (n > lanes) throw ParseException("lane index must be less than " + std::to_string(lanes));
+ if (end == str || *end != '\0')
+ throw ParseException("Expected lane index");
+ if (n > lanes)
+ throw ParseException("lane index must be less than " +
+ std::to_string(lanes));
return uint8_t(n);
}
-Expression* SExpressionWasmBuilder::makeSIMDExtract(Element& s, SIMDExtractOp op, size_t lanes) {
+Expression* SExpressionWasmBuilder::makeSIMDExtract(Element& s,
+ SIMDExtractOp op,
+ size_t lanes) {
auto ret = allocator.alloc<SIMDExtract>();
ret->op = op;
ret->index = parseLaneIndex(s[1], lanes);
@@ -1098,7 +1243,9 @@ Expression* SExpressionWasmBuilder::makeSIMDExtract(Element& s, SIMDExtractOp op
return ret;
}
-Expression* SExpressionWasmBuilder::makeSIMDReplace(Element& s, SIMDReplaceOp op, size_t lanes) {
+Expression* SExpressionWasmBuilder::makeSIMDReplace(Element& s,
+ SIMDReplaceOp op,
+ size_t lanes) {
auto ret = allocator.alloc<SIMDReplace>();
ret->op = op;
ret->index = parseLaneIndex(s[1], lanes);
@@ -1111,7 +1258,7 @@ Expression* SExpressionWasmBuilder::makeSIMDReplace(Element& s, SIMDReplaceOp op
Expression* SExpressionWasmBuilder::makeSIMDShuffle(Element& s) {
auto ret = allocator.alloc<SIMDShuffle>();
for (size_t i = 0; i < 16; ++i) {
- ret->mask[i] = parseLaneIndex(s[i+1], 32);
+ ret->mask[i] = parseLaneIndex(s[i + 1], 32);
}
ret->left = parseExpression(s[17]);
ret->right = parseExpression(s[18]);
@@ -1203,11 +1350,13 @@ Expression* SExpressionWasmBuilder::makeIf(Element& s) {
return ret;
}
-
-Expression* SExpressionWasmBuilder::makeMaybeBlock(Element& s, size_t i, Type type) {
+Expression*
+SExpressionWasmBuilder::makeMaybeBlock(Element& s, size_t i, Type type) {
Index stopAt = -1;
- if (s.size() == i) return allocator.alloc<Nop>();
- if (s.size() == i+1) return parseExpression(s[i]);
+ if (s.size() == i)
+ return allocator.alloc<Nop>();
+ if (s.size() == i + 1)
+ return parseExpression(s[i]);
auto ret = allocator.alloc<Block>();
for (; i < s.size() && i < stopAt; i++) {
ret->list.push_back(parseExpression(s[i]));
@@ -1265,7 +1414,8 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s) {
}
Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
- if (!wasm.table.exists) throw ParseException("no table");
+ if (!wasm.table.exists)
+ throw ParseException("no table");
auto ret = allocator.alloc<CallIndirect>();
Index i = 1;
Element& typeElement = *s[i];
@@ -1273,7 +1423,8 @@ Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
// type name given
IString type = typeElement[1]->str();
auto* fullType = wasm.getFunctionTypeOrNull(type);
- if (!fullType) throw ParseException("invalid call_indirect type", s.line, s.col);
+ if (!fullType)
+ throw ParseException("invalid call_indirect type", s.line, s.col);
ret->fullType = fullType->name;
i++;
} else {
@@ -1314,9 +1465,11 @@ Name SExpressionWasmBuilder::getLabel(Element& s) {
} catch (std::out_of_range&) {
throw ParseException("out of range break offset");
}
- if (offset > nameMapper.labelStack.size()) throw ParseException("invalid label", s.line, s.col);
+ if (offset > nameMapper.labelStack.size())
+ throw ParseException("invalid label", s.line, s.col);
if (offset == nameMapper.labelStack.size()) {
- // a break to the function's scope. this means we need an automatic block, with a name
+ // a break to the function's scope. this means we need an automatic block,
+ // with a name
brokeToAutoBlock = true;
return FAKE_RETURN;
}
@@ -1329,7 +1482,8 @@ Expression* SExpressionWasmBuilder::makeBreak(Element& s) {
size_t i = 1;
ret->name = getLabel(*s[i]);
i++;
- if (i == s.size()) return ret;
+ if (i == s.size())
+ return ret;
if (s[0]->str() == BR_IF) {
if (i + 1 < s.size()) {
ret->value = parseExpression(s[i]);
@@ -1349,7 +1503,8 @@ Expression* SExpressionWasmBuilder::makeBreakTable(Element& s) {
while (!s[i]->isList()) {
ret->targets.push_back(getLabel(*s[i++]));
}
- if (ret->targets.size() == 0) throw ParseException("switch with no targets");
+ if (ret->targets.size() == 0)
+ throw ParseException("switch with no targets");
ret->default_ = ret->targets.back();
ret->targets.pop_back();
ret->condition = parseExpression(s[i++]);
@@ -1368,14 +1523,18 @@ Expression* SExpressionWasmBuilder::makeReturn(Element& s) {
return ret;
}
-// converts an s-expression string representing binary data into an output sequence of raw bytes
-// this appends to data, which may already contain content.
-void SExpressionWasmBuilder::stringToBinary(const char* input, size_t size, std::vector<char>& data) {
+// converts an s-expression string representing binary data into an output
+// sequence of raw bytes this appends to data, which may already contain
+// content.
+void SExpressionWasmBuilder::stringToBinary(const char* input,
+ size_t size,
+ std::vector<char>& data) {
auto originalSize = data.size();
data.resize(originalSize + size);
- char *write = data.data() + originalSize;
+ char* write = data.data() + originalSize;
while (1) {
- if (input[0] == 0) break;
+ if (input[0] == 0)
+ break;
if (input[0] == '\\') {
if (input[1] == '"') {
*write++ = '"';
@@ -1398,7 +1557,7 @@ void SExpressionWasmBuilder::stringToBinary(const char* input, size_t size, std:
input += 2;
continue;
} else {
- *write++ = (char)(unhex(input[1])*16 + unhex(input[2]));
+ *write++ = (char)(unhex(input[1]) * 16 + unhex(input[2]));
input += 3;
continue;
}
@@ -1419,13 +1578,15 @@ Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
return i;
}
uint64_t max = atoll(s[i++]->c_str());
- if (max > Memory::kMaxSize) throw ParseException("total memory must be <= 4GB");
+ if (max > Memory::kMaxSize)
+ throw ParseException("total memory must be <= 4GB");
wasm.memory.max = max;
return i;
}
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
- if (wasm.memory.exists) throw ParseException("too many memories");
+ if (wasm.memory.exists)
+ throw ParseException("too many memories");
wasm.memory.exists = true;
wasm.memory.shared = false;
Index i = 1;
@@ -1440,7 +1601,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = wasm.memory.name;
ex->kind = ExternalKind::Memory;
- if (wasm.getExportOrNull(ex->name)) throw ParseException("duplicate export", s.line, s.col);
+ if (wasm.getExportOrNull(ex->name))
+ throw ParseException("duplicate export", s.line, s.col);
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
@@ -1452,7 +1614,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
parseMemoryLimits(inner, 1);
i++;
} else {
- if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true)) throw ParseException("bad import ending");
+ if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true))
+ throw ParseException("bad import ending");
// (memory (data ..)) format
auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
parseInnerData(*s[i], 1, offset, false);
@@ -1460,7 +1623,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
return;
}
}
- if (!wasm.memory.shared) i = parseMemoryLimits(s, i);
+ if (!wasm.memory.shared)
+ i = parseMemoryLimits(s, i);
// Parse memory initializers.
while (i < s.size()) {
@@ -1472,7 +1636,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
} else {
offsetValue = getCheckedAddress(curr[j++], "excessive memory offset");
}
- const char *input = curr[j]->c_str();
+ const char* input = curr[j]->c_str();
auto* offset = allocator.alloc<Const>();
offset->type = i32;
offset->value = Literal(int32_t(offsetValue));
@@ -1488,7 +1652,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
}
void SExpressionWasmBuilder::parseData(Element& s) {
- if (!wasm.memory.exists) throw ParseException("data but no memory");
+ if (!wasm.memory.exists)
+ throw ParseException("data but no memory");
bool isPassive = false;
Expression* offset = nullptr;
Index i = 1;
@@ -1508,15 +1673,19 @@ void SExpressionWasmBuilder::parseData(Element& s) {
parseInnerData(s, s.size() - 1, offset, isPassive);
}
-void SExpressionWasmBuilder::parseInnerData(Element& s, Index i, Expression* offset, bool isPassive) {
+void SExpressionWasmBuilder::parseInnerData(Element& s,
+ Index i,
+ Expression* offset,
+ bool isPassive) {
std::vector<char> data;
while (i < s.size()) {
- const char *input = s[i++]->c_str();
+ const char* input = s[i++]->c_str();
if (auto size = strlen(input)) {
stringToBinary(input, size, data);
}
}
- wasm.memory.segments.emplace_back(isPassive, offset, data.data(), data.size());
+ wasm.memory.segments.emplace_back(
+ isPassive, offset, data.data(), data.size());
}
void SExpressionWasmBuilder::parseExport(Element& s) {
@@ -1533,14 +1702,17 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
ex->kind = ExternalKind::Table;
} else if (inner[0]->str() == GLOBAL) {
ex->kind = ExternalKind::Global;
- if (wasm.getGlobalOrNull(ex->value) && wasm.getGlobal(ex->value)->mutable_) throw ParseException("cannot export a mutable global", s.line, s.col);
+ if (wasm.getGlobalOrNull(ex->value) &&
+ wasm.getGlobal(ex->value)->mutable_)
+ throw ParseException("cannot export a mutable global", s.line, s.col);
} else {
throw ParseException("invalid export");
}
} else if (!s[2]->dollared() && !std::isdigit(s[2]->str()[0])) {
ex->value = s[3]->str();
if (s[2]->str() == MEMORY) {
- if (!wasm.memory.exists) throw ParseException("memory exported but no memory");
+ if (!wasm.memory.exists)
+ throw ParseException("memory exported but no memory");
ex->kind = ExternalKind::Memory;
} else if (s[2]->str() == TABLE) {
ex->kind = ExternalKind::Table;
@@ -1554,24 +1726,28 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
ex->value = s[2]->str();
ex->kind = ExternalKind::Function;
}
- if (wasm.getExportOrNull(ex->name)) throw ParseException("duplicate export", s.line, s.col);
+ if (wasm.getExportOrNull(ex->name))
+ throw ParseException("duplicate export", s.line, s.col);
wasm.addExport(ex.release());
}
void SExpressionWasmBuilder::parseImport(Element& s) {
size_t i = 1;
- bool newStyle = s.size() == 4 && s[3]->isList(); // (import "env" "STACKTOP" (global $stackTop i32))
+ // (import "env" "STACKTOP" (global $stackTop i32))
+ bool newStyle = s.size() == 4 && s[3]->isList();
auto kind = ExternalKind::Invalid;
if (newStyle) {
if ((*s[3])[0]->str() == FUNC) {
kind = ExternalKind::Function;
} else if ((*s[3])[0]->str() == MEMORY) {
kind = ExternalKind::Memory;
- if (wasm.memory.exists) throw ParseException("more than one memory");
+ if (wasm.memory.exists)
+ throw ParseException("more than one memory");
wasm.memory.exists = true;
} else if ((*s[3])[0]->str() == TABLE) {
kind = ExternalKind::Table;
- if (wasm.table.exists) throw ParseException("more than one table");
+ if (wasm.table.exists)
+ throw ParseException("more than one table");
wasm.table.exists = true;
} else if ((*s[3])[0]->str() == GLOBAL) {
kind = ExternalKind::Global;
@@ -1583,7 +1759,8 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
Name name;
if (s.size() > 3 && s[3]->isStr()) {
name = s[i++]->str();
- } else if (newStyle && newStyleInner < s[3]->size() && (*s[3])[newStyleInner]->dollared()) {
+ } else if (newStyle && newStyleInner < s[3]->size() &&
+ (*s[3])[newStyleInner]->dollared()) {
name = (*s[3])[newStyleInner++]->str();
}
if (!name.is()) {
@@ -1616,9 +1793,11 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
kind = ExternalKind::Function;
}
auto module = s[i++]->str();
- if (!s[i]->isStr()) throw ParseException("no name for import");
+ if (!s[i]->isStr())
+ throw ParseException("no name for import");
auto base = s[i++]->str();
- if (!module.size() || !base.size()) throw ParseException("imports must have module and base");
+ if (!module.size() || !base.size())
+ throw ParseException("imports must have module and base");
// parse internals
Element& inner = newStyle ? *s[3] : s;
Index j = newStyle ? newStyleInner : i;
@@ -1635,14 +1814,16 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
type->result = stringToType(params[1]->str());
} else if (id == TYPE) {
IString name = params[1]->str();
- if (!wasm.getFunctionTypeOrNull(name)) throw ParseException("bad function type for import");
+ if (!wasm.getFunctionTypeOrNull(name))
+ throw ParseException("bad function type for import");
*type = *wasm.getFunctionType(name);
} else {
throw ParseException("bad import element");
}
- if (inner.size() > j+1) {
- Element& result = *inner[j+1];
- if (result[0]->str() != RESULT) throw ParseException("expected result");
+ if (inner.size() > j + 1) {
+ Element& result = *inner[j + 1];
+ if (result[0]->str() != RESULT)
+ throw ParseException("expected result");
type->result = stringToType(result[1]->str());
}
}
@@ -1662,7 +1843,8 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
type = stringToType(inner[j]->str());
} else {
auto& inner2 = *inner[j];
- if (inner2[0]->str() != MUT) throw ParseException("expected mut");
+ if (inner2[0]->str() != MUT)
+ throw ParseException("expected mut");
type = stringToType(inner2[1]->str());
mutable_ = true;
}
@@ -1677,10 +1859,12 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.table.module = module;
wasm.table.base = base;
if (j < inner.size() - 1) {
- wasm.table.initial = getCheckedAddress(inner[j++], "excessive table init size");
+ wasm.table.initial =
+ getCheckedAddress(inner[j++], "excessive table init size");
}
if (j < inner.size() - 1) {
- wasm.table.max = getCheckedAddress(inner[j++], "excessive table max size");
+ wasm.table.max =
+ getCheckedAddress(inner[j++], "excessive table max size");
} else {
wasm.table.max = Table::kUnlimitedSize;
}
@@ -1690,7 +1874,8 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.memory.base = base;
if (inner[j]->isList()) {
auto& limits = *inner[j];
- if (!(limits[0]->isStr() && limits[0]->str() == "shared")) throw ParseException("bad memory limit declaration");
+ if (!(limits[0]->isStr() && limits[0]->str() == "shared"))
+ throw ParseException("bad memory limit declaration");
wasm.memory.shared = true;
parseMemoryLimits(limits, 1);
} else {
@@ -1720,7 +1905,8 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = global->name;
ex->kind = ExternalKind::Global;
- if (wasm.getExportOrNull(ex->name)) throw ParseException("duplicate export", s.line, s.col);
+ if (wasm.getExportOrNull(ex->name))
+ throw ParseException("duplicate export", s.line, s.col);
wasm.addExport(ex.release());
exported = true;
i++;
@@ -1736,25 +1922,30 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
break;
}
}
- if (exported && mutable_) throw ParseException("cannot export a mutable global", s.line, s.col);
+ if (exported && mutable_)
+ throw ParseException("cannot export a mutable global", s.line, s.col);
if (type == none) {
type = stringToType(s[i++]->str());
}
if (importModule.is()) {
// this is an import, actually
- if (!importBase.size()) throw ParseException("module but no base for import");
- if (!preParseImport) throw ParseException("!preParseImport in global");
+ if (!importBase.size())
+ throw ParseException("module but no base for import");
+ if (!preParseImport)
+ throw ParseException("!preParseImport in global");
auto im = make_unique<Global>();
im->name = global->name;
im->module = importModule;
im->base = importBase;
im->type = type;
im->mutable_ = mutable_;
- if (wasm.getGlobalOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
+ if (wasm.getGlobalOrNull(im->name))
+ throw ParseException("duplicate import", s.line, s.col);
wasm.addGlobal(im.release());
return;
}
- if (preParseImport) throw ParseException("preParseImport in global");
+ if (preParseImport)
+ throw ParseException("preParseImport in global");
global->type = type;
if (i < s.size()) {
global->init = parseExpression(s[i++]);
@@ -1762,21 +1953,25 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
throw ParseException("global without init", s.line, s.col);
}
global->mutable_ = mutable_;
- if (i != s.size()) throw ParseException("extra import elements");
- if (wasm.getGlobalOrNull(global->name)) throw ParseException("duplicate import", s.line, s.col);
+ if (i != s.size())
+ throw ParseException("extra import elements");
+ if (wasm.getGlobalOrNull(global->name))
+ throw ParseException("duplicate import", s.line, s.col);
wasm.addGlobal(global.release());
}
-
void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
- if (wasm.table.exists) throw ParseException("more than one table");
+ if (wasm.table.exists)
+ throw ParseException("more than one table");
wasm.table.exists = true;
Index i = 1;
- if (i == s.size()) return; // empty table in old notation
+ if (i == s.size())
+ return; // empty table in old notation
if (s[i]->dollared()) {
wasm.table.name = s[i++]->str();
}
- if (i == s.size()) return;
+ if (i == s.size())
+ return;
Name importModule, importBase;
if (s[i]->isList()) {
auto& inner = *s[i];
@@ -1785,11 +1980,13 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = wasm.table.name;
ex->kind = ExternalKind::Table;
- if (wasm.getExportOrNull(ex->name)) throw ParseException("duplicate export", s.line, s.col);
+ if (wasm.getExportOrNull(ex->name))
+ throw ParseException("duplicate export", s.line, s.col);
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
- if (!preParseImport) throw ParseException("!preParseImport in table");
+ if (!preParseImport)
+ throw ParseException("!preParseImport in table");
wasm.table.module = inner[1]->str();
wasm.table.base = inner[2]->str();
i++;
@@ -1797,19 +1994,23 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
throw ParseException("invalid table");
}
}
- if (i == s.size()) return;
+ if (i == s.size())
+ return;
if (!s[i]->dollared()) {
if (s[i]->str() == FUNCREF) {
// (table type (elem ..))
parseInnerElem(*s[i + 1]);
if (wasm.table.segments.size() > 0) {
- wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size();
+ wasm.table.initial = wasm.table.max =
+ wasm.table.segments[0].data.size();
} else {
wasm.table.initial = wasm.table.max = 0;
}
return;
}
- // first element isn't dollared, and isn't funcref. this could be old syntax for (table 0 1) which means function 0 and 1, or it could be (table initial max? type), look for type
+ // first element isn't dollared, and isn't funcref. this could be old syntax
+ // for (table 0 1) which means function 0 and 1, or it could be (table
+ // initial max? type), look for type
if (s[s.size() - 1]->str() == FUNCREF) {
// (table initial max? type)
if (i < s.size() - 1) {
@@ -1840,8 +2041,11 @@ void SExpressionWasmBuilder::parseElem(Element& s) {
parseInnerElem(s, i, offset);
}
-void SExpressionWasmBuilder::parseInnerElem(Element& s, Index i, Expression* offset) {
- if (!wasm.table.exists) throw ParseException("elem without table", s.line, s.col);
+void SExpressionWasmBuilder::parseInnerElem(Element& s,
+ Index i,
+ Expression* offset) {
+ if (!wasm.table.exists)
+ throw ParseException("elem without table", s.line, s.col);
if (!offset) {
offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
}
@@ -1867,7 +2071,8 @@ void SExpressionWasmBuilder::parseType(Element& s) {
type->params.push_back(stringToType(curr[j]->str()));
}
} else if (curr[0]->str() == RESULT) {
- if (curr.size() > 2) throw ParseException("invalid result arity", curr.line, curr.col);
+ if (curr.size() > 2)
+ throw ParseException("invalid result arity", curr.line, curr.col);
type->result = stringToType(curr[1]->str());
}
}
@@ -1875,7 +2080,8 @@ void SExpressionWasmBuilder::parseType(Element& s) {
type->name = Name::fromInt(wasm.functionTypes.size());
}
functionTypeNames.push_back(type->name);
- if (wasm.getFunctionTypeOrNull(type->name)) throw ParseException("duplicate function type", s.line, s.col);
+ if (wasm.getFunctionTypeOrNull(type->name))
+ throw ParseException("duplicate function type", s.line, s.col);
wasm.addFunctionType(std::move(type));
}