diff --git a/cranelift/codegen/src/ir/function.rs b/cranelift/codegen/src/ir/function.rs index f5b85c50af80..885b1e2f0d29 100644 --- a/cranelift/codegen/src/ir/function.rs +++ b/cranelift/codegen/src/ir/function.rs @@ -314,7 +314,17 @@ impl FunctionStencil { pub fn is_leaf(&self) -> bool { // Conservative result: if there's at least one function signature referenced in this // function, assume it is not a leaf. - self.dfg.signatures.is_empty() + let has_signatures = !self.dfg.signatures.is_empty(); + + // Under some TLS models, retrieving the address of a TLS variable requires calling a + // function. Conservatively assume that any function that references a global value is not + // a leaf. + let has_tls = self.global_values.values().any(|gv| match gv { + GlobalValueData::Symbol { tls, .. } => *tls, + _ => false, + }); + + !has_signatures && !has_tls } /// Replace the `dst` instruction's data with the `src` instruction's data diff --git a/cranelift/filetests/filetests/isa/riscv64/tls-elf.clif b/cranelift/filetests/filetests/isa/riscv64/tls-elf.clif index 18e781b2fc0d..ab352c4f1b75 100644 --- a/cranelift/filetests/filetests/isa/riscv64/tls-elf.clif +++ b/cranelift/filetests/filetests/isa/riscv64/tls-elf.clif @@ -56,3 +56,54 @@ block0(v0: i32): ; addi sp, sp, 0x10 ; ret + + +function u0:1(i64) -> i64 system_v { +gv0 = symbol colocated tls u1:0 + +block0(v0: i64): + v1 = tls_value.i64 gv0 + v2 = iconst.i8 0 + store notrap v2, v1 + v3 = iconst.i64 0 + return v3 +} + +; VCode: +; add sp,-16 +; sd ra,8(sp) +; sd fp,0(sp) +; mv fp,sp +; block0: +; elf_tls_get_addr a0,userextname0 +; li a4,0 +; sb a4,0(a0) +; li a0,0 +; ld ra,8(sp) +; ld fp,0(sp) +; add sp,+16 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; addi sp, sp, -0x10 +; sd ra, 8(sp) +; sd s0, 0(sp) +; mv s0, sp +; block1: ; offset 0x10 +; auipc a0, 0 ; reloc_external RiscvTlsGdHi20 u1:0 0 +; mv a0, a0 ; reloc_external RiscvPCRelLo12I func+16 0 +; auipc t5, 0 +; ld t5, 0xc(t5) +; j 0xc +; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %ElfTlsGetAddr 0 +; .byte 0x00, 0x00, 0x00, 0x00 +; jalr t5 +; mv a4, zero +; sb a4, 0(a0) +; mv a0, zero +; ld ra, 8(sp) +; ld s0, 0(sp) +; addi sp, sp, 0x10 +; ret +