summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-12-10 16:59:18 -0500
committerAlon Zakai <alonzakai@gmail.com>2015-12-10 16:59:18 -0500
commitbfd65fee1403ca93e847ee2cbd109aca46d7e41c (patch)
tree4bf03606cca65d86c3e1c4917f1fadc0daa493f0 /src
parent3bb2ec9cbaece20ce5930db64aa82d2018bbc10d (diff)
downloadbinaryen-bfd65fee1403ca93e847ee2cbd109aca46d7e41c.tar.gz
binaryen-bfd65fee1403ca93e847ee2cbd109aca46d7e41c.tar.bz2
binaryen-bfd65fee1403ca93e847ee2cbd109aca46d7e41c.zip
process on s2wasm, and first working testcase
Diffstat (limited to 'src')
-rw-r--r--src/parsing.h2
-rw-r--r--src/s2wasm-main.cpp43
-rw-r--r--src/s2wasm.h218
-rw-r--r--src/wasm-s-parser.h1
4 files changed, 263 insertions, 1 deletions
diff --git a/src/parsing.h b/src/parsing.h
index 1a207a3ab..59e8fc5ae 100644
--- a/src/parsing.h
+++ b/src/parsing.h
@@ -1,4 +1,6 @@
+#include <sstream>
+
#include "wasm.h"
#include "shared-constants.h"
#include "mixed_arena.h"
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
new file mode 100644
index 000000000..011e4d164
--- /dev/null
+++ b/src/s2wasm-main.cpp
@@ -0,0 +1,43 @@
+//
+// wasm2asm console tool
+//
+
+#include "s2wasm.h"
+
+using namespace cashew;
+using namespace wasm;
+
+namespace wasm {
+int debug = 0;
+}
+
+int main(int argc, char **argv) {
+ debug = getenv("WASM2ASM_DEBUG") ? getenv("WASM2ASM_DEBUG")[0] - '0' : 0;
+
+ char *infile = argv[1];
+
+ if (debug) std::cerr << "loading '" << infile << "'...\n";
+ FILE *f = fopen(argv[1], "r");
+ assert(f);
+ fseek(f, 0, SEEK_END);
+ int size = ftell(f);
+ char *input = new char[size+1];
+ rewind(f);
+ int num = fread(input, 1, size, f);
+ // On Windows, ftell() gives the byte position (\r\n counts as two bytes), but when
+ // reading, fread() returns the number of characters read (\r\n is read as one char \n, and counted as one),
+ // so return value of fread can be less than size reported by ftell, and that is normal.
+ assert((num > 0 || size == 0) && num <= size);
+ fclose(f);
+ input[num] = 0;
+
+ if (debug) std::cerr << "parsing and wasming...\n";
+ AllocatingModule wasm;
+ S2WasmBuilder s2wasm(wasm, input);
+
+ if (debug) std::cerr << "printing...\n";
+ std::cout << wasm;
+
+ if (debug) std::cerr << "done.\n";
+}
+
diff --git a/src/s2wasm.h b/src/s2wasm.h
new file mode 100644
index 000000000..e6782a284
--- /dev/null
+++ b/src/s2wasm.h
@@ -0,0 +1,218 @@
+
+//
+// .s to WebAssembly translator.
+//
+
+#include "wasm.h"
+#include "parsing.h"
+
+namespace wasm {
+
+extern int debug; // wasm::debug is set in main(), typically from an env var
+
+//
+// S2WasmBuilder - parses a .s file into WebAssembly
+//
+
+class S2WasmBuilder {
+ AllocatingModule& wasm;
+ MixedArena& allocator;
+ char *s;
+
+public:
+ S2WasmBuilder(AllocatingModule& wasm, char *s) : wasm(wasm), allocator(wasm.allocator), s(s) {
+ process();
+ }
+
+private:
+ // utilities
+
+ void skipWhitespace() {
+ while (1) {
+ while (*s && isspace(*s)) s++;
+ if (*s != '#') break;
+ while (*s != '\n') s++;
+ }
+ }
+
+ void findComma() {
+ while (*s && *s != ',') s++;
+ s++;
+ skipWhitespace();
+ }
+
+ // match and skip the pattern, if matched
+ bool match(const char *pattern) {
+ size_t size = strlen(pattern);
+ if (strncmp(s, pattern, size) == 0) {
+ s += size;
+ skipWhitespace();
+ return true;
+ }
+ return false;
+ }
+
+ void mustMatch(const char *pattern) {
+ bool matched = match(pattern);
+ assert(matched);
+ }
+
+ #define abort_on(why) { \
+ printf("%s : %20s\n", why, s); \
+ abort(); \
+ }
+
+ void dump(const char *text) {
+ std::cerr << text << "\n==========\n" << s << "\n==========\n";
+ }
+
+ Name getStr() {
+ std::string str;
+ while (*s && !isspace(*s)) {
+ str += *s;
+ s++;
+ }
+ return cashew::IString(str.c_str(), false);
+ }
+
+ WasmType getType() {
+ if (match("i32")) return i32;
+ if (match("i64")) return i64;
+ if (match("f32")) return f32;
+ if (match("f64")) return f64;
+ abort_on("getType");
+ }
+
+ // state
+
+ typedef std::pair<Const*, Name> Addressing;
+ std::vector<Addressing> addressings;
+
+ // processors
+
+ void process() {
+ while (*s) {
+ skipWhitespace();
+ if (!*s) break;
+ if (*s != '.') break;
+ s++;
+ if (match("text")) parseText();
+ else if (match("data")) parseData();
+ else abort_on(s);
+ }
+ }
+
+ void parseText() {
+ while (*s) {
+ skipWhitespace();
+ if (!*s) break;
+ if (*s != '.') break;
+ s++;
+ if (match("file")) parseFile();
+ else if (match("globl")) parseGlobl();
+ else abort_on(s);
+ }
+ }
+
+ void parseFile() {
+ assert(*s == '"');
+ s++;
+ std::string filename;
+ while (*s != '"') {
+ filename += *s;
+ s++;
+ }
+ s++;
+ // TODO: use the filename?
+ }
+
+ void parseGlobl() {
+ unsigned nextId = 0;
+ auto getNextId = [&nextId]() {
+ return cashew::IString(('$' + std::to_string(nextId++)).c_str(), false);
+ };
+
+ Name name = getStr();
+ skipWhitespace();
+ mustMatch(".type");
+ mustMatch(name.str);
+ mustMatch(",@function");
+ mustMatch(name.str);
+ mustMatch(":");
+ auto func = allocator.alloc<Function>();
+ // params and result
+ while (1) {
+ if (match(".param")) {
+ while (1) {
+ func->params.emplace_back(getNextId(), getType());
+ skipWhitespace();
+ if (!match(",")) break;
+ }
+ } else if (match(".result")) {
+ func->result = getType();
+ } else break;
+ }
+ // parse body
+ auto currBlock = allocator.alloc<Block>();
+ func->body = currBlock;
+ std::vector<Expression*> stack;
+ auto push = [&](Expression* curr) {
+ stack.push_back(curr);
+ };
+ auto pop = [&]() {
+ Expression* ret = stack.back();
+ stack.pop_back();
+ return ret;
+ };
+ while (1) {
+ skipWhitespace();
+ if (match("i32.")) {
+ if (match("const")) {
+ mustMatch("$push");
+ findComma();
+ if (*s == '.') {
+ // global address
+ auto curr = allocator.alloc<Const>();
+ curr->type = i32;
+ addressings.emplace_back(curr, getStr());
+ push(curr);
+ } else {
+ // constant
+ push(parseConst(getStr(), i32, allocator));
+ }
+ }
+ } else if (match("return")) {
+ Block *temp;
+ if (!(func->body && (temp = func->body->dyn_cast<Block>()) && temp->name == FAKE_RETURN)) {
+ Expression* old = func->body;
+ temp = allocator.alloc<Block>();
+ temp->name = FAKE_RETURN;
+ if (old) temp->list.push_back(old);
+ func->body = temp;
+ }
+ auto curr = allocator.alloc<Break>();
+ curr->name = FAKE_RETURN;
+ if (*s == '$') {
+ getStr();
+ curr->value = pop();
+ }
+ currBlock->list.push_back(curr);
+ } else if (match("func_end0:")) {
+ mustMatch(".size");
+ mustMatch("main,");
+ mustMatch("func_end0-main");
+ wasm.addFunction(func);
+ return; // the function is done
+ } else {
+ break;
+ }
+ }
+ }
+
+ void parseData() {
+ abort();
+ }
+};
+
+} // namespace wasm
+
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index c84c93dc9..1600e41f5 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -5,7 +5,6 @@
//
#include <cmath>
-#include <sstream>
#include "wasm.h"
#include "mixed_arena.h"