Skip to content

aarch64: A number of issues with BTI and its implementation #14938

Open

Description

@alexcrichton

This test:

(module
  (func (export "f") (param i32) (result i32)
    (block $default
      (block $b1
        (block $b0
          local.get 0
          br_table $b0 $b1 $default)
        i32.const 10
        return)
      i32.const 20
      return)
    i32.const 30))

(assert_return (invoke "f" (i32.const 0)) (i32.const 10))
(assert_return (invoke "f" (i32.const 5)) (i32.const 30))

fails with:

$ cargo run --target aarch64-unknown-linux-gnu -- wast -Ccranelift-use-bti br-table.wast
qemu: uncaught target signal 4 (Illegal instruction) - core dumped

This test:

(module
  (tag $e (param i32))
  (func $throw (param i32)
    local.get 0
    throw $e)
  (func (export "f") (param i32) (result i32)
    (block $h (result i32)
      (try_table (catch $e $h)
        local.get 0
        call $throw)
      unreachable)))

(assert_return (invoke "f" (i32.const 5)) (i32.const 5))

fails with:

$ cargo run --target aarch64-unknown-linux-gnu -- wast -Ccranelift-use-bti try-table.wast
qemu: uncaught target signal 4 (Illegal instruction) - core dumped

This test:

(module
  (type $t (func (param i32) (result i32)))
  (table funcref (elem $g))
  (func $g (type $t)
    local.get 0
    i32.const 1
    i32.add)
  (func (export "f") (param i32) (result i32)
    local.get 0
    i32.const 0
    return_call_indirect (type $t)))

(assert_return (invoke "f" (i32.const 5)) (i32.const 6))

fails with:

$ cargo run --target aarch64-unknown-linux-gnu -- wast -Ccranelift-use-bti return-call-indirect.wast
qemu: uncaught target signal 4 (Illegal instruction) - core dumped

This test:

(module
  (type $t (func (param i32) (result i32)))
  (table funcref (elem $g))
  (func $g (type $t)
    local.get 0
    i32.const 1
    i32.add)
  (func (export "f") (param i32) (result i32)
    local.get 0
    i32.const 0
    call_indirect (type $t)))

(assert_return (invoke "f" (i32.const 5)) (i32.const 6))

fails with:

$ cargo run --target aarch64-unknown-linux-gnu -- wast -Ccranelift-use-bti -Ccranelift-sign-return-address call-indirect.wast
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
LLM summary, if useful
  • br_table default: since Cranelift/aarch64: fix br_tables with very large target count. #14826 the aarch64 jump-table sequence
    clamps the index and reaches the default block through the table, but
    visit_block_succs (inst_predicates.rs) still reports the default as
    a direct successor, so it gets no bti j. The expected output in
    filetests/isa/aarch64/bti.clif already shows this.
  • try_table handlers: the unwinder resumes into try_call handler
    blocks with br x4 (crates/unwinder/src/arch/aarch64.rs), but handler
    blocks aren't treated as indirect-branch targets, so they get no
    bti j.
  • return_call_indirect / return_call_ref: ReturnCallInd pins the
    target to x1 and emits br x1. The callee's bti c accepts br only
    from x16/x17.
  • call_indirect with sign_return_address: tail-convention
    functions sign with the zero-modifier key (paciaz) and skip bti c,
    assuming the PACI instruction is an implicit landing pad. Only
    paciasp/pacibsp are, so every blr into a Wasm function faults.
  • CLIF runtests don't catch any of this: the runner skips a target aarch64 use_bti line because cranelift-native never reports
    use_bti for the host, so runtests/br_table.clif's existing use_bti
    target never runs.

Activity

  1. added
    bugIncorrect behavior in the current implementation that needs fixing
    craneliftIssues related to the Cranelift code generator
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixingcraneliftIssues related to the Cranelift code generatorcranelift:area:aarch64Issues related to AArch64 backend.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions