diff --git a/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll @@ -0,0 +1,97 @@ +;; -ffunction-sections previously resulted in call relocations against the +;; .text.foo section symbol instead of the actual function symbol. +;; However, that results in a relocation against a symbol without the LSB set, +;; so the linker thinks it is not linking against a Thumb symbol. +;; Check that we use a relocation against the symbol for calls to functions +;; marked as dso_local (foo$local) +;; NB: Right now only R_ARM_PREL31 and R_ARM_ABS32 are converted to section +;; plus offset, so this test can't use a call. +; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections -o - --relocation-model=pic %s | FileCheck %s +; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections --filetype=obj -o %t --relocation-model=pic %s +; RUN: llvm-readobj -r --symbols %t | FileCheck %s --check-prefix=RELOCS +;; Do not autogen (we check directives that are normally filtered out): +; UTC-ARGS: --disable + +; RELOCS-LABEL: Relocations [ +; RELOCS-NEXT: Section (5) .rel.ARM.exidx.text._ZdlPv { +; RELOCS-NEXT: 0x0 R_ARM_PREL31 .text._ZdlPv +; RELOCS-NEXT: } +; RELOCS-NEXT: Section (7) .rel.text.test { +; RELOCS-NEXT: 0x4 R_ARM_CALL _ZdlPv +; FIXME: these two relocation should not be against the section! +; RELOCS-NEXT: 0xC R_ARM_ABS32 .text._ZdlPv +; RELOCS-NEXT: 0x10 R_ARM_ABS32 .text._ZdlPv +; RELOCS-NEXT: 0x1C R_ARM_REL32 _ZdlPv +; RELOCS-NEXT: } +; RELOCS-NEXT: Section (9) .rel.ARM.exidx.text.test { +; RELOCS-NEXT: 0x0 R_ARM_PREL31 .text.test +; RELOCS-NEXT: } +; RELOCS-NEXT: Section (11) .rel.data { +; RELOCS-NEXT: 0x0 R_ARM_ABS32 _ZdlPv +; RELOCS-NEXT: } +; RELOCS-NEXT: ] + +; RELOCS-LABEL: Symbols [ +; RELOCS: Symbol { +; FIXME: we should include the symbol in the symbol table! +; RELOCS-NOT: Name: .L_ZdlPv$local +; RELOCS-TODO: Name: .L_ZdlPv$local +; RELOCS-TODO: Value: 0x1 +; RELOCS-TODO: Size: 2 +; RELOCS-TODO: Binding: Local (0x0) +; RELOCS-TODO: Type: Function (0x2) +; RELOCS-TODO: Other: 0 +; RELOCS-TODO: Section: .text._ZdlPv ( +; RELOCS-TODO: } + +define dso_local void @_ZdlPv(ptr %ptr) local_unnamed_addr nounwind "target-features"="+armv7-a,+thumb-mode" { +; CHECK-LABEL: .section .text._ZdlPv,"ax",%progbits +; CHECK-NEXT: .globl _ZdlPv @ -- Begin function _ZdlPv +; CHECK-NEXT: .p2align 1 +; CHECK-NEXT: .type _ZdlPv,%function +; CHECK-NEXT: .code 16 @ @_ZdlPv +; CHECK-NEXT: .thumb_func +; CHECK-NEXT: _ZdlPv: +; CHECK-NEXT: .L_ZdlPv$local: +; CHECK-NEXT: .fnstart +; CHECK-NEXT: @ %bb.0: +; CHECK-NEXT: bx lr +; CHECK-NEXT: .Lfunc_end0: +; CHECK-NEXT: .size _ZdlPv, .Lfunc_end0-_ZdlPv +; CHECK-NEXT: .cantunwind +; CHECK-NEXT: .fnend + ret void +} + +define ptr @test(ptr %ptr) nounwind { +; CHECK-LABEL: test: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: .save {r11, lr} +; CHECK-NEXT: push {r11, lr} +; CHECK-NEXT: bl _ZdlPv{{$}} +; CHECK-NEXT: ldr r0, .LCPI1_0 +; CHECK-NEXT: @APP +; CHECK-NEXT: .long .L_ZdlPv$local +; CHECK-NEXT: @NO_APP +; CHECK-NEXT: @APP +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: .reloc .Ltmp0, R_ARM_ABS32, .L_ZdlPv$local +; CHECK-NEXT: .long 0 +; CHECK-NEXT: @NO_APP +; CHECK-NEXT: .LPC1_0: +; CHECK-NEXT: add r0, pc, r0 +; CHECK-NEXT: pop {r11, pc} +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: @ %bb.1: +; CHECK-NEXT: .LCPI1_0: +; CHECK-NEXT: .long _ZdlPv-(.LPC1_0+8) +entry: + call void @_ZdlPv(ptr %ptr) + ; This inline assembly is needed to highlight the missing Thumb LSB since + ; only R_ARM_ABS32 is converted to section+offset + tail call void asm sideeffect ".4byte .L_ZdlPv$$local", ""() + tail call void asm sideeffect ".reloc ., R_ARM_ABS32, .L_ZdlPv$$local\0A.4byte 0", ""() + ret ptr @_ZdlPv +} + +@fnptr = hidden local_unnamed_addr global ptr @_ZdlPv