diff --git a/lld/test/ELF/lto/Inputs/undef-mixed2.ll b/lld/test/ELF/lto/Inputs/undef-mixed2.ll new file mode 100644 --- /dev/null +++ b/lld/test/ELF/lto/Inputs/undef-mixed2.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define hidden void @foo() { + ret void +} diff --git a/lld/test/ELF/lto/archive-mixed.ll b/lld/test/ELF/lto/archive-mixed.ll new file mode 100644 --- /dev/null +++ b/lld/test/ELF/lto/archive-mixed.ll @@ -0,0 +1,63 @@ +; REQUIRES: x86 +;; Show that whether an object is a bitcode file or regular ELF object does not +;; make any difference to which file is selected from an archive. + +; RUN: rm -rf %t.dir +; RUN: split-file %s %t.dir +; RUN: cd %t.dir + +; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux ref.s -o ref.o +; RUN: llvm-as a.ll -o a.bc +; RUN: llvm-as b.ll -o b.bc +; RUN: llc -filetype=obj a.ll -o a.o +; RUN: llc -filetype=obj b.ll -o b.o + +; RUN: llvm-ar rc a.bc.b.bc.a a.bc b.bc +; RUN: llvm-ar rc a.bc.b.o.a a.bc b.o +; RUN: llvm-ar rc a.o.b.bc.a a.o b.bc +; RUN: llvm-ar rc a.o.b.o.a a.o b.o +; RUN: llvm-ar rc other.bc.a a.bc +; RUN: llvm-ar rc other.o.a a.o + +; RUN: ld.lld -o /dev/null --trace ref.o a.bc.b.bc.a other.bc.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.bc.b.bc.a other.o.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.o.b.bc.a other.bc.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.o.b.bc.a other.o.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.bc.b.o.a other.bc.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.bc.b.o.a other.o.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +; RUN: ld.lld -o /dev/null --trace ref.o a.o.b.o.a other.bc.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} +;; Not an LTO test case, but here for completeness. +; RUN: ld.lld -o /dev/null --trace ref.o a.o.b.o.a other.o.a | \ +; RUN: FileCheck %s --implicit-check-not={{.}} + +; CHECK: ref.o +; CHECK-NEXT: a.{{.*}}.b.{{.*}}.a(b.{{.*}}) +; CHECK-NEXT: a.{{.*}}.b.{{.*}}.a(a.{{.*}}) + +;--- a.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux" +define void @bar() { + ret void +} + +;--- b.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux" +define void @foo() { + call void @bar() + ret void +} +declare void @bar() + +;--- ref.s +.global _start +_start: + call foo diff --git a/lld/test/ELF/lto/internalize-basic.ll b/lld/test/ELF/lto/internalize-basic.ll --- a/lld/test/ELF/lto/internalize-basic.ll +++ b/lld/test/ELF/lto/internalize-basic.ll @@ -7,6 +7,11 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" define void @_start() { + call void @bar() + ret void +} + +define hidden void @bar() { ret void } @@ -17,5 +22,6 @@ ; Check that _start is not internalized. ; CHECK: define dso_local void @_start() -; Check that foo function is correctly internalized. +; Check that the foo and bar functions are correctly internalized. +; CHECK: define internal void @bar() ; CHECK: define internal void @foo() diff --git a/lld/test/ELF/lto/undef-mixed2.s b/lld/test/ELF/lto/undef-mixed2.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/lto/undef-mixed2.s @@ -0,0 +1,21 @@ +## Show that a symbol referenced from an object and defined in bitcode is +## not internalized and is emitted in the output. +# REQUIRES: x86 +# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux +# RUN: llvm-as %p/Inputs/undef-mixed2.ll -o %t2.o +# RUN: ld.lld %t2.o %t.o -o %t.so -shared +# RUN: llvm-readobj --symbols %t.so | FileCheck %s + +# CHECK: Name: foo +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other [ +# CHECK-NEXT: STV_HIDDEN +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text + + .globl bar +bar: + call foo diff --git a/lld/test/ELF/lto/wrap-2.ll b/lld/test/ELF/lto/wrap-2.ll --- a/lld/test/ELF/lto/wrap-2.ll +++ b/lld/test/ELF/lto/wrap-2.ll @@ -1,28 +1,52 @@ ; REQUIRES: x86 -; LTO -; RUN: llvm-as %s -o %t.o -; RUN: llvm-as %S/Inputs/wrap-bar.ll -o %t1.o -; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar -; RUN: llvm-objdump -d %t.so | FileCheck %s -; RUN: llvm-readobj --symbols %t.so | FileCheck -check-prefix=BIND %s - -; ThinLTO -; RUN: opt -module-summary %s -o %t.o -; RUN: opt -module-summary %S/Inputs/wrap-bar.ll -o %t1.o -; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar -; RUN: llvm-objdump -d %t.so | FileCheck %s -; RUN: llvm-readobj --symbols %t.so | FileCheck -check-prefix=BIND %s - -; Make sure that calls in foo() are not eliminated and that bar is -; routed to __wrap_bar and __real_bar is routed to bar. +;; LTO + LTO +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-as %S/Inputs/wrap-bar.ll -o %t1.bc +; RUN: ld.lld %t.bc %t1.bc -shared -o %t.bc.bc.so -wrap=bar +; RUN: llvm-objdump -d %t.bc.bc.so | FileCheck %s --check-prefixes=CHECK,JMP +; RUN: llvm-readobj --symbols %t.bc.bc.so | FileCheck --check-prefix=BIND %s + +;; LTO + Object +; RUN: llc %S/Inputs/wrap-bar.ll -o %t1.o --filetype=obj +; RUN: ld.lld %t.bc %t1.o -shared -o %t.bc.o.so -wrap=bar +; RUN: llvm-objdump -d %t.bc.o.so | FileCheck %s --check-prefixes=CHECK,JMP +; RUN: llvm-readobj --symbols %t.bc.o.so | FileCheck --check-prefix=BIND %s + +;; Object + LTO +; RUN: llc %s -o %t.o --filetype=obj +; RUN: ld.lld %t.o %t1.bc -shared -o %t.o.bc.so -wrap=bar +; RUN: llvm-objdump -d %t.o.bc.so | FileCheck %s --check-prefixes=CHECK,CALL +; RUN: llvm-readobj --symbols %t.o.bc.so | FileCheck --check-prefix=BIND %s + +;; ThinLTO + ThinLTO +; RUN: opt -module-summary %s -o %t.thin +; RUN: opt -module-summary %S/Inputs/wrap-bar.ll -o %t1.thin +; RUN: ld.lld %t.thin %t1.thin -shared -o %t.thin.thin.so -wrap=bar +; RUN: llvm-objdump -d %t.thin.thin.so | FileCheck %s --check-prefixes=CHECK,JMP +; RUN: llvm-readobj --symbols %t.thin.thin.so | FileCheck --check-prefix=BIND %s + +;; ThinLTO + Object +; RUN: ld.lld %t.thin %t1.o -shared -o %t.thin.o.so -wrap=bar +; RUN: llvm-objdump -d %t.thin.o.so | FileCheck %s --check-prefixes=CHECK,JMP +; RUN: llvm-readobj --symbols %t.thin.o.so | FileCheck --check-prefix=BIND %s + +;; Object + ThinLTO +; RUN: ld.lld %t.o %t1.thin -shared -o %t.o.thin.so -wrap=bar +; RUN: llvm-objdump -d %t.o.thin.so | FileCheck %s --check-prefixes=CHECK,CALL +; RUN: llvm-readobj --symbols %t.o.thin.so | FileCheck --check-prefix=BIND %s + +;; Make sure that calls in foo() are not eliminated and that bar is +;; routed to __wrap_bar and __real_bar is routed to bar. ; CHECK: : ; CHECK-NEXT: pushq %rax ; CHECK-NEXT: callq{{.*}}<__wrap_bar> -; CHECK-NEXT: popq %rax -; CHECK-NEXT: jmp{{.*}} +; JMP-NEXT: popq %rax +; JMP-NEXT: jmp{{.*}} +; CALL-NEXT: callq{{.*}} +; CALL-NEXT: popq %rax -; Check that bar and __wrap_bar retain their original binding. +;; Check that bar and __wrap_bar retain their original binding. ; BIND: Name: bar ; BIND-NEXT: Value: ; BIND-NEXT: Size: