aboutsummaryrefslogtreecommitdiff
path: root/test/ELF/lto
diff options
context:
space:
mode:
Diffstat (limited to 'test/ELF/lto')
-rw-r--r--test/ELF/lto/Inputs/archive-2.ll6
-rw-r--r--test/ELF/lto/Inputs/archive-3.ll5
-rw-r--r--test/ELF/lto/Inputs/archive.ll6
-rw-r--r--test/ELF/lto/Inputs/available-externally.ll6
-rw-r--r--test/ELF/lto/Inputs/comdat.s5
-rw-r--r--test/ELF/lto/Inputs/common.s1
-rw-r--r--test/ELF/lto/Inputs/drop-debug-info.bcbin0 -> 1152 bytes
-rw-r--r--test/ELF/lto/Inputs/drop-linkage.ll12
-rw-r--r--test/ELF/lto/Inputs/dynsym.s3
-rw-r--r--test/ELF/lto/Inputs/internalize-exportdyn.ll6
-rw-r--r--test/ELF/lto/Inputs/internalize-undef.ll6
-rw-r--r--test/ELF/lto/Inputs/irmover-error.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce-odr.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce.ll6
-rw-r--r--test/ELF/lto/Inputs/resolution.s4
-rw-r--r--test/ELF/lto/Inputs/save-temps.ll6
-rw-r--r--test/ELF/lto/Inputs/shared.s7
-rw-r--r--test/ELF/lto/Inputs/start-lib1.ll8
-rw-r--r--test/ELF/lto/Inputs/start-lib2.ll6
-rw-r--r--test/ELF/lto/Inputs/tls-mixed.s4
-rw-r--r--test/ELF/lto/Inputs/type-merge.ll8
-rw-r--r--test/ELF/lto/Inputs/type-merge2.ll8
-rw-r--r--test/ELF/lto/Inputs/undef-mixed.s3
-rw-r--r--test/ELF/lto/Inputs/unnamed-addr-lib.s6
-rw-r--r--test/ELF/lto/Inputs/visibility.s8
-rw-r--r--test/ELF/lto/archive-2.ll28
-rw-r--r--test/ELF/lto/archive-3.ll19
-rw-r--r--test/ELF/lto/archive.ll37
-rw-r--r--test/ELF/lto/asmundef.ll25
-rw-r--r--test/ELF/lto/available-externally.ll22
-rw-r--r--test/ELF/lto/combined-lto-object-name.ll14
-rw-r--r--test/ELF/lto/comdat.ll21
-rw-r--r--test/ELF/lto/comdat2.ll40
-rw-r--r--test/ELF/lto/common.ll31
-rw-r--r--test/ELF/lto/common2.ll24
-rw-r--r--test/ELF/lto/ctors.ll18
-rw-r--r--test/ELF/lto/discard-value-names.ll23
-rw-r--r--test/ELF/lto/drop-debug-info.ll9
-rw-r--r--test/ELF/lto/drop-linkage.ll14
-rw-r--r--test/ELF/lto/duplicated.ll10
-rw-r--r--test/ELF/lto/dynamic-list.ll25
-rw-r--r--test/ELF/lto/dynsym.ll25
-rw-r--r--test/ELF/lto/inline-asm.ll11
-rw-r--r--test/ELF/lto/internalize-basic.ll21
-rw-r--r--test/ELF/lto/internalize-exportdyn.ll47
-rw-r--r--test/ELF/lto/internalize-llvmused.ll20
-rw-r--r--test/ELF/lto/internalize-undef.ll16
-rw-r--r--test/ELF/lto/internalize-version-script.ll22
-rw-r--r--test/ELF/lto/invalid-bitcode.ll12
-rw-r--r--test/ELF/lto/irmover-error.ll12
-rw-r--r--test/ELF/lto/linkage.ll20
-rw-r--r--test/ELF/lto/linkonce-odr.ll17
-rw-r--r--test/ELF/lto/linkonce.ll17
-rw-r--r--test/ELF/lto/lto-start.ll23
-rw-r--r--test/ELF/lto/ltopasses-basic.ll18
-rw-r--r--test/ELF/lto/ltopasses-custom.ll30
-rw-r--r--test/ELF/lto/metadata.ll13
-rw-r--r--test/ELF/lto/mix-platforms.ll10
-rw-r--r--test/ELF/lto/module-asm.ll19
-rw-r--r--test/ELF/lto/opt-level.ll29
-rw-r--r--test/ELF/lto/parallel-internalize.ll57
-rw-r--r--test/ELF/lto/parallel.ll24
-rw-r--r--test/ELF/lto/pic.ll20
-rw-r--r--test/ELF/lto/relax-relocs.ll15
-rw-r--r--test/ELF/lto/resolution.ll27
-rw-r--r--test/ELF/lto/save-temps.ll20
-rw-r--r--test/ELF/lto/shlib-undefined.ll27
-rw-r--r--test/ELF/lto/start-lib.ll27
-rw-r--r--test/ELF/lto/tls-mixed.ll10
-rw-r--r--test/ELF/lto/tls-preserve.ll25
-rw-r--r--test/ELF/lto/type-merge.ll26
-rw-r--r--test/ELF/lto/type-merge2.ll27
-rw-r--r--test/ELF/lto/undef-mixed.ll22
-rw-r--r--test/ELF/lto/undef-weak.ll29
-rw-r--r--test/ELF/lto/undef.ll20
-rw-r--r--test/ELF/lto/undefined-puts.ll28
-rw-r--r--test/ELF/lto/unnamed-addr-comdat.ll11
-rw-r--r--test/ELF/lto/unnamed-addr-lib.ll21
-rw-r--r--test/ELF/lto/unnamed-addr.ll14
-rw-r--r--test/ELF/lto/verify-invalid.ll17
-rw-r--r--test/ELF/lto/version-script.ll50
-rw-r--r--test/ELF/lto/visibility.ll35
-rw-r--r--test/ELF/lto/weak.ll16
83 files changed, 1452 insertions, 0 deletions
diff --git a/test/ELF/lto/Inputs/archive-2.ll b/test/ELF/lto/Inputs/archive-2.ll
new file mode 100644
index 000000000000..8236cfe5cd84
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive-2.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/archive-3.ll b/test/ELF/lto/Inputs/archive-3.ll
new file mode 100644
index 000000000000..ad8fb1e33ef2
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive-3.ll
@@ -0,0 +1,5 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/archive.ll b/test/ELF/lto/Inputs/archive.ll
new file mode 100644
index 000000000000..71c1e4f35600
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/available-externally.ll b/test/ELF/lto/Inputs/available-externally.ll
new file mode 100644
index 000000000000..b8583eab829d
--- /dev/null
+++ b/test/ELF/lto/Inputs/available-externally.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @zed() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/comdat.s b/test/ELF/lto/Inputs/comdat.s
new file mode 100644
index 000000000000..6f6e5ae1d9df
--- /dev/null
+++ b/test/ELF/lto/Inputs/comdat.s
@@ -0,0 +1,5 @@
+ .section .text.f,"axG",@progbits,c,comdat
+ .globl foo
+
+foo:
+ retq
diff --git a/test/ELF/lto/Inputs/common.s b/test/ELF/lto/Inputs/common.s
new file mode 100644
index 000000000000..e2cd9e6d50c3
--- /dev/null
+++ b/test/ELF/lto/Inputs/common.s
@@ -0,0 +1 @@
+ .comm a,8,4
diff --git a/test/ELF/lto/Inputs/drop-debug-info.bc b/test/ELF/lto/Inputs/drop-debug-info.bc
new file mode 100644
index 000000000000..f9c471f8e0d1
--- /dev/null
+++ b/test/ELF/lto/Inputs/drop-debug-info.bc
Binary files differ
diff --git a/test/ELF/lto/Inputs/drop-linkage.ll b/test/ELF/lto/Inputs/drop-linkage.ll
new file mode 100644
index 000000000000..0e3dc7a41421
--- /dev/null
+++ b/test/ELF/lto/Inputs/drop-linkage.ll
@@ -0,0 +1,12 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+define linkonce void @foo() comdat {
+ ret void
+}
+
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/dynsym.s b/test/ELF/lto/Inputs/dynsym.s
new file mode 100644
index 000000000000..a69f870a1b60
--- /dev/null
+++ b/test/ELF/lto/Inputs/dynsym.s
@@ -0,0 +1,3 @@
+.globl foo
+foo:
+ret
diff --git a/test/ELF/lto/Inputs/internalize-exportdyn.ll b/test/ELF/lto/Inputs/internalize-exportdyn.ll
new file mode 100644
index 000000000000..21ac3580762c
--- /dev/null
+++ b/test/ELF/lto/Inputs/internalize-exportdyn.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define weak_odr void @bah() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/internalize-undef.ll b/test/ELF/lto/Inputs/internalize-undef.ll
new file mode 100644
index 000000000000..71c1e4f35600
--- /dev/null
+++ b/test/ELF/lto/Inputs/internalize-undef.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/irmover-error.ll b/test/ELF/lto/Inputs/irmover-error.ll
new file mode 100644
index 000000000000..86ed259b2a00
--- /dev/null
+++ b/test/ELF/lto/Inputs/irmover-error.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+!0 = !{ i32 1, !"foo", i32 2 }
+
+!llvm.module.flags = !{ !0 }
diff --git a/test/ELF/lto/Inputs/linkonce-odr.ll b/test/ELF/lto/Inputs/linkonce-odr.ll
new file mode 100644
index 000000000000..0b3828846eb5
--- /dev/null
+++ b/test/ELF/lto/Inputs/linkonce-odr.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define linkonce_odr void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/linkonce.ll b/test/ELF/lto/Inputs/linkonce.ll
new file mode 100644
index 000000000000..a6738b3ad71e
--- /dev/null
+++ b/test/ELF/lto/Inputs/linkonce.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define linkonce void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/resolution.s b/test/ELF/lto/Inputs/resolution.s
new file mode 100644
index 000000000000..60b7870efbf4
--- /dev/null
+++ b/test/ELF/lto/Inputs/resolution.s
@@ -0,0 +1,4 @@
+ .data
+ .global a
+a:
+ .long 9
diff --git a/test/ELF/lto/Inputs/save-temps.ll b/test/ELF/lto/Inputs/save-temps.ll
new file mode 100644
index 000000000000..d6e6eb661f33
--- /dev/null
+++ b/test/ELF/lto/Inputs/save-temps.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @bar() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/shared.s b/test/ELF/lto/Inputs/shared.s
new file mode 100644
index 000000000000..ab79ed131c3f
--- /dev/null
+++ b/test/ELF/lto/Inputs/shared.s
@@ -0,0 +1,7 @@
+.globl printf
+.type printf, @function
+printf:
+
+.globl puts
+.type puts, @function
+puts:
diff --git a/test/ELF/lto/Inputs/start-lib1.ll b/test/ELF/lto/Inputs/start-lib1.ll
new file mode 100644
index 000000000000..9f42e6afff0f
--- /dev/null
+++ b/test/ELF/lto/Inputs/start-lib1.ll
@@ -0,0 +1,8 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/start-lib2.ll b/test/ELF/lto/Inputs/start-lib2.ll
new file mode 100644
index 000000000000..68b3c8362808
--- /dev/null
+++ b/test/ELF/lto/Inputs/start-lib2.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @bar() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/tls-mixed.s b/test/ELF/lto/Inputs/tls-mixed.s
new file mode 100644
index 000000000000..b31ae3dd54d1
--- /dev/null
+++ b/test/ELF/lto/Inputs/tls-mixed.s
@@ -0,0 +1,4 @@
+.globl foo
+.section .tbss,"awT",@nobits
+foo:
+.long 0
diff --git a/test/ELF/lto/Inputs/type-merge.ll b/test/ELF/lto/Inputs/type-merge.ll
new file mode 100644
index 000000000000..c31642105f3a
--- /dev/null
+++ b/test/ELF/lto/Inputs/type-merge.ll
@@ -0,0 +1,8 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @zed() {
+ call void @bar()
+ ret void
+}
+declare void @bar()
diff --git a/test/ELF/lto/Inputs/type-merge2.ll b/test/ELF/lto/Inputs/type-merge2.ll
new file mode 100644
index 000000000000..79fd1f886306
--- /dev/null
+++ b/test/ELF/lto/Inputs/type-merge2.ll
@@ -0,0 +1,8 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%zed = type { i16 }
+define void @bar(%zed* %this) {
+ store %zed* %this, %zed** null
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/undef-mixed.s b/test/ELF/lto/Inputs/undef-mixed.s
new file mode 100644
index 000000000000..2e4b7e114bb5
--- /dev/null
+++ b/test/ELF/lto/Inputs/undef-mixed.s
@@ -0,0 +1,3 @@
+ .globl bar
+bar:
+ retq
diff --git a/test/ELF/lto/Inputs/unnamed-addr-lib.s b/test/ELF/lto/Inputs/unnamed-addr-lib.s
new file mode 100644
index 000000000000..e6ebce024f05
--- /dev/null
+++ b/test/ELF/lto/Inputs/unnamed-addr-lib.s
@@ -0,0 +1,6 @@
+ .protected foo
+ .global foo
+foo:
+
+ .global bar
+bar:
diff --git a/test/ELF/lto/Inputs/visibility.s b/test/ELF/lto/Inputs/visibility.s
new file mode 100644
index 000000000000..db1379cc441f
--- /dev/null
+++ b/test/ELF/lto/Inputs/visibility.s
@@ -0,0 +1,8 @@
+ .global g
+g:
+ ret
+
+ .data
+ .global a
+a:
+ .long 41
diff --git a/test/ELF/lto/archive-2.ll b/test/ELF/lto/archive-2.ll
new file mode 100644
index 000000000000..6712d60c11e3
--- /dev/null
+++ b/test/ELF/lto/archive-2.ll
@@ -0,0 +1,28 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive-2.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.a -o %t3
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o --whole-archive %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+
+; CHECK: Name: _start (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @g() {
+ call void @_start()
+ ret void
+}
+
+declare void @_start()
+
diff --git a/test/ELF/lto/archive-3.ll b/test/ELF/lto/archive-3.ll
new file mode 100644
index 000000000000..350c8929c9df
--- /dev/null
+++ b/test/ELF/lto/archive-3.ll
@@ -0,0 +1,19 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive-3.ll -o %t1.o
+; RUN: llvm-as %s -o %t2.o
+
+; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t3 -save-temps
+; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: ld.lld -m elf_x86_64 %t.a %t1.o %t2.o -o %t3 -save-temps
+; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+
+; CHECK: define internal void @foo() {
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/archive.ll b/test/ELF/lto/archive.ll
new file mode 100644
index 000000000000..b3f69fb9920f
--- /dev/null
+++ b/test/ELF/lto/archive.ll
@@ -0,0 +1,37 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o --whole-archive %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+
+
+; CHECK: Name: g (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+; CHECK: Name: f (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+declare void @f()
+
diff --git a/test/ELF/lto/asmundef.ll b/test/ELF/lto/asmundef.ll
new file mode 100644
index 000000000000..d76e418fce81
--- /dev/null
+++ b/test/ELF/lto/asmundef.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t -save-temps
+; RUN: llvm-dis %t.lto.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".weak patatino"
+module asm ".equ patatino, foo"
+
+declare void @patatino()
+
+define void @foo() {
+ ret void
+}
+
+define void @_start() {
+ call void @patatino()
+ ret void
+}
+
+; CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
+; CHECK: define internal void @foo
+
diff --git a/test/ELF/lto/available-externally.ll b/test/ELF/lto/available-externally.ll
new file mode 100644
index 000000000000..74aa86002c9e
--- /dev/null
+++ b/test/ELF/lto/available-externally.ll
@@ -0,0 +1,22 @@
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o
+; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps
+; RUN: llvm-dis < %t.so.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void @bar()
+ call void @zed()
+ ret void
+}
+define available_externally void @bar() {
+ ret void
+}
+define available_externally void @zed() {
+ ret void
+}
+
+; CHECK: define available_externally void @bar() {
+; CHECK: define void @zed() {
diff --git a/test/ELF/lto/combined-lto-object-name.ll b/test/ELF/lto/combined-lto-object-name.ll
new file mode 100644
index 000000000000..f5b7e3ae40e6
--- /dev/null
+++ b/test/ELF/lto/combined-lto-object-name.ll
@@ -0,0 +1,14 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2 2>&1 | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @foo()
+define void @_start() {
+ call void @foo()
+ ret void
+}
+
+; CHECK: undefined symbol: foo in {{.*}}combined-lto-object-name.ll.tmp.o
diff --git a/test/ELF/lto/comdat.ll b/test/ELF/lto/comdat.ll
new file mode 100644
index 000000000000..e1384d0abd23
--- /dev/null
+++ b/test/ELF/lto/comdat.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: foo
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+define void @foo() comdat {
+ ret void
+}
+
diff --git a/test/ELF/lto/comdat2.ll b/test/ELF/lto/comdat2.ll
new file mode 100644
index 000000000000..1509585f1553
--- /dev/null
+++ b/test/ELF/lto/comdat2.ll
@@ -0,0 +1,40 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.o -o %t2.so -shared
+; RUN: llvm-readobj -t %t2.so | FileCheck %s --check-prefix=OTHER
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$c = comdat any
+
+define protected void @foo() comdat($c) {
+ ret void
+}
+
+; CHECK: Symbol {
+; CHECK: Name: foo
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other [
+; CHECK-NEXT: STV_PROTECTED
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+; OTHER: Symbol {
+; OTHER: Name: foo
+; OTHER-NEXT: Value: 0x1000
+; OTHER-NEXT: Size: 0
+; OTHER-NEXT: Binding: Global
+; OTHER-NEXT: Type: None
+; OTHER-NEXT: Other [
+; OTHER-NEXT: STV_PROTECTED
+; OTHER-NEXT: ]
+; OTHER-NEXT: Section: .text
+; OTHER-NEXT: }
diff --git a/test/ELF/lto/common.ll b/test/ELF/lto/common.ll
new file mode 100644
index 000000000000..b02002431320
--- /dev/null
+++ b/test/ELF/lto/common.ll
@@ -0,0 +1,31 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -s -t %t.so | FileCheck %s
+
+; CHECK: Name: .bss
+; CHECK-NEXT: Type: SHT_NOBITS
+; CHECK-NEXT: Flags [
+; CHECK-NEXT: SHF_ALLOC
+; CHECK-NEXT: SHF_WRITE
+; CHECK-NEXT: ]
+; CHECK-NEXT: Address:
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Link: 0
+; CHECK-NEXT: Info: 0
+; CHECK-NEXT: AddressAlignment: 8
+
+; CHECK: Name: a
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Object
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .bss
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = common global i32 0, align 8
diff --git a/test/ELF/lto/common2.ll b/test/ELF/lto/common2.ll
new file mode 100644
index 000000000000..59a2676e4fc9
--- /dev/null
+++ b/test/ELF/lto/common2.ll
@@ -0,0 +1,24 @@
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SHARED
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = common global i8 0, align 8
+
+; Shared library case, we ensure that the bitcode generated file
+; has not the a symbol but is appears in the final shared library
+; produced.
+; CHECK-NOT: @a = common global i8 0, align 8
+
+; SHARED: Symbol {
+; SHARED: Name: a
+; SHARED-NEXT: Value: 0x2000
+; SHARED-NEXT: Size: 1
+; SHARED-NEXT: Binding: Global
+; SHARED-NEXT: Type: Object
+; SHARED-NEXT: Other: 0
+; SHARED-NEXT: Section: .bss
+; SHARED-NEXT: }
diff --git a/test/ELF/lto/ctors.ll b/test/ELF/lto/ctors.ll
new file mode 100644
index 000000000000..7fce645f28f6
--- /dev/null
+++ b/test/ELF/lto/ctors.ll
@@ -0,0 +1,18 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-readobj -sections %t.so | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define void @ctor() {
+ call void asm "nop", ""()
+ ret void
+}
+
+; The llvm.global_ctors should end up producing constructors.
+; On x86-64 (linux) we should always emit .init_array and never .ctors.
+; CHECK: Name: .init_array
+; CHECK-NOT: Name: .ctors
diff --git a/test/ELF/lto/discard-value-names.ll b/test/ELF/lto/discard-value-names.ll
new file mode 100644
index 000000000000..c6cd94fd2e18
--- /dev/null
+++ b/test/ELF/lto/discard-value-names.ll
@@ -0,0 +1,23 @@
+; RUN: llvm-as %s -o %t.o
+
+; RUN: ld.lld -m elf_x86_64 -shared -save-temps %t.o -o %t2.o
+; RUN: llvm-dis < %t2.o.lto.bc | FileCheck %s
+
+; CHECK: @GlobalValueName
+; CHECK: @foo(i32 %in)
+; CHECK: somelabel:
+; CHECK: %GV = load i32, i32* @GlobalValueName
+; CHECK: %add = add i32 %in, %GV
+; CHECK: ret i32 %add
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@GlobalValueName = global i32 0
+
+define i32 @foo(i32 %in) {
+somelabel:
+ %GV = load i32, i32* @GlobalValueName
+ %add = add i32 %in, %GV
+ ret i32 %add
+}
diff --git a/test/ELF/lto/drop-debug-info.ll b/test/ELF/lto/drop-debug-info.ll
new file mode 100644
index 000000000000..7a7ed5ea41d1
--- /dev/null
+++ b/test/ELF/lto/drop-debug-info.ll
@@ -0,0 +1,9 @@
+; REQUIRES: x86
+;
+; drop-debug-info.bc was created from "void f(void) {}" with clang 3.5 and
+; -gline-tables-only, so it contains old debug info.
+;
+; RUN: ld.lld -m elf_x86_64 -shared %p/Inputs/drop-debug-info.bc \
+; RUN: -disable-verify 2>&1 | FileCheck %s
+; CHECK: warning: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc
+
diff --git a/test/ELF/lto/drop-linkage.ll b/test/ELF/lto/drop-linkage.ll
new file mode 100644
index 000000000000..fd111c18bd13
--- /dev/null
+++ b/test/ELF/lto/drop-linkage.ll
@@ -0,0 +1,14 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; REQUIRES: x86
+; RUN: llc %s -o %t.o -filetype=obj
+; RUN: llvm-as %p/Inputs/drop-linkage.ll -o %t2.o
+; RUN: ld.lld %t.o %t2.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+define void @foo() {
+ ret void
+}
+
+; CHECK: declare void @foo()
diff --git a/test/ELF/lto/duplicated.ll b/test/ELF/lto/duplicated.ll
new file mode 100644
index 000000000000..6ef6772c5f20
--- /dev/null
+++ b/test/ELF/lto/duplicated.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared 2>&1 | FileCheck %s
+; CHECK: duplicate symbol: f in {{.*}}.o and {{.*}}.o
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/dynamic-list.ll b/test/ELF/lto/dynamic-list.ll
new file mode 100644
index 000000000000..0e950b3c83fd
--- /dev/null
+++ b/test/ELF/lto/dynamic-list.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "{ foo; };" > %t.list
+; RUN: ld.lld -m elf_x86_64 -o %t --dynamic-list %t.list -pie %t.o
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+; CHECK: Name: foo@
+; CHECK-NEXT: Value: 0x1010
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/dynsym.ll b/test/ELF/lto/dynsym.ll
new file mode 100644
index 000000000000..5885960c7bc3
--- /dev/null
+++ b/test/ELF/lto/dynsym.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t.o %p/Inputs/dynsym.s
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.so -o %t
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ call void @foo()
+ ret void
+}
+
+; CHECK: Name: foo
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding:
+; CHECK-NEXT: Type:
+; CHECK-NEXT: Other:
+; CHECK-NEXT: Section: .text
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/inline-asm.ll b/test/ELF/lto/inline-asm.ll
new file mode 100644
index 000000000000..b6af6a5a5cbb
--- /dev/null
+++ b/test/ELF/lto/inline-asm.ll
@@ -0,0 +1,11 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void asm "nop", ""()
+ ret void
+}
diff --git a/test/ELF/lto/internalize-basic.ll b/test/ELF/lto/internalize-basic.ll
new file mode 100644
index 000000000000..396b9cb60f17
--- /dev/null
+++ b/test/ELF/lto/internalize-basic.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define hidden void @foo() {
+ ret void
+}
+
+; Check that _start is not internalized.
+; CHECK: define void @_start()
+
+; Check that foo function is correctly internalized.
+; CHECK: define internal void @foo()
diff --git a/test/ELF/lto/internalize-exportdyn.ll b/test/ELF/lto/internalize-exportdyn.ll
new file mode 100644
index 000000000000..bee9a1e6a1ee
--- /dev/null
+++ b/test/ELF/lto/internalize-exportdyn.ll
@@ -0,0 +1,47 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @foo() {
+ ret void
+}
+
+define hidden void @bar() {
+ ret void
+}
+
+define linkonce_odr void @zed() local_unnamed_addr {
+ ret void
+}
+
+define linkonce_odr void @zed2() unnamed_addr {
+ ret void
+}
+
+define linkonce_odr void @bah() {
+ ret void
+}
+
+define linkonce_odr void @baz() {
+ ret void
+}
+
+@use_baz = global void ()* @baz
+
+; Check what gets internalized.
+; CHECK: define void @_start()
+; CHECK: define void @foo()
+; CHECK: define internal void @bar()
+; CHECK: define internal void @zed()
+; CHECK: define internal void @zed2()
+; CHECK: define weak_odr void @bah()
+; CHECK: define weak_odr void @baz()
diff --git a/test/ELF/lto/internalize-llvmused.ll b/test/ELF/lto/internalize-llvmused.ll
new file mode 100644
index 000000000000..46c90a65ff72
--- /dev/null
+++ b/test/ELF/lto/internalize-llvmused.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define hidden void @f() {
+ ret void
+}
+
+@llvm.used = appending global [1 x i8*] [ i8* bitcast (void ()* @f to i8*)]
+
+; Check that f is not internalized.
+; CHECK: define hidden void @f()
diff --git a/test/ELF/lto/internalize-undef.ll b/test/ELF/lto/internalize-undef.ll
new file mode 100644
index 000000000000..5d74c31eee8b
--- /dev/null
+++ b/test/ELF/lto/internalize-undef.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/internalize-undef.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @f()
+define void @_start() {
+ call void @f()
+ ret void
+}
+
+; CHECK: define internal void @f()
diff --git a/test/ELF/lto/internalize-version-script.ll b/test/ELF/lto/internalize-version-script.ll
new file mode 100644
index 000000000000..c25328fb56e2
--- /dev/null
+++ b/test/ELF/lto/internalize-version-script.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "{ global: foo; local: *; };" > %t.script
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+define void @bar() {
+ ret void
+}
+
+; Check that foo is not internalized.
+; CHECK: define void @foo()
+
+; Check that bar is correctly internalized.
+; CHECK: define internal void @bar()
diff --git a/test/ELF/lto/invalid-bitcode.ll b/test/ELF/lto/invalid-bitcode.ll
new file mode 100644
index 000000000000..eceffb10d8ad
--- /dev/null
+++ b/test/ELF/lto/invalid-bitcode.ll
@@ -0,0 +1,12 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o 2>&1 | FileCheck %s
+
+; CHECK: invalid bitcode file:
+
+; This bitcode file has no datalayout.
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/irmover-error.ll b/test/ELF/lto/irmover-error.ll
new file mode 100644
index 000000000000..aee411441c47
--- /dev/null
+++ b/test/ELF/lto/irmover-error.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-as -o %t1.bc %s
+; RUN: llvm-as -o %t2.bc %S/Inputs/irmover-error.ll
+; RUN: not ld.lld -m elf_x86_64 %t1.bc %t2.bc -o %t 2>&1 | FileCheck %s
+
+; CHECK: failed to link module {{.*}}2.bc: linking module flags 'foo': IDs have conflicting values
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+!0 = !{ i32 1, !"foo", i32 1 }
+
+!llvm.module.flags = !{ !0 }
diff --git a/test/ELF/lto/linkage.ll b/test/ELF/lto/linkage.ll
new file mode 100644
index 000000000000..5af9b321eeec
--- /dev/null
+++ b/test/ELF/lto/linkage.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o %t1.o -o %t.so -shared
+; RUN: llvm-nm %t.so | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Should not encounter a duplicate symbol error for @.str
+@.str = private unnamed_addr constant [4 x i8] c"Hey\00", align 1
+
+; Should not encounter a duplicate symbol error for @llvm.global_ctors
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define internal void @ctor() {
+ ret void
+}
+
+; Should not try to merge a declaration into the combined module.
+declare i32 @llvm.ctpop.i32(i32)
+; CHECK-NOT: llvm.ctpop.i32
diff --git a/test/ELF/lto/linkonce-odr.ll b/test/ELF/lto/linkonce-odr.ll
new file mode 100644
index 000000000000..569e27154545
--- /dev/null
+++ b/test/ELF/lto/linkonce-odr.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %p/Inputs/linkonce-odr.ll -o %t1.o
+; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+declare void @f()
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+; Be sure that 'f' is kept and has weak_odr linkage.
+; CHECK: define weak_odr void @f()
diff --git a/test/ELF/lto/linkonce.ll b/test/ELF/lto/linkonce.ll
new file mode 100644
index 000000000000..f980eff887b1
--- /dev/null
+++ b/test/ELF/lto/linkonce.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %p/Inputs/linkonce.ll -o %t1.o
+; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+declare void @f()
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+; Be sure that 'f' is kept and has weak linkage.
+; CHECK: define weak void @f()
diff --git a/test/ELF/lto/lto-start.ll b/test/ELF/lto/lto-start.ll
new file mode 100644
index 000000000000..e93eecfbf033
--- /dev/null
+++ b/test/ELF/lto/lto-start.ll
@@ -0,0 +1,23 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2
+; RUN: llvm-readobj -t %t2 | FileCheck %s
+
+; CHECK: Format: ELF64-x86-64
+; CHECK-NEXT: Arch: x86_64
+; CHECK-NEXT: AddressSize: 64bit
+
+; CHECK: Name: _start
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other:
+; CHECK-NEXT: Section: .text
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/ltopasses-basic.ll b/test/ELF/lto/ltopasses-basic.ll
new file mode 100644
index 000000000000..5bd5f4122fd0
--- /dev/null
+++ b/test/ELF/lto/ltopasses-basic.ll
@@ -0,0 +1,18 @@
+; REQUIRES: x86
+; RUN: rm -f %t.so.lto.bc %t.so.lto.opt.bc %t.so.lto.o
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -mllvm -debug-pass=Arguments -shared 2>&1 | FileCheck %s --check-prefix=MLLVM
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define void @ctor() {
+ ret void
+}
+
+; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+
+; MLLVM: Pass Arguments:
diff --git a/test/ELF/lto/ltopasses-custom.ll b/test/ELF/lto/ltopasses-custom.ll
new file mode 100644
index 000000000000..3e982e079fb1
--- /dev/null
+++ b/test/ELF/lto/ltopasses-custom.ll
@@ -0,0 +1,30 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps --lto-aa-pipeline=basic-aa \
+; RUN: --lto-newpm-passes=ipsccp -shared
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2.so -save-temps --lto-newpm-passes=loweratomic -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.so.lto.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @barrier() {
+ fence seq_cst
+ ret void
+}
+
+; IPSCCP won't remove the fence.
+; CHECK: define void @barrier() {
+; CHECK-NEXT: fence seq_cst
+; CHECK-NEXT: ret void
+
+; LowerAtomic will remove the fence.
+; ATOMIC: define void @barrier() {
+; ATOMIC-NEXT: ret void
+
+; Check that invalid passes are rejected gracefully.
+; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2.so \
+; RUN: --lto-newpm-passes=iamnotapass -shared 2>&1 | \
+; RUN: FileCheck %s --check-prefix=INVALID
+; INVALID: unable to parse pass pipeline description: iamnotapass
diff --git a/test/ELF/lto/metadata.ll b/test/ELF/lto/metadata.ll
new file mode 100644
index 000000000000..3e73de5aab47
--- /dev/null
+++ b/test/ELF/lto/metadata.ll
@@ -0,0 +1,13 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o %t1.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define weak void @foo(i32* %p) {
+ store i32 5, i32* %p, align 4, !tbaa !0
+ ret void
+}
+
+!0 = !{!"Simple C/C++ TBAA"}
diff --git a/test/ELF/lto/mix-platforms.ll b/test/ELF/lto/mix-platforms.ll
new file mode 100644
index 000000000000..3478caa5cff6
--- /dev/null
+++ b/test/ELF/lto/mix-platforms.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/shared.s -o %t386.o -filetype=obj -triple=i386-pc-linux
+; RUN: ld.lld %t386.o -o %ti386.so -shared
+; RUN: llvm-as %s -o %tx64.o
+; RUN: not ld.lld %ti386.so %tx64.o -o %t 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: {{.*}}x64.o is incompatible with {{.*}}i386.so
diff --git a/test/ELF/lto/module-asm.ll b/test/ELF/lto/module-asm.ll
new file mode 100644
index 000000000000..1389b9f5472e
--- /dev/null
+++ b/test/ELF/lto/module-asm.ll
@@ -0,0 +1,19 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t
+; RUN: llvm-nm %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".text"
+module asm ".globl foo"
+; CHECK: T foo
+module asm "foo: ret"
+
+declare void @foo()
+
+define void @_start() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/opt-level.ll b/test/ELF/lto/opt-level.ll
new file mode 100644
index 000000000000..934bf01b6c32
--- /dev/null
+++ b/test/ELF/lto/opt-level.ll
@@ -0,0 +1,29 @@
+; RUN: llvm-as -o %t.o %s
+; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --lto-O0 %t.o
+; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s
+; RUN: ld.lld -o %t2 -m elf_x86_64 -e main --lto-O2 %t.o
+; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s
+; RUN: ld.lld -o %t2a -m elf_x86_64 -e main %t.o
+; RUN: llvm-nm %t2a | FileCheck --check-prefix=CHECK-O2 %s
+
+; Reject invalid optimization levels.
+; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O6 %t.o 2>&1 | \
+; RUN: FileCheck --check-prefix=INVALID %s
+; INVALID: invalid optimization level for LTO: 6
+; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \
+; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s
+; INVALIDNEGATIVE: invalid optimization level for LTO: -1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK-O0: foo
+; CHECK-O2-NOT: foo
+define internal void @foo() {
+ ret void
+}
+
+define void @main() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/parallel-internalize.ll b/test/ELF/lto/parallel-internalize.ll
new file mode 100644
index 000000000000..58ed50eab894
--- /dev/null
+++ b/test/ELF/lto/parallel-internalize.ll
@@ -0,0 +1,57 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %t.bc %s
+; RUN: ld.lld -m elf_x86_64 --lto-jobs=2 -save-temps -o %t %t.bc -e foo --lto-O0
+; RUN: llvm-readobj -t -dyn-symbols %t | FileCheck %s
+; RUN: llvm-nm %t0.lto.o | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
+
+; CHECK: Symbols [
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: (0)
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local (0x0)
+; CHECK-NEXT: Type: None (0x0)
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined (0x0)
+; CHECK-NEXT: }
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: bar (5)
+; CHECK-NEXT: Value: 0x11010
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Local (0x0)
+; CHECK-NEXT: Type: Function (0x2)
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN (0x2)
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text (0x2)
+; CHECK-NEXT: }
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: foo (1)
+; CHECK-NEXT: Value: 0x11000
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function (0x2)
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text (0x2)
+; CHECK-NEXT: }
+; CHECK-NEXT: ]
+; CHECK-NEXT: DynamicSymbols [
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK0: U bar
+; CHECK0: T foo
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK1: T bar
+; CHECK1: U foo
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/parallel.ll b/test/ELF/lto/parallel.ll
new file mode 100644
index 000000000000..8ea62ef3ae08
--- /dev/null
+++ b/test/ELF/lto/parallel.ll
@@ -0,0 +1,24 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %t.bc %s
+; RUN: ld.lld -m elf_x86_64 --lto-jobs=2 -save-temps -o %t %t.bc -shared
+; RUN: llvm-nm %t0.lto.o | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK0-NOT: bar
+; CHECK0: T foo
+; CHECK0-NOT: bar
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK1-NOT: foo
+; CHECK1: T bar
+; CHECK1-NOT: foo
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/pic.ll b/test/ELF/lto/pic.ll
new file mode 100644
index 000000000000..abc514d7ca3d
--- /dev/null
+++ b/test/ELF/lto/pic.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld %t.o -o %t.so -shared
+; RUN: llvm-readobj -r %t.so | FileCheck %s
+
+; CHECK: Relocations [
+; CHECK-NEXT: Section ({{.*}}) .rela.plt {
+; CHECK-NEXT: R_X86_64_JUMP_SLOT bar 0x0
+; CHECK-NEXT: }
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
diff --git a/test/ELF/lto/relax-relocs.ll b/test/ELF/lto/relax-relocs.ll
new file mode 100644
index 000000000000..929e124b2d8e
--- /dev/null
+++ b/test/ELF/lto/relax-relocs.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 -save-temps -shared %t.o -o %t.so
+; RUN: llvm-readobj -r %t.so.lto.o | FileCheck %s
+
+; Test that we produce R_X86_64_REX_GOTPCRELX instead of R_X86_64_GOTPCREL
+; CHECK: R_X86_64_REX_GOTPCRELX foo
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = external global i32
+define i32 @bar() {
+ %t = load i32, i32* @foo
+ ret i32 %t
+}
diff --git a/test/ELF/lto/resolution.ll b/test/ELF/lto/resolution.ll
new file mode 100644
index 000000000000..b3fcf1db3a1b
--- /dev/null
+++ b/test/ELF/lto/resolution.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/resolution.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -s --section-data %t.so | FileCheck %s
+
+; CHECK: Name: .data
+; CHECK-NEXT: Type: SHT_PROGBITS
+; CHECK-NEXT: Flags [
+; CHECK-NEXT: SHF_ALLOC
+; CHECK-NEXT: SHF_WRITE
+; CHECK-NEXT: ]
+; CHECK-NEXT: Address:
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Size: 4
+; CHECK-NEXT: Link: 0
+; CHECK-NEXT: Info: 0
+; CHECK-NEXT: AddressAlignment: 1
+; CHECK-NEXT: EntrySize: 0
+; CHECK-NEXT: SectionData (
+; CHECK-NEXT: 0000: 09000000 |{{.*}}|
+; CHECK-NEXT: )
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = weak global i32 8
diff --git a/test/ELF/lto/save-temps.ll b/test/ELF/lto/save-temps.ll
new file mode 100644
index 000000000000..0b0f939c53f1
--- /dev/null
+++ b/test/ELF/lto/save-temps.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: cd %T
+; RUN: rm -f a.out a.out.lto.bc a.out.lto.o
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/save-temps.ll -o %t2.o
+; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o -save-temps
+; RUN: llvm-nm a.out | FileCheck %s
+; RUN: llvm-nm a.out.lto.bc | FileCheck %s
+; RUN: llvm-nm a.out.lto.o | FileCheck %s
+; RUN: llvm-dis a.out.lto.bc
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+; CHECK: T bar
+; CHECK: T foo
diff --git a/test/ELF/lto/shlib-undefined.ll b/test/ELF/lto/shlib-undefined.ll
new file mode 100644
index 000000000000..db60de8e21b2
--- /dev/null
+++ b/test/ELF/lto/shlib-undefined.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo .global __progname > %t2.s
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o
+; RUN: ld.lld -shared %t2.o -o %t2.so
+; RUN: ld.lld -o %t %t.o %t2.so
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+; CHECK: Name: __progname@
+; CHECK-NEXT: Value: 0x11010
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @__progname() {
+ ret void
+}
diff --git a/test/ELF/lto/start-lib.ll b/test/ELF/lto/start-lib.ll
new file mode 100644
index 000000000000..ec73954a80ca
--- /dev/null
+++ b/test/ELF/lto/start-lib.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+;
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-as %p/Inputs/start-lib1.ll -o %t2.o
+; RUN: llvm-as %p/Inputs/start-lib2.ll -o %t3.o
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 %t1.o %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST1 %s
+; TEST1: Name: bar
+; TEST1: Name: foo
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 -u bar %t1.o --start-lib %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST2 %s
+; TEST2: Name: bar
+; TEST2-NOT: Name: foo
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 %t1.o --start-lib %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST3 %s
+; TEST3-NOT: Name: bar
+; TEST3-NOT: Name: foo
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/tls-mixed.ll b/test/ELF/lto/tls-mixed.ll
new file mode 100644
index 000000000000..524bb4fb44a3
--- /dev/null
+++ b/test/ELF/lto/tls-mixed.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc %p/Inputs/tls-mixed.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Should not encounter TLS-ness mismatch for @foo
+@foo = external thread_local global i32, align 4
diff --git a/test/ELF/lto/tls-preserve.ll b/test/ELF/lto/tls-preserve.ll
new file mode 100644
index 000000000000..8aebcb783f48
--- /dev/null
+++ b/test/ELF/lto/tls-preserve.ll
@@ -0,0 +1,25 @@
+; TLS attribute needs to be preserved.
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -shared %t1.o -m elf_x86_64 -o %t1
+; RUN: llvm-readobj -t %t1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@tsp_int = thread_local global i32 1
+
+define void @_start() {
+ %val = load i32, i32* @tsp_int
+ ret void
+}
+
+; CHECK: Symbol {
+; CHECK: Name: tsp_int
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 4
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: TLS
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .tdata
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/type-merge.ll b/test/ELF/lto/type-merge.ll
new file mode 100644
index 000000000000..98db53970b0c
--- /dev/null
+++ b/test/ELF/lto/type-merge.ll
@@ -0,0 +1,26 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/type-merge.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -shared -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void @bar(i8* null)
+ ret void
+}
+declare void @bar(i8*)
+
+; CHECK: define void @foo() {
+; CHECK-NEXT: call void @bar(i8* null)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+
+; CHECK: declare void @bar(i8*)
+
+; CHECK: define void @zed() {
+; CHECK-NEXT: call void bitcast (void (i8*)* @bar to void ()*)()
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/type-merge2.ll b/test/ELF/lto/type-merge2.ll
new file mode 100644
index 000000000000..f0931ddc9d5e
--- /dev/null
+++ b/test/ELF/lto/type-merge2.ll
@@ -0,0 +1,27 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/type-merge2.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%zed = type { i8 }
+define void @foo() {
+ call void @bar(%zed* null)
+ ret void
+}
+declare void @bar(%zed*)
+
+; CHECK: %zed = type { i8 }
+; CHECK-NEXT: %zed.0 = type { i16 }
+
+; CHECK: define void @foo() {
+; CHECK-NEXT: call void bitcast (void (%zed.0*)* @bar to void (%zed*)*)(%zed* null)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+
+; CHECK: define void @bar(%zed.0* %this) {
+; CHECK-NEXT: store %zed.0* %this, %zed.0** null
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/undef-mixed.ll b/test/ELF/lto/undef-mixed.ll
new file mode 100644
index 000000000000..0fff5781020c
--- /dev/null
+++ b/test/ELF/lto/undef-mixed.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/undef-mixed.s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld %t2.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: bar
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
diff --git a/test/ELF/lto/undef-weak.ll b/test/ELF/lto/undef-weak.ll
new file mode 100644
index 000000000000..215978a73df0
--- /dev/null
+++ b/test/ELF/lto/undef-weak.ll
@@ -0,0 +1,29 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+
+
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o -o %t2.so %t.a -shared
+; RUN: llvm-readobj -t %t2.so | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare extern_weak void @f()
+define void @foo() {
+ call void @f()
+ ret void
+}
+
+; We should not fetch the archive member.
+
+; CHECK: Name: f ({{.*}})
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Weak
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined
+
diff --git a/test/ELF/lto/undef.ll b/test/ELF/lto/undef.ll
new file mode 100644
index 000000000000..41da61052290
--- /dev/null
+++ b/test/ELF/lto/undef.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK: Name: bar
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined
diff --git a/test/ELF/lto/undefined-puts.ll b/test/ELF/lto/undefined-puts.ll
new file mode 100644
index 000000000000..54fb32cef4a2
--- /dev/null
+++ b/test/ELF/lto/undefined-puts.ll
@@ -0,0 +1,28 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/shared.s -o %t1.o -filetype=obj -triple=x86_64-unknown-linux
+; RUN: ld.lld %t1.o -o %t1.so -shared
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld %t1.so %t2.o -m elf_x86_64 -o %t
+; RUN: llvm-readobj -dyn-symbols -dyn-relocations %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@.str = private unnamed_addr constant [6 x i8] c"blah\0A\00", align 1
+
+define i32 @_start() {
+ %str = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
+; Check that puts symbol is present in the dynamic symbol table and
+; there's a relocation for it.
+; CHECK: Dynamic Relocations {
+; CHECK-NEXT: 0x13018 R_X86_64_JUMP_SLOT puts 0x0
+; CHECK-NEXT: }
+
+; CHECK: DynamicSymbols [
+; CHECK: Symbol {
+; CHECK: Name: puts@
diff --git a/test/ELF/lto/unnamed-addr-comdat.ll b/test/ELF/lto/unnamed-addr-comdat.ll
new file mode 100644
index 000000000000..c8c36de88d4c
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr-comdat.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+@foo = linkonce_odr unnamed_addr constant i32 42, comdat
+
+; CHECK: @foo = internal unnamed_addr constant i32 42, comdat
diff --git a/test/ELF/lto/unnamed-addr-lib.ll b/test/ELF/lto/unnamed-addr-lib.ll
new file mode 100644
index 000000000000..c1c31f84bc8e
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr-lib.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-mc %p/Inputs/unnamed-addr-lib.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: ld.lld %t2.o -shared -o %t2.so
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.so -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+; This documents a small limitation of lld's internalization logic. We decide
+; that bar should be in the symbol table because if it is it will preempt the
+; one in the shared library.
+; We could add one extra bit for ODR so that we know that preemption is not
+; necessary, but that is probably not worth it.
+
+; CHECK: @foo = internal unnamed_addr constant i8 42
+; CHECK: @bar = weak_odr unnamed_addr constant i8 42
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = linkonce_odr unnamed_addr constant i8 42
+@bar = linkonce_odr unnamed_addr constant i8 42
diff --git a/test/ELF/lto/unnamed-addr.ll b/test/ELF/lto/unnamed-addr.ll
new file mode 100644
index 000000000000..a2c0105fd85f
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr.ll
@@ -0,0 +1,14 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@a = internal unnamed_addr constant i8 42
+
+define i8* @f() {
+ ret i8* @a
+}
+
+; CHECK: @a = internal unnamed_addr constant i8 42
diff --git a/test/ELF/lto/verify-invalid.ll b/test/ELF/lto/verify-invalid.ll
new file mode 100644
index 000000000000..16d6a3e54f12
--- /dev/null
+++ b/test/ELF/lto/verify-invalid.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \
+; RUN: 2>&1 | FileCheck -check-prefix=DEFAULT %s
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \
+; RUN: -disable-verify 2>&1 | FileCheck -check-prefix=DISABLE %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+; -disable-verify should disable the verification of bitcode.
+; DEFAULT: Pass Arguments: {{.*}} -verify {{.*}} -verify
+; DISABLE-NOT: Pass Arguments: {{.*}} -verify {{.*}} -verify
diff --git a/test/ELF/lto/version-script.ll b/test/ELF/lto/version-script.ll
new file mode 100644
index 000000000000..11a7f073ab51
--- /dev/null
+++ b/test/ELF/lto/version-script.ll
@@ -0,0 +1,50 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+; RUN: llvm-readobj -V -dyn-symbols %t2 | FileCheck --check-prefix=DSO %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+define void @bar() {
+ ret void
+}
+
+; CHECK: define void @foo()
+; CHECK: define void @bar()
+
+; DSO: DynamicSymbols [
+; DSO: Symbol {
+; DSO: Name: @ (0)
+; DSO: Value: 0x0
+; DSO: Size: 0
+; DSO: Binding: Local
+; DSO: Type: None
+; DSO: Other: 0
+; DSO: Section: Undefined
+; DSO: }
+; DSO: Symbol {
+; DSO: Name: foo@@VERSION_1.0
+; DSO: Value: 0x1000
+; DSO: Size: 1
+; DSO: Binding: Global
+; DSO: Type: Function
+; DSO: Other: 0
+; DSO: Section: .text
+; DSO: }
+; DSO: Symbol {
+; DSO: Name: bar@@VERSION_2.0
+; DSO: Value: 0x1010
+; DSO: Size: 1
+; DSO: Binding: Global
+; DSO: Type: Function
+; DSO: Other: 0
+; DSO: Section: .text
+; DSO: }
+; DSO: ]
diff --git a/test/ELF/lto/visibility.ll b/test/ELF/lto/visibility.ll
new file mode 100644
index 000000000000..718cc5b06986
--- /dev/null
+++ b/test/ELF/lto/visibility.ll
@@ -0,0 +1,35 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: g
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text
+
+; CHECK: Name: a
+; CHECK-NEXT: Value: 0x3000
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .data
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare hidden void @g()
+define void @f() {
+ call void @g()
+ ret void
+}
+@a = weak hidden global i32 42
diff --git a/test/ELF/lto/weak.ll b/test/ELF/lto/weak.ll
new file mode 100644
index 000000000000..381ef7a1a347
--- /dev/null
+++ b/test/ELF/lto/weak.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define weak void @f() {
+ ret void
+}
+
+; CHECK: Name: f
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Weak