diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-12-10 16:59:18 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-12-10 16:59:18 -0500 |
commit | bfd65fee1403ca93e847ee2cbd109aca46d7e41c (patch) | |
tree | 4bf03606cca65d86c3e1c4917f1fadc0daa493f0 /src | |
parent | 3bb2ec9cbaece20ce5930db64aa82d2018bbc10d (diff) | |
download | binaryen-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.h | 2 | ||||
-rw-r--r-- | src/s2wasm-main.cpp | 43 | ||||
-rw-r--r-- | src/s2wasm.h | 218 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 1 |
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" |