[lld] [LLD] [COFF] Handle undefined weak symbols in LTO (PR #70430)

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 5 13:57:17 PST 2023


https://github.com/mstorsjo updated https://github.com/llvm/llvm-project/pull/70430

>From 085cd72e3d0a3f39d7fb23cdcc843fc779682846 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Fri, 27 Oct 2023 11:52:16 +0300
Subject: [PATCH] [LLD] [COFF] Handle undefined weak symbols in LTO

When reading the bitcode input, undefined weak symbols will show
up as undefined symbols - which fails the early pass of checking
for missing symbols in symtab.reportUnresolvable(), before doing
the actual LTO compilation.

Mark such symbols as deferUndefined (added in
3785a413feef896e8a022731cc6ed405d5ebe81b /
https://reviews.llvm.org/D89004 for the -wrap option), to let them
pass through this LTO precheck. After the LTO compilation, the weak
undefined symbols will point towards an absolute null symbol as
default.

Such weak undefined symbols are used for the TLS init function
in the Itanium C++ ABI, for TLS variables that potentially need
to run a constructor, when accessed across translation units.

This fixes https://github.com/llvm/llvm-project/issues/64513.
---
 lld/COFF/InputFiles.cpp             |  2 ++
 lld/test/COFF/lto-weak-undefined.ll | 40 +++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 lld/test/COFF/lto-weak-undefined.ll

diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 3ae05f42ac5ff63..79d0ed62307ba23 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -1040,6 +1040,8 @@ void BitcodeFile::parse() {
       fakeSC = &ctx.ltoDataSectionChunk.chunk;
     if (objSym.isUndefined()) {
       sym = ctx.symtab.addUndefined(symName, this, false);
+      if (objSym.isWeak())
+        sym->deferUndefined = true;
     } else if (objSym.isCommon()) {
       sym = ctx.symtab.addCommon(this, symName, objSym.getCommonSize());
     } else if (objSym.isWeak() && objSym.isIndirect()) {
diff --git a/lld/test/COFF/lto-weak-undefined.ll b/lld/test/COFF/lto-weak-undefined.ll
new file mode 100644
index 000000000000000..037ecc2b1209b16
--- /dev/null
+++ b/lld/test/COFF/lto-weak-undefined.ll
@@ -0,0 +1,40 @@
+; REQUIRES: x86
+
+;; Test linking of weak symbols with LTO. The weak symbol may be defined
+;; by another object file, or may be left undefined. When compiling the
+;; IR with an undefined weak symbol, the emitted object file will contain
+;; a weak alias pointing at an absolute symbol for the address null.
+;; Make sure both cases can be linked correctly.
+
+; RUN: split-file %s %t.dir
+; RUN: llvm-as %t.dir/main.ll -o %t.main.obj
+; RUN: llvm-as %t.dir/optional.ll -o %t.optional.obj
+
+; RUN: lld-link /entry:main %t.main.obj /out:%t-undef.exe
+; RUN: lld-link /entry:main %t.main.obj %t.optional.obj /out:%t-def.exe
+
+;--- main.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define dso_local i32 @main() {
+entry:
+  br i1 icmp ne (ptr @optionalFunc, ptr null), label %if.then, label %if.end
+
+if.then:
+  tail call void @optionalFunc()
+  br label %if.end
+
+if.end:
+  ret i32 0
+}
+
+declare extern_weak void @optionalFunc()
+
+;--- optional.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @optionalFunc() {
+  ret void
+}



More information about the llvm-commits mailing list