diff --git a/src/s2wasm.h b/src/s2wasm.h index 729e060f91b..5614c7b5873 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.h b/src/wasm-linker.h index af682b42d69..a0519273f5e 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -159,6 +159,11 @@ class LinkerObject { return f->second; } + void addIndirectIndex(Name name, uint64_t index) { + assert(!indirect_indexes.count(name)); + indirect_indexes[name] = index; + } + bool isEmpty() { return wasm.functions.empty(); } @@ -192,6 +197,8 @@ class LinkerObject { std::map segments; // name => segment index (in wasm module) std::map tables; // index => table index (in wasm module) + std::map indirect_indexes; + std::vector initializerFunctions; LinkerObject(const LinkerObject&) = delete; @@ -328,7 +335,8 @@ class Linker { std::unordered_map staticAddresses; // name => address std::unordered_map segmentsByAddress; // address => segment index - std::unordered_map> functionIndexes; // name => table, entry indexes + std::unordered_map> functionIndexes; // name => table, entry indexes + std::map functionNames; }; diff --git a/test/dot_s/indidx.s b/test/dot_s/indidx.s new file mode 100644 index 00000000000..9f9078dfdc8 --- /dev/null +++ b/test/dot_s/indidx.s @@ -0,0 +1,93 @@ + .text + .file "cfi-wasm.bs.bc" + .type a,@function +a: # @a + .indidx 0 + .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 2 + .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 3 + .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 00000000000..7051c07f969 --- /dev/null +++ b/test/dot_s/indidx.wast @@ -0,0 +1,57 @@ +(module + (memory 1 + (segment 16 "\00\00\00\00\01\00\00\00\02\00\00\00\03\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 $a $b $c $d) + (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": [] }