diff options
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r-- | src/s2wasm.h | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 46cf972c8..82675df1b 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -159,6 +159,7 @@ private: return cashew::IString(str.c_str(), false); } + // get an int int32_t getInt() { const char* loc = s; uint32_t value = 0; @@ -192,6 +193,15 @@ private: return value; } + // get an int from an arbitrary string, with our full error handling + int32_t getInt(const char *from) { + const char *before = s; + s = from; + auto ret = getInt(); + s = before; + return ret; + } + // gets a constant, which may be a relocation for later. // returns whether this is a relocation bool getConst(uint32_t* target) { @@ -343,7 +353,9 @@ private: } void prepare() { - staticAddresses["__stack_pointer"] = 0; // XXX HACK for now + assert(nextStatic == globalBase); // we are the first allocation + staticAddresses["__stack_pointer"] = nextStatic; + nextStatic += 4; } void process() { @@ -359,7 +371,7 @@ private: else if (match("imports")) skipImports(); else if (match("data")) {} else if (match("ident")) {} - else if (match("section") || match("align")) s = strchr(s, '\n'); + else if (match("section") || match("align") || match("p2align")) s = strchr(s, '\n'); else if (match("Lfunc_end")) { // skip the next line, which has a .size we can ignore s = strstr(s, ".size"); @@ -375,7 +387,8 @@ private: if (!*s) break; if (*s != '.') break; s++; - if (match("file")) parseFile(); + if (parseVersionMin()); + else if (match("file")) parseFile(); else if (match("globl")) parseGlobl(); else if (match("type")) parseType(); else { @@ -402,6 +415,15 @@ private: skipWhitespace(); } + bool parseVersionMin() { + if (match("watchos_version_min") || match("tvos_version_min") || match("ios_version_min") || match("macosx_version_min")) { + s = strchr(s, '\n'); + skipWhitespace(); + return true; + } else + return false; + } + void parseFunction() { if (debug) dump("func"); Name name = getStrToSep(); @@ -490,6 +512,10 @@ private: inputs[i] = curr; } if (*s == ')') s++; // tolerate 0(argument) syntax, where we started at the 'a' + if (*s == ':') { // tolerate :attribute=value syntax (see getAttributes) + s++; + skipToSep(); + } if (i < num - 1) skipComma(); } for (int i = num-1; i >= 0; i--) { @@ -513,6 +539,24 @@ private: addToBlock(set); } }; + auto getAttributes = [&](int num) { + const char *before = s; + std::vector<const char*> attributes; // TODO: optimize (if .s format doesn't change) + attributes.resize(num); + for (int i = 0; i < num; i++) { + skipToSep(); + if (*s == ')') s++; // tolerate 0(argument) syntax, where we started at the 'a' + if (*s == ':') { + attributes[i] = s + 1; + } else { + attributes[i] = nullptr; + } + if (i < num - 1) skipComma(); + } + s = before; + return attributes; + }; + // auto makeBinary = [&](BinaryOp op, WasmType type) { Name assign = getAssign(); skipComma(); @@ -557,9 +601,14 @@ private: match("_u"); Name assign = getAssign(); getConst(&curr->offset); - curr->align = curr->bytes; // XXX mustMatch("("); + auto attributes = getAttributes(1); curr->ptr = getInput(); + curr->align = curr->bytes; + if (attributes[0]) { + assert(strncmp(attributes[0], "p2align=", 8) == 0); + curr->align = pow(2, getInt(attributes[0] + 8)); + } setOutput(curr, assign); }; auto makeStore = [&](WasmType type) { @@ -568,12 +617,17 @@ private: curr->type = type; int32_t bytes = getInt(); curr->bytes = bytes > 0 ? bytes : getWasmTypeSize(type); - curr->align = curr->bytes; // XXX Name assign = getAssign(); getConst(&curr->offset); mustMatch("("); + auto attributes = getAttributes(2); auto inputs = getInputs(2); curr->ptr = inputs[0]; + curr->align = curr->bytes; + if (attributes[0]) { + assert(strncmp(attributes[0], "p2align=", 8) == 0); + curr->align = pow(2, getInt(attributes[0] + 8)); + } curr->value = inputs[1]; setOutput(curr, assign); }; @@ -930,7 +984,7 @@ private: mustMatch(name.str); skipWhitespace(); } - if (match(".align")) { + if (match(".align") || match(".p2align")) { align = getInt(); skipWhitespace(); } |