summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/s2wasm-main.cpp1
-rw-r--r--src/s2wasm.h58
-rw-r--r--src/wasm.h6
3 files changed, 65 insertions, 0 deletions
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
index 78f158509..694dc4a08 100644
--- a/src/s2wasm-main.cpp
+++ b/src/s2wasm-main.cpp
@@ -37,6 +37,7 @@ int main(int argc, char **argv) {
if (debug) std::cerr << "printing...\n";
std::cout << wasm;
+ s2wasm.printMeta(std::cout);
if (debug) std::cerr << "done.\n";
}
diff --git a/src/s2wasm.h b/src/s2wasm.h
index c21a8b0f8..bdeb78fdd 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -11,6 +11,8 @@ namespace wasm {
extern int debug; // wasm::debug is set in main(), typically from an env var
+cashew::IString EMSCRIPTEN_ASM_CONST("emscripten_asm_const");
+
//
// S2WasmBuilder - parses a .s file into WebAssembly
//
@@ -43,6 +45,8 @@ private:
std::set<Name> implementedFunctions;
+ std::map<size_t, size_t> addressSegments; // address => segment index
+
// utilities
void skipWhitespace() {
@@ -815,6 +819,7 @@ private:
while (nextStatic % align) nextStatic++;
// assign the address, add to memory
staticAddresses[name] = nextStatic;
+ addressSegments[nextStatic] = wasm.memory.segments.size();
wasm.memory.segments.emplace_back(nextStatic, (const char*)&(*raw)[0], seenSize);
nextStatic += seenSize;
}
@@ -844,6 +849,59 @@ private:
(*(int32_t*)(&(*raw)[0])) = staticAddresses[name];
}
}
+
+ template<class C>
+ void printSet(std::ostream& o, C& c) {
+ o << "[";
+ bool first = true;
+ for (auto& item : c) {
+ if (first) first = false;
+ else o << ",";
+ o << '"' << item << '"';
+ }
+ o << "]";
+ }
+
+public:
+
+ // emit metadata for emscripten integration
+ void printMeta(std::ostream& o) {
+ o << "; METADATA: { ";
+ // find asmConst calls, and emit their metadata
+ struct AsmConstWalker : public WasmWalker {
+ S2WasmBuilder* parent;
+ std::ostream& o;
+
+ std::map<std::string, std::set<std::string>> sigsForCode;
+
+ AsmConstWalker(S2WasmBuilder* parent) : parent(parent), o(o) {}
+
+ void visitCallImport(CallImport* curr) override {
+ if (curr->target == EMSCRIPTEN_ASM_CONST) {
+ auto arg = curr->operands[0]->cast<Const>();
+ size_t segmentIndex = parent->addressSegments[arg->value.geti32()];
+ std::string code = parent->wasm.memory.segments[segmentIndex].data;
+ std::string sig = getSig(curr);
+ sigsForCode[code].insert(sig);
+ }
+ }
+ };
+ AsmConstWalker walker(this);
+ walker.startWalk(&wasm);
+ o << "\"asmConsts\": {";
+ bool first = true;
+ for (auto& pair : walker.sigsForCode) {
+ auto& code = pair.first;
+ auto& sigs = pair.second;
+ if (first) first = false;
+ else o << ",";
+ o << '"' << code << '"' << ":";
+ printSet(o, sigs);
+ }
+ o << "}";
+
+ o << " }";
+ }
};
} // namespace wasm
diff --git a/src/wasm.h b/src/wasm.h
index 37aa495db..afc2cf88c 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -298,6 +298,12 @@ public:
return _id == T()._id ? (T*)this : nullptr;
}
+ template<class T>
+ T* cast() {
+ assert(_id == T()._id);
+ return (T*)this;
+ }
+
inline std::ostream& print(std::ostream &o, unsigned indent); // avoid virtual here, for performance
friend std::ostream& operator<<(std::ostream &o, Expression* expression) {