diff options
-rw-r--r-- | src/s2wasm.h | 37 | ||||
-rw-r--r-- | test/dot_s/alias.s | 29 | ||||
-rw-r--r-- | test/dot_s/alias.wast | 22 |
3 files changed, 81 insertions, 7 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 5eeb808bb..8ef1135dd 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -66,6 +66,7 @@ private: std::vector<Relocation> relocations; std::set<Name> implementedFunctions; + std::map<Name, Name> aliasedFunctions; std::map<size_t, size_t> addressSegments; // address => segment index @@ -143,7 +144,7 @@ private: Name getStrToSep() { std::string str; - while (*s && !isspace(*s) && *s != ',' && *s != '(' && *s != ')' && *s != ':' && *s != '+' && *s != '-') { + while (*s && !isspace(*s) && *s != ',' && *s != '(' && *s != ')' && *s != ':' && *s != '+' && *s != '-' && *s != '=') { str += *s; s++; } @@ -257,16 +258,18 @@ private: return value; } - Name getCommaSeparated() { + Name getSeparated(char separator) { skipWhitespace(); std::string str; - while (*s && *s != ',' && *s != '\n') { + while (*s && *s != separator && *s != '\n') { str += *s; s++; } skipWhitespace(); return cashew::IString(str.c_str(), false); } + Name getCommaSeparated() { return getSeparated(','); } + Name getAtSeparated() { return getSeparated('@'); } Name getAssign() { skipWhitespace(); @@ -346,9 +349,17 @@ private: Name name = getCommaSeparated(); skipComma(); if (!match("@function")) continue; + if (match(".hidden")) mustMatch(name.str); mustMatch(name.str); - mustMatch(":"); - implementedFunctions.insert(name); + if (match(":")) { + implementedFunctions.insert(name); + } else if (match("=")) { + Name alias = getAtSeparated(); + mustMatch("@FUNCTION"); + aliasedFunctions.insert({name, alias}); + } else { + abort_on("unknown directive"); + } } } @@ -427,6 +438,12 @@ private: void parseFunction() { if (debug) dump("func"); Name name = getStrToSep(); + if (match(" =")) { + /* alias = */ getAtSeparated(); + mustMatch("@FUNCTION"); + return; + } + mustMatch(":"); unsigned nextId = 0; @@ -653,6 +670,8 @@ private: } else { assign = getAssign(); Name target = cleanFunction(getCommaSeparated()); + auto aliased = aliasedFunctions.find(target); + if (aliased != aliasedFunctions.end()) target = aliased->second; if (implementedFunctions.count(target) > 0) { auto specific = allocator.alloc<Call>(); specific->target = target; @@ -973,8 +992,12 @@ private: if (debug) dump("type"); Name name = getStrToSep(); skipComma(); - if (match("@function")) return parseFunction(); - else if (match("@object")) return parseObject(name); + if (match("@function")) { + if (match(".hidden")) mustMatch(name.str); + return parseFunction(); + } else if (match("@object")) { + return parseObject(name); + } abort_on("parseType"); } diff --git a/test/dot_s/alias.s b/test/dot_s/alias.s new file mode 100644 index 000000000..a29470b2f --- /dev/null +++ b/test/dot_s/alias.s @@ -0,0 +1,29 @@ + .text + .file "alias.c" + + .hidden __exit + .globl __exit + .type __exit,@function +__exit: # @__exit + .local i32 +# BB#0: # %entry + return + .endfunc +.Lfunc_end0: + .size __exit, .Lfunc_end0-__exit + + .hidden __needs_exit + .globl __needs_exit + .type __needs_exit,@function +__needs_exit: # @__needs_exit +# BB#0: # %entry + call __exit_needed@FUNCTION + return + .endfunc +.Lfunc_end1: + .size __needs_exit, .Lfunc_end1-__needs_exit + + .weak __exit_needed + .type __exit_needed,@function + .hidden __exit_needed +__exit_needed = __exit@FUNCTION diff --git a/test/dot_s/alias.wast b/test/dot_s/alias.wast new file mode 100644 index 000000000..41fb16f75 --- /dev/null +++ b/test/dot_s/alias.wast @@ -0,0 +1,22 @@ +(module + (memory 0 4294967295) + (export "__exit" $__exit) + (export "__needs_exit" $__needs_exit) + (func $__exit + (local $$0 i32) + (block $fake_return_waka123 + (block + (br $fake_return_waka123) + ) + ) + ) + (func $__needs_exit + (block $fake_return_waka123 + (block + (call $__exit) + (br $fake_return_waka123) + ) + ) + ) +) +;; METADATA: { "asmConsts": {},"staticBump": 4 } |