summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/s2wasm.h7
-rw-r--r--src/wasm-linker.cpp21
-rw-r--r--src/wasm-linker.h12
-rw-r--r--test/dot_s/indidx.s93
-rw-r--r--test/dot_s/indidx.wast57
5 files changed, 188 insertions, 2 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 729e060f9..5614c7b58 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -639,6 +639,13 @@ class S2WasmBuilder {
}
} else if (match(".result")) {
resultType = getType();
+ } else if (match(".indidx")) {
+ int64_t indirectIndex = getInt64();
+ skipWhitespace();
+ if (indirectIndex < 0) {
+ abort_on("indidx");
+ }
+ linkerObj->addIndirectIndex(name, indirectIndex);
} else if (match(".local")) {
while (1) {
Name name = getNextId();
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 628e24ecc..3ff90cc0a 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -112,9 +112,30 @@ void Linker::layout() {
for (Name name : out.globls) exportFunction(name, false);
for (Name name : out.initializerFunctions) exportFunction(name, true);
+ // Pre-assign the function indexes
+ for (auto& pair : out.indirectIndexes) {
+ if (functionIndexes.count(pair.first) != 0 ||
+ functionNames.count(pair.second) != 0) {
+ Fatal() << "Function " << pair.first << " already has an index " <<
+ functionIndexes[pair.first] << " while setting index " << pair.second;
+ }
+ if (debug) {
+ std::cerr << "pre-assigned function index: " << pair.first << ": "
+ << pair.second << '\n';
+ }
+ functionIndexes[pair.first] = pair.second;
+ functionNames[pair.second] = pair.first;
+ }
+
+ // Emit the pre-assigned function names in sorted order
+ for (const auto& P : functionNames) {
+ out.wasm.table.names.push_back(P.second);
+ }
+
auto ensureFunctionIndex = [this](Name name) {
if (functionIndexes.count(name) == 0) {
functionIndexes[name] = out.wasm.table.names.size();
+ functionNames[functionIndexes[name]] = name;
out.wasm.table.names.push_back(name);
if (debug) {
std::cerr << "function index: " << name << ": "
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index 535b5dc55..701585190 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -141,6 +141,11 @@ class LinkerObject {
return f->second;
}
+ void addIndirectIndex(Name name, Address index) {
+ assert(!indirectIndexes.count(name));
+ indirectIndexes[name] = index;
+ }
+
bool isEmpty() {
return wasm.functions.empty();
}
@@ -173,6 +178,9 @@ class LinkerObject {
std::map<Name, Address> segments; // name => segment index (in wasm module)
+ // preassigned indexes for functions called indirectly
+ std::map<Name, Address> indirectIndexes;
+
std::vector<Name> initializerFunctions;
LinkerObject(const LinkerObject&) = delete;
@@ -309,8 +317,8 @@ class Linker {
std::unordered_map<cashew::IString, int32_t> staticAddresses; // name => address
std::unordered_map<Address, Address> segmentsByAddress; // address => segment index
- std::unordered_map<cashew::IString, size_t> functionIndexes;
-
+ std::unordered_map<cashew::IString, Address> functionIndexes;
+ std::map<Address, cashew::IString> functionNames;
};
diff --git a/test/dot_s/indidx.s b/test/dot_s/indidx.s
new file mode 100644
index 000000000..4ebd28af1
--- /dev/null
+++ b/test/dot_s/indidx.s
@@ -0,0 +1,93 @@
+ .text
+ .file "cfi-wasm.bs.bc"
+ .type a,@function
+a: # @a
+ .indidx 3
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, 0
+ # fallthrough-return: $pop0
+ .endfunc
+.Lfunc_end0:
+ .size a, .Lfunc_end0-a
+
+ .type b,@function
+b: # @b
+ .indidx 1
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, 1
+ # fallthrough-return: $pop0
+ .endfunc
+.Lfunc_end1:
+ .size b, .Lfunc_end1-b
+
+ .type c,@function
+c: # @c
+ .indidx 0
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, 2
+ # fallthrough-return: $pop0
+ .endfunc
+.Lfunc_end2:
+ .size c, .Lfunc_end2-c
+
+ .type d,@function
+d: # @d
+ .indidx 2
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, 3
+ # fallthrough-return: $pop0
+ .endfunc
+.Lfunc_end3:
+ .size d, .Lfunc_end3-d
+
+ .hidden main
+ .globl main
+ .type main,@function
+main: # @main
+ .param i32, i32
+ .result i32
+ .local i32
+# BB#0: # %entry
+ block
+ i32.call $push1=, getchar@FUNCTION
+ i32.const $push0=, 2
+ i32.shl $push2=, $pop1, $pop0
+ i32.const $push3=, .Lmain.fp-192
+ i32.add $push4=, $pop2, $pop3
+ i32.load $push9=, 0($pop4)
+ tee_local $push8=, $2=, $pop9
+ i32.const $push5=, 4
+ i32.ge_u $push6=, $pop8, $pop5
+ br_if 0, $pop6 # 0: down to label0
+# BB#1: # %cont
+ i32.call_indirect $push7=, $2
+ return $pop7
+.LBB4_2: # %trap
+ end_block # label0:
+ unreachable
+ unreachable
+ .endfunc
+.Lfunc_end4:
+ .size main, .Lfunc_end4-main
+
+ .type .Lmain.fp,@object # @main.fp
+ .section .data.rel.ro,"aw",@progbits
+ .p2align 4
+.Lmain.fp:
+ .int32 a@FUNCTION
+ .int32 b@FUNCTION
+ .int32 c@FUNCTION
+ .int32 d@FUNCTION
+ .size .Lmain.fp, 16
+
+ .type .L__unnamed_1,@object # @0
+ .section .rodata,"a",@progbits
+.L__unnamed_1:
+ .size .L__unnamed_1, 0
+
+
+ .ident "clang version 3.9.0 (trunk 271314) (llvm/trunk 271322)"
diff --git a/test/dot_s/indidx.wast b/test/dot_s/indidx.wast
new file mode 100644
index 000000000..7d0a56f66
--- /dev/null
+++ b/test/dot_s/indidx.wast
@@ -0,0 +1,57 @@
+(module
+ (memory 1
+ (segment 16 "\03\00\00\00\01\00\00\00\00\00\00\00\02\00\00\00")
+ )
+ (export "memory" memory)
+ (type $FUNCSIG$i (func (result i32)))
+ (import $getchar "env" "getchar" (result i32))
+ (export "main" $main)
+ (export "dynCall_i" $dynCall_i)
+ (table $c $b $d $a)
+ (func $a (type $FUNCSIG$i) (result i32)
+ (i32.const 0)
+ )
+ (func $b (type $FUNCSIG$i) (result i32)
+ (i32.const 1)
+ )
+ (func $c (type $FUNCSIG$i) (result i32)
+ (i32.const 2)
+ )
+ (func $d (type $FUNCSIG$i) (result i32)
+ (i32.const 3)
+ )
+ (func $main (param $0 i32) (param $1 i32) (result i32)
+ (local $2 i32)
+ (block $label$0
+ (br_if $label$0
+ (i32.ge_u
+ (set_local $2
+ (i32.load
+ (i32.add
+ (i32.shl
+ (call_import $getchar)
+ (i32.const 2)
+ )
+ (i32.const -176)
+ )
+ )
+ )
+ (i32.const 4)
+ )
+ )
+ (return
+ (call_indirect $FUNCSIG$i
+ (get_local $2)
+ )
+ )
+ )
+ (unreachable)
+ (unreachable)
+ )
+ (func $dynCall_i (param $fptr i32) (result i32)
+ (call_indirect $FUNCSIG$i
+ (get_local $fptr)
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 32, "initializers": [] }