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

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 27 02:02:10 PDT 2023


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

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, 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.

>From 50a124890670dd2e9c6da0236a6cf090337f7f58 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, 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 | 34 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 lld/test/COFF/lto-weak-undefined.ll

diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 38ce29e6ab68c04..b5db6d2e1613d75 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..408d4342431baa7
--- /dev/null
+++ b/lld/test/COFF/lto-weak-undefined.ll
@@ -0,0 +1,34 @@
+; REQUIRES: x86
+
+; 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