diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-12-01 15:19:48 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-12-01 15:19:48 +0000 |
| commit | baa3bf8f76568de6198613fb2ba7695a76c29109 (patch) | |
| tree | ec15e39aac1505fc951253627c2ee9f094b4abdf /llvm/test/Linker | |
| parent | 6c800eb3f02f2a57cceae862f9602318f9b7b9cc (diff) | |
| download | bcm5719-llvm-baa3bf8f76568de6198613fb2ba7695a76c29109.tar.gz bcm5719-llvm-baa3bf8f76568de6198613fb2ba7695a76c29109.zip | |
Bring r254336 back:
The difference is that now we don't error on out-of-comdat access to
internal global values. We copy them instead. This seems to match the
expectation of COFF linkers (see pr25686).
Original message:
Start deciding earlier what to link.
A traditional linker is roughly split in symbol resolution and
"copying
stuff".
The two tasks are badly mixed in lib/Linker.
This starts splitting them apart.
With this patch there are no direct call to linkGlobalValueBody or
linkGlobalValueProto. Everything is linked via WapValue.
This also includes a few fixes:
* A GV goes undefined if the comdat is dropped (comdat11.ll).
* We error if an internal GV goes undefined (comdat13.ll).
* We don't link an unused comdat.
The first two match the behavior of an ELF linker. The second one is
equivalent to running globaldce on the input.
llvm-svn: 254418
Diffstat (limited to 'llvm/test/Linker')
| -rw-r--r-- | llvm/test/Linker/Inputs/comdat11.ll | 9 | ||||
| -rw-r--r-- | llvm/test/Linker/Inputs/comdat13.ll | 9 | ||||
| -rw-r--r-- | llvm/test/Linker/comdat11.ll | 13 | ||||
| -rw-r--r-- | llvm/test/Linker/comdat12.ll | 8 | ||||
| -rw-r--r-- | llvm/test/Linker/comdat13.ll | 30 | ||||
| -rw-r--r-- | llvm/test/Linker/comdat9.ll | 3 |
6 files changed, 72 insertions, 0 deletions
diff --git a/llvm/test/Linker/Inputs/comdat11.ll b/llvm/test/Linker/Inputs/comdat11.ll new file mode 100644 index 00000000000..5b7f74cf0b2 --- /dev/null +++ b/llvm/test/Linker/Inputs/comdat11.ll @@ -0,0 +1,9 @@ +$foo = comdat any +@foo = global i8 1, comdat +define void @zed() { + call void @bar() + ret void +} +define void @bar() comdat($foo) { + ret void +} diff --git a/llvm/test/Linker/Inputs/comdat13.ll b/llvm/test/Linker/Inputs/comdat13.ll new file mode 100644 index 00000000000..85515210ed7 --- /dev/null +++ b/llvm/test/Linker/Inputs/comdat13.ll @@ -0,0 +1,9 @@ +$foo = comdat any +@foo = internal global i8 1, comdat +define i8* @zed() { + call void @bax() + ret i8* @foo +} +define internal void @bax() comdat($foo) { + ret void +} diff --git a/llvm/test/Linker/comdat11.ll b/llvm/test/Linker/comdat11.ll new file mode 100644 index 00000000000..dbade4104fe --- /dev/null +++ b/llvm/test/Linker/comdat11.ll @@ -0,0 +1,13 @@ +; RUN: llvm-link -S %s %p/Inputs/comdat11.ll -o - | FileCheck %s + +$foo = comdat any +@foo = global i8 0, comdat + +; CHECK: @foo = global i8 0, comdat + +; CHECK: define void @zed() { +; CHECK: call void @bar() +; CHECK: ret void +; CHECK: } + +; CHECK: declare void @bar() diff --git a/llvm/test/Linker/comdat12.ll b/llvm/test/Linker/comdat12.ll new file mode 100644 index 00000000000..d06e222b63a --- /dev/null +++ b/llvm/test/Linker/comdat12.ll @@ -0,0 +1,8 @@ +; RUN: llvm-link %s -S -o - | FileCheck %s + +$foo = comdat largest +define internal void @foo() comdat($foo) { + ret void +} + +; CHECK-NOT: foo diff --git a/llvm/test/Linker/comdat13.ll b/llvm/test/Linker/comdat13.ll new file mode 100644 index 00000000000..d1e382a2f27 --- /dev/null +++ b/llvm/test/Linker/comdat13.ll @@ -0,0 +1,30 @@ +; RUN: llvm-link -S %s %p/Inputs/comdat13.ll -o - | FileCheck %s + +; In Inputs/comdat13.ll a function not in the $foo comdat (zed) references an +; internal function in the comdat $foo. +; The IR would be ilegal on ELF ("relocation refers to discarded section"), +; but COFF linkers seem to just duplicate the comdat. + +$foo = comdat any +@foo = internal global i8 0, comdat +define i8* @bar() { + ret i8* @foo +} + +; CHECK: $foo = comdat any + +; CHECK: @foo = internal global i8 0, comdat +; CHECK: @foo.1 = internal global i8 1, comdat($foo) + +; CHECK: define i8* @bar() { +; CHECK-NEXT: ret i8* @foo +; CHECK-NEXT: } + +; CHECK: define i8* @zed() { +; CHECK-NEXT: call void @bax() +; CHECK-NEXT: ret i8* @foo.1 +; CHECK-NEXT: } + +; CHECK: define internal void @bax() comdat($foo) { +; CHECK-NEXT: ret void +; CHECK-NEXT: } diff --git a/llvm/test/Linker/comdat9.ll b/llvm/test/Linker/comdat9.ll index 274957401aa..4f6f2cfb845 100644 --- a/llvm/test/Linker/comdat9.ll +++ b/llvm/test/Linker/comdat9.ll @@ -14,6 +14,9 @@ $f2 = comdat largest define internal void @f2() comdat($f2) { ret void } +define void @f3() comdat($f2) { + ret void +} ; CHECK-DAG: $f2 = comdat largest ; CHECK-DAG: define internal void @f2() comdat { |

