HEITZMANN Frédéric 218168 via llvm-dev
2016-May-12 13:26 UTC
[llvm-dev] Why LR is saved before calling a 'noreturn' function ?
Dear all, I don't get how llvm handles functions with __attribute__((noreturn)). It seems that LR register is backed up on the stack whilst it will never be used to return from a 'noreturn' function. I have this problem with a home-made backend but it seems that ARM flavour of clang has same behaviour. By the way, SP is also saved, I don't understand why. Is there a syntax error in my C code snippet ? Any idea on how to solve it in llvm ? ### C code snippet $ cat noreturn.c extern void bar(int* a) __attribute__((noreturn)); void foo(int* a) __attribute__ ((noreturn)); void foo(int* a){ bar(a); *a=42; } ### Generated assembly with target ARM $ clang --target=arm -S -O1 noreturn.c -o noreturn.s && cat noreturn.s clang: warning: unknown platform, assuming -mfloat-abi=soft clang: warning: unknown platform, assuming -mfloat-abi=soft .text .syntax unified .eabi_attribute 67, "2.09" @ Tag_conformance .cpu arm7tdmi .eabi_attribute 6, 2 @ Tag_CPU_arch .eabi_attribute 8, 1 @ Tag_ARM_ISA_use .eabi_attribute 17, 1 @ Tag_ABI_PCS_GOT_use .eabi_attribute 20, 1 @ Tag_ABI_FP_denormal .eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions .eabi_attribute 23, 3 @ Tag_ABI_FP_number_model .eabi_attribute 34, 0 @ Tag_CPU_unaligned_access .eabi_attribute 24, 1 @ Tag_ABI_align_needed .eabi_attribute 25, 1 @ Tag_ABI_align_preserved .eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format .eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t .eabi_attribute 26, 2 @ Tag_ABI_enum_size .eabi_attribute 14, 0 @ Tag_ABI_PCS_R9_use .file "noreturn.c" .globl foo .align 2 .type foo,%function foo: @ @foo .fnstart @ BB#0: @ %entry push {r11, lr} mov r11, sp bl bar .Lfunc_end0: .size foo, .Lfunc_end0-foo .cantunwind .fnend .ident "clang version 3.8.0 (git at git-lialp.intra.cea.fr:IL222352/wuc-clang.git d8f7ebf3bc146bce1b1b5e567484a56b60f2ec44) (git at git-lialp.intra.cea.fr:IL222352/wuc-llvm.git d2234a333ed3f101488a33ed3f58e2769cb8fda6)" .section ".note.GNU-stack","",%progbits ### Just to make sure : LLVM representation of the function has the attribute noreturn $ clang --target=arm -S -emit-llvm -O1 noreturn.c -o noreturn.ll && cat noreturn.ll ; ModuleID = 'noreturn.c' target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" target triple = "armv4t--" ; Function Attrs: noreturn nounwind define arm_aapcscc void @foo(i32* %a) #0 { entry: tail call arm_aapcscc void @bar(i32* %a) #2 unreachable } ; Function Attrs: noreturn declare arm_aapcscc void @bar(i32*) #1 attributes #0 = { noreturn nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="arm7tdmi" "target-features"="+soft-float,+strict-align,-crypto,-neon" "unsafe-fp-math"="false" "use-soft-float"="true" } attributes #1 = { noreturn "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="arm7tdmi" "target-features"="+soft-float,+strict-align,-crypto,-neon" "unsafe-fp-math"="false" "use-soft-float"="true" } attributes #2 = { noreturn nounwind } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 1, !"min_enum_size", i32 4} !2 = !{!"clang version 3.8.0 (git at git-lialp.intra.cea.fr:IL222352/wuc-clang.git d8f7ebf3bc146bce1b1b5e567484a56b60f2ec44) (git at git-lialp.intra.cea.fr:IL222352/wuc-llvm.git d2234a333ed3f101488a33ed3f58e2769cb8fda6)"} -- Frédéric Heitzmann
Tim Northover via llvm-dev
2016-May-12 14:00 UTC
[llvm-dev] Why LR is saved before calling a 'noreturn' function ?
Hi Frédéric, On 12 May 2016 at 06:26, HEITZMANN Frédéric 218168 <llvm-dev at lists.llvm.org> wrote:> I don't get how llvm handles functions with __attribute__((noreturn)). > It seems that LR register is backed up on the stack whilst it will never be used to return from a 'noreturn' function.In your case, Clang is producing a proper frame record. r11 is set to the address of a struct roughly this form: struct { void *previous_r11; void *return_address; }; This is necessary for producing a coherent backtraces and other usability features. It could be dropped with -fomit-frame-pointer, but we don't seem to take that opportunity. The code inserting that prologue is very late (and very fragile anyway) and it just happens not to bother with that optimization. The main place noreturn is used is for larger-scale optimizations earlier on (eliminating code after a noreturn call as dead, for example).> I have this problem with a home-made backend but it seems that ARM flavour of clang has same behaviour.To fix it, you'll want to look into XYZFrameLowering.cpp (and possibly code that ends up marking your LR as callee-saved in XYZCallingConv.td).> By the way, SP is also saved, I don't understand why.This is the frame pointer. Cheers. Tim.
HEITZMANN Frédéric 218168 via llvm-dev
2016-May-12 15:53 UTC
[llvm-dev] Why LR is saved before calling a 'noreturn' function ?
Hi Tim,> De : Tim Northover [mailto:t.p.northover at gmail.com] > In your case, Clang is producing a proper frame record. r11 is set to the > address of a struct roughly this form: > > struct { > void *previous_r11; > void *return_address; > }; > > This is necessary for producing a coherent backtraces and other usability > features.If I get your point, this additional instructions are need by gdb to rebuild the call stack. Strange that we cannot remove it if we want to save every tiny bit in a memory-constraint target. -fomit-frame-pointer does not change this.> To fix it, you'll want to look into XYZFrameLowering.cpp (and possibly code > that ends up marking your LR as callee-saved in XYZCallingConv.td). >You got it, LR was wrongly marked as callee-saved here. Thanks for you help. -- Fred
Joerg Sonnenberger via llvm-dev
2016-May-12 15:58 UTC
[llvm-dev] Why LR is saved before calling a 'noreturn' function ?
On Thu, May 12, 2016 at 01:26:56PM +0000, HEITZMANN Frédéric 218168 via llvm-dev wrote:> It seems that LR register is backed up on the stack whilst it will never be used to return from a 'noreturn' function.To keep the stack aligned? Joerg
Possibly Parallel Threads
- [cfe-dev] ARM float16 intrinsic test
- [LLVMdev] [Questions] clang cross compilation and SimpleScalar simulation
- [LLVMdev] [Questions] clang cross compilation and SimpleScalar simulation
- [LLVMdev] ARM c++ exceptions handling not working with clang/llvm-3.2?
- Substitute instruction with a jump to a library code