|
| 1 | +; REQUIRES: arm |
| 2 | +;; Test for LTO optimizing out references to symbols that are pulled in by |
| 3 | +;; compiler-generated libcalls (post LTO). |
| 4 | +;; Lazy files extracted post LTO compilation might reference other lazy files. |
| 5 | +;; Referenced relocatable files are extracted and everything works as intended. |
| 6 | +;; However, if the referenced lazy file is a bitcode file, no further LTO |
| 7 | +;; compilation occurs. lld currently treats any symbols from that bitcode file |
| 8 | +;; as absolute, which leads to a "refer to absolute symbol" error in PIC links |
| 9 | +;; and leads to silently broken output. For example, lazy aeabi_ldivmod.o post |
| 10 | +;; LTO extraction might call __divmoddi4 defined in an unextracted lazy bitcode |
| 11 | +;; file (https://github.com/llvm/llvm-project/issues/127284). |
| 12 | +; RUN: rm -rf %t && split-file %s %t && cd %t |
| 13 | +; RUN: llvm-as divmoddi4.ll -o divmoddi4.bc |
| 14 | +; RUN: llvm-mc -filetype=obj -triple=armv7-none-unknown-eabi aeabi_ldivmod.s -o aeabi_ldivmod.o |
| 15 | +;; With an explicit __aebi_ldivmod call in the input IR this works as expected: |
| 16 | +; RUN: llvm-as main-explicit.ll -o main-explicit-ldivmod.bc |
| 17 | +; RUN: ld.lld main-explicit-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.explicit |
| 18 | +; RUN: llvm-objdump -d -r -t out.explicit | FileCheck %s --check-prefix=GOOD-DUMP |
| 19 | +; GOOD-DUMP-LABEL: SYMBOL TABLE: |
| 20 | +; GOOD-DUMP: [[#]] g F .text 00000024 __aeabi_ldivmod |
| 21 | +; GOOD-DUMP: [[#]] g F .text [[#]] __divmoddi4 |
| 22 | +; GOOD-DUMP-LABEL: <__aeabi_ldivmod>: |
| 23 | +; GOOD-DUMP: bl 0x20140 <__divmoddi4> @ imm = #0x28 |
| 24 | + |
| 25 | +;; But if the call is generated by ISel, we end up with an invalid reference: |
| 26 | +; RUN: llvm-as main-implicit.ll -o main-implicit-ldivmod.bc |
| 27 | +; RUN: ld.lld main-implicit-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.implicit |
| 28 | +; RUN: llvm-objdump -d -r -t out.implicit | FileCheck %s --check-prefix=BAD-DUMP |
| 29 | +;; We jump to address zero here and __divmoddi4 ends up being an absolute symbol: |
| 30 | +; BAD-DUMP-LABEL: SYMBOL TABLE: |
| 31 | +; BAD-DUMP: [[#]] g F .text 00000024 __aeabi_ldivmod |
| 32 | +; BAD-DUMP: [[#]] g *ABS* 00000000 __divmoddi4 |
| 33 | +; BAD-DUMP-LABEL: <__aeabi_ldivmod>: |
| 34 | +; BAD-DUMP: bl 0x0 <__divmoddi4> |
| 35 | +;; Linking with -pie complains about the invalid relocation (and even points back to the source files) |
| 36 | +; 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 |
| 37 | +PIE-ERROR: ld.lld: error: relocation R_ARM_CALL cannot refer to absolute symbol: __divmoddi4 |
| 38 | +PIE-ERROR-NEXT: >>> defined in divmoddi4.bc |
| 39 | +PIE-ERROR-NEXT: >>> referenced by aeabi_ldivmod.o:(__aeabi_ldivmod) |
| 40 | +;; Removing --start-lib/--end-lib also ensures that the reference is retained |
| 41 | +; RUN: ld.lld main-implicit-ldivmod.bc aeabi_ldivmod.o divmoddi4.bc -o out.nolib |
| 42 | +; RUN: llvm-objdump -d -r -t out.nolib | FileCheck %s --check-prefix=GOOD-DUMP |
| 43 | + |
| 44 | +;; Interestingly, just declaring __aeabi_ldivmod is sufficient to not run into this issue. |
| 45 | +; RUN: llvm-as main-declared.ll -o main-declared-ldivmod.bc |
| 46 | +; RUN: ld.lld main-declared-ldivmod.bc --start-lib aeabi_ldivmod.o divmoddi4.bc --end-lib -o out.declared |
| 47 | +; RUN: llvm-objdump -d -r -t out.declared | FileCheck %s --check-prefix=GOOD-DUMP |
| 48 | + |
| 49 | +;--- divmoddi4.ll |
| 50 | +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| 51 | +target triple = "armv7-none-unknown-eabi" |
| 52 | + |
| 53 | +; Adding it to llvm.used does not appears to have any effect! |
| 54 | +;; @llvm.used = appending global [1 x ptr] [ptr @__divmoddi4], section "llvm.metadata" |
| 55 | + |
| 56 | +; Stub version of the real __divmoddi4 |
| 57 | +define i64 @__divmoddi4(i64 %a, i64 %b, ptr writeonly %rem) #0 align 32 { |
| 58 | +entry: |
| 59 | + %sub = sub i64 %a, %b |
| 60 | + store i64 0, ptr %rem, align 8 |
| 61 | + ret i64 %sub |
| 62 | +} |
| 63 | + |
| 64 | +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" } |
| 65 | + |
| 66 | +;--- aeabi_ldivmod.s |
| 67 | +.syntax unified |
| 68 | +.p2align 2 |
| 69 | +.arm |
| 70 | +.globl __aeabi_ldivmod |
| 71 | +.type __aeabi_ldivmod,%function |
| 72 | +__aeabi_ldivmod: |
| 73 | + push {r6, lr} |
| 74 | + sub sp, sp, #16 |
| 75 | + add r6, sp, #8 |
| 76 | + str r6, [sp] |
| 77 | + bl __divmoddi4 |
| 78 | + ldr r2, [sp, #8] |
| 79 | + ldr r3, [sp, #12] |
| 80 | + add sp, sp, #16 |
| 81 | + pop {r6, pc} |
| 82 | +.size __aeabi_ldivmod, . - __aeabi_ldivmod |
| 83 | + |
| 84 | +;--- main-implicit.ll |
| 85 | +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| 86 | +target triple = "armv7-none-unknown-eabi" |
| 87 | + |
| 88 | +define dso_local i64 @_start(i64 %num, i64 %denom) local_unnamed_addr #0 { |
| 89 | +entry: |
| 90 | + %div = sdiv i64 %num, %denom |
| 91 | + %ret = add i64 %div, 2 |
| 92 | + ret i64 %ret |
| 93 | +} |
| 94 | + |
| 95 | +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } |
| 96 | + |
| 97 | +;--- main-explicit.ll |
| 98 | +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| 99 | +target triple = "armv7-none-unknown-eabi" |
| 100 | + |
| 101 | +declare { i64, i64 } @__aeabi_ldivmod(i64, i64) |
| 102 | + |
| 103 | +define dso_local noundef i64 @_start(i64 noundef %num, i64 noundef %denom) local_unnamed_addr #0 { |
| 104 | +entry: |
| 105 | + %quotrem = call { i64, i64 } @__aeabi_ldivmod(i64 %num, i64 %denom) |
| 106 | + %div = extractvalue { i64, i64 } %quotrem, 0 |
| 107 | + %ret = add i64 %div, 2 |
| 108 | + ret i64 %ret |
| 109 | +} |
| 110 | + |
| 111 | +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } |
| 112 | + |
| 113 | +;--- main-declared.ll |
| 114 | +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| 115 | +target triple = "armv7-none-unknown-eabi" |
| 116 | + |
| 117 | +declare { i64, i64 } @__aeabi_ldivmod(i64, i64) |
| 118 | + |
| 119 | +define dso_local i64 @_start(i64 %num, i64 %denom) local_unnamed_addr #0 { |
| 120 | +entry: |
| 121 | + %div = sdiv i64 %num, %denom |
| 122 | + %ret = add i64 %div, 2 |
| 123 | + ret i64 %ret |
| 124 | +} |
| 125 | + |
| 126 | +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a15" } |
0 commit comments