summaryrefslogtreecommitdiff
path: root/src/s2wasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r--src/s2wasm.h66
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();
}