diff --git a/lld/test/ELF/lto/arm-rtlibcall.ll b/lld/test/ELF/lto/arm-rtlibcall.ll new file mode 100644 index 0000000000000..b254fa0c034e8 --- /dev/null +++ b/lld/test/ELF/lto/arm-rtlibcall.ll @@ -0,0 +1,126 @@ +; REQUIRES: arm +;; Test for LTO optimizing out references to symbols that are pulled in by +;; compiler-generated libcalls (post LTO). +;; Lazy files extracted post LTO compilation might reference other lazy files. +;; Referenced relocatable files are extracted and everything works as intended. +;; However, if the referenced lazy file is a bitcode file, no further LTO +;; compilation occurs. lld currently treats any symbols from that bitcode file +;; as absolute, which leads to a "refer to absolute symbol" error in PIC links +;; and leads to silently broken output. For example, lazy aeabi_ldivmod.o post +;; LTO extraction might call __divmoddi4 defined in an unextracted lazy bitcode +;; file (https://github.com/llvm/llvm-project/issues/127284). +; RUN: rm -rf %t && split-file %s %t && cd %t +; RUN: llvm-as divmoddi4.ll -o divmoddi4.bc +; RUN: llvm-mc -filetype=obj -triple=armv7-none-unknown-eabi aeabi_ldivmod.s -o aeabi_ldivmod.o +;; With an explicit __aebi_ldivmod call in the input IR this works as expected: +; RUN: llvm-as main-explicit.ll -o main-explicit-ldivmod.bc +; RUN: ld.lld main-explicit-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.explicit +; RUN: llvm-objdump -d -r -t out.explicit | FileCheck %s --check-prefix=GOOD-DUMP +; GOOD-DUMP-LABEL: SYMBOL TABLE: +; GOOD-DUMP: [[#]] g F .text 00000024 __aeabi_ldivmod +; GOOD-DUMP: [[#]] g F .text [[#]] __divmoddi4 +; GOOD-DUMP-LABEL: <__aeabi_ldivmod>: +; GOOD-DUMP: bl 0x20140 <__divmoddi4> @ imm = #0x28 + +;; But if the call is generated by ISel, we end up with an invalid reference: +; RUN: llvm-as main-implicit.ll -o main-implicit-ldivmod.bc +; RUN: ld.lld main-implicit-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.implicit +; RUN: llvm-objdump -d -r -t out.implicit | FileCheck %s --check-prefix=BAD-DUMP +;; We jump to address zero here and __divmoddi4 ends up being an absolute symbol: +; BAD-DUMP-LABEL: SYMBOL TABLE: +; BAD-DUMP: [[#]] g F .text 00000024 __aeabi_ldivmod +; BAD-DUMP: [[#]] g *ABS* 00000000 __divmoddi4 +; BAD-DUMP-LABEL: <__aeabi_ldivmod>: +; BAD-DUMP: bl 0x0 <__divmoddi4> +;; Linking with -pie complains about the invalid relocation (and even points back to the source files) +; RUN: not ld.lld main-implicit-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.pie --no-undefined -pie --no-dynamic-linker 2>&1 | FileCheck %s --check-prefix=PIE-ERROR +PIE-ERROR: ld.lld: error: relocation R_ARM_CALL cannot refer to absolute symbol: __divmoddi4 +PIE-ERROR-NEXT: >>> defined in divmoddi4.bc +PIE-ERROR-NEXT: >>> referenced by aeabi_ldivmod.o:(__aeabi_ldivmod) +;; Removing --start-lib/--end-lib also ensures that the reference is retained +; RUN: ld.lld main-implicit-ldivmod.bc aeabi_ldivmod.o divmoddi4.bc -o out.nolib +; RUN: llvm-objdump -d -r -t out.nolib | FileCheck %s --check-prefix=GOOD-DUMP + +;; Interestingly, just declaring __aeabi_ldivmod is sufficient to not run into this issue. +; RUN: llvm-as main-declared.ll -o main-declared-ldivmod.bc +; RUN: ld.lld main-declared-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.declared +; RUN: llvm-objdump -d -r -t out.declared | FileCheck %s --check-prefix=GOOD-DUMP + +;--- divmoddi4.ll +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7-none-unknown-eabi" + +; Adding it to llvm.used does not appears to have any effect! +;; @llvm.used = appending global [1 x ptr] [ptr @__divmoddi4], section "llvm.metadata" + +; Stub version of the real __divmoddi4 +define i64 @__divmoddi4(i64 %a, i64 %b, ptr writeonly %rem) #0 align 32 { +entry: + %sub = sub i64 %a, %b + store i64 0, ptr %rem, align 8 + ret i64 %sub +} + +attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } + +;--- aeabi_ldivmod.s +.syntax unified +.p2align 2 +.arm +.globl __aeabi_ldivmod +.type __aeabi_ldivmod,%function +__aeabi_ldivmod: + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] + bl __divmoddi4 + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +.size __aeabi_ldivmod, . - __aeabi_ldivmod + +;--- main-implicit.ll +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7-none-unknown-eabi" + +define dso_local i64 @_start(i64 %num, i64 %denom) local_unnamed_addr #0 { +entry: + %div = sdiv i64 %num, %denom + %ret = add i64 %div, 2 + ret i64 %ret +} + +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } + +;--- main-explicit.ll +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7-none-unknown-eabi" + +declare { i64, i64 } @__aeabi_ldivmod(i64, i64) + +define dso_local noundef i64 @_start(i64 noundef %num, i64 noundef %denom) local_unnamed_addr #0 { +entry: + %quotrem = call { i64, i64 } @__aeabi_ldivmod(i64 %num, i64 %denom) + %div = extractvalue { i64, i64 } %quotrem, 0 + %ret = add i64 %div, 2 + ret i64 %ret +} + +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } + +;--- main-declared.ll +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7-none-unknown-eabi" + +declare { i64, i64 } @__aeabi_ldivmod(i64, i64) + +define dso_local i64 @_start(i64 %num, i64 %denom) local_unnamed_addr #0 { +entry: + %div = sdiv i64 %num, %denom + %ret = add i64 %div, 2 + ret i64 %ret +} + +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" }