[llvm] [WebAssembly] Implement lowering calls through funcref to call_ref when available (PR #162227)

Demetrius Kanios via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 14 16:42:23 PDT 2025


QuantumSegfault wrote:

...it works?

It compiles just fine `bin/llvm-mc -filetype=obj -mattr=+reference-types call_ref_test.s`

If I run that through `wasm-ld --allow-undefined --no-entry --export-dynamic` I get:
```wat
(module $-
  (type (;0;) (func (param i32)))
  (type (;1;) (func (param funcref)))
  (import "env" "__funcref_call_table" (table (;0;) 0 funcref))
  (memory (;0;) 2)
  (global $__stack_pointer (;0;) (mut i32) (i32.const 66560))
  (export "memory" (memory 0))
  (export "__stack_pointer" (global $__stack_pointer))
  (export "test_func" (func $test_func))
  (func $test_func (;0;) (type 1) (param funcref)
    (table.set 0
      (i32.const 0)
      (local.get 0))
    (call_indirect (type 0)
      (i32.const 32)
      (i32.const 0))
    (table.set 0
      (i32.const 0)
      (ref.null func))
  )
  (@producers
    (processed-by "clang" "20.1.8")
  )
  (@custom "target_features" (after code) "\08+\0bbulk-memory+\0fbulk-memory-opt+\16call-indirect-overlong+\0amultivalue+\0fmutable-globals+\13nontrapping-fptoint+\0freference-types+\08sign-ext")
)
```

The one thing that sticks out is that `__funcref_call_table` is not defined. Here is the output of obj2yaml after `llvm-mc`

```yaml
--- !WASM
FileHeader:
  Version:         0x1
Sections:
  - Type:            TYPE
    Signatures:
      - Index:           0
        ParamTypes:
          - FUNCREF
        ReturnTypes:     []
      - Index:           1
        ParamTypes:
          - I32
        ReturnTypes:     []
  - Type:            IMPORT
    Imports:
      - Module:          env
        Field:           __linear_memory
        Kind:            MEMORY
        Memory:
          Minimum:         0x0
      - Module:          env
        Field:           __funcref_call_table
        Kind:            TABLE
        Table:
          Index:           0
          ElemType:        FUNCREF
          Limits:
            Minimum:         0x0
  - Type:            FUNCTION
    FunctionTypes:   [ 0 ]
  - Type:            CODE
    Relocations:
      - Type:            R_WASM_TABLE_NUMBER_LEB
        Index:           1
        Offset:          0x8
      - Type:            R_WASM_TYPE_INDEX_LEB
        Index:           1
        Offset:          0x12
      - Type:            R_WASM_TABLE_NUMBER_LEB
        Index:           1
        Offset:          0x17
      - Type:            R_WASM_TABLE_NUMBER_LEB
        Index:           1
        Offset:          0x21
    Functions:
      - Index:           0
        Locals:          []
        Body:            410020002680808080004120410011818080800080808080004100D0702680808080000B
  - Type:            CUSTOM
    Name:            linking
    Version:         2
    SymbolTable:
      - Index:           0
        Kind:            FUNCTION
        Name:            test_func
        Flags:           [  ]
        Function:        0
      - Index:           1
        Kind:            TABLE
        Name:            __funcref_call_table
        Flags:           [ UNDEFINED ]
        Table:           0
  - Type:            CUSTOM
    Name:            producers
    Tools:
      - Name:            clang
        Version:         20.1.8
  - Type:            CUSTOM
    Name:            target_features
    Features:
      - Prefix:          USED
        Name:            bulk-memory
      - Prefix:          USED
        Name:            bulk-memory-opt
      - Prefix:          USED
        Name:            call-indirect-overlong
      - Prefix:          USED
        Name:            multivalue
      - Prefix:          USED
        Name:            mutable-globals
      - Prefix:          USED
        Name:            nontrapping-fptoint
      - Prefix:          USED
        Name:            reference-types
      - Prefix:          USED
        Name:            sign-ext
```

---

The symbol is created weak, just like the `__indirect_function_table`, but unlike that other table, it is never provided default contents. So maybe we just need to initialize the table somewhere? I'll look into it. I'm guessing that should be a separate PR?

https://github.com/llvm/llvm-project/pull/162227


More information about the llvm-commits mailing list