xref: /llvm-project/lld/test/MachO/thinlto-split-unit-start-lib.ll (revision 0f46e31cfbf415fcd3d3ce121bef94e92c6ccfc8)
1; REQUIRES: x86
2; RUN: rm -rf %t; split-file %s %t
3
4;; Split-LTO bitcode files can have the same symbol (typeinfo) twice in the
5;; symbol table: First undefined in the main file, then defined in the index
6;; file.
7;; When used in --start-lib / --end-lib, ld64.lld creates lazy symbols
8;; for all non-undefined symbols in the bitcode file.
9;; In vtable.o below, the typeinfo __ZTI1S is present once as undefined and
10;; once as defined. The defined version is added as a added as a LazyObject
11;; symbol.
12;; When vtable.o gets loaded due to the __ZN1SC1Ev ref from vtable_use.o,
13;; the first __ZTI1S (undefined) used to cause vtable.o to be extracted
14;; a second time, which used to cause an assert.
15;; See PR59162 for details.
16
17; RUN: opt --thinlto-bc --thinlto-split-lto-unit -o %t/vtable.o %t/vtable.ll
18; RUN: opt --thinlto-bc --thinlto-split-lto-unit -o %t/vtable_use.o %t/vtable_use.ll
19
20; RUN: %lld -lc++ --start-lib %t/vtable.o --end-lib %t/vtable_use.o -o /dev/null
21
22;; Bitcode files created by:
23; % cat vtable.cc
24; struct S {
25;   S();
26;   virtual void f();
27; };
28; S::S() {}
29; void S::f() {}
30
31; % cat vtable_use.cc
32; struct S {
33;   S();
34;   virtual void f();
35; };
36; int main() { S s; }
37
38; % clang -c vtable_use.cc vtable.cc -emit-llvm -S -fno-exceptions -arch x86_64 -mmacos-version-min=11 -O1
39
40; ...and then manually adding `, !type !8, type !9` based on `clang -S -emit-llvm -flto=thin` output,
41; because splitAndWriteThinLTOBitcode() in ThinLTOBitcodeWriter.cpp only splits bitcode
42; if type annotations are present. While at it, also removed unnecessary metadata.
43; (NB: The first comment creates vtable.ll while the latter generates vtable.s! vtable.s
44; contains a few things opt complains about, so we can't use the output of that directly.)
45
46;--- vtable.ll
47; ModuleID = 'vtable.cc'
48source_filename = "vtable.cc"
49target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
50target triple = "x86_64-apple-macosx11.0.0"
51
52@_ZTV1S = unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI1S, ptr @_ZN1S1fEv] }, align 8
53@_ZTVN10__cxxabiv117__class_type_infoE = external global ptr
54@_ZTS1S = constant [3 x i8] c"1S\00", align 1
55@_ZTI1S = constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1S }, align 8, !type !0, !type !1
56
57; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable
58define void @_ZN1SC2Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 {
59entry:
60  store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8
61  ret void
62}
63
64; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable
65define void @_ZN1SC1Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 {
66entry:
67  store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8
68  ret void
69}
70
71; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(none) uwtable
72define void @_ZN1S1fEv(ptr nocapture nonnull align 8 %this) unnamed_addr align 2 {
73entry:
74  ret void
75}
76
77!0 = !{i64 16, !"_ZTS1S"}
78!1 = !{i64 16, !"_ZTSM1SFvvE.virtual"}
79
80;--- vtable_use.ll
81; ModuleID = 'vtable_use.cc'
82source_filename = "vtable_use.cc"
83target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
84target triple = "x86_64-apple-macosx11.0.0"
85
86%struct.S = type { ptr }
87
88; Function Attrs: mustprogress noinline norecurse nounwind optnone ssp uwtable
89define noundef i32 @main() {
90entry:
91  %s = alloca %struct.S, align 8
92  call void @_ZN1SC1Ev(ptr noundef nonnull align 8 dereferenceable(8) %s)
93  ret i32 0
94}
95
96declare void @_ZN1SC1Ev(ptr noundef nonnull align 8 dereferenceable(8)) unnamed_addr
97