33
44; RUN: rm -rf %t && split-file %s %t
55
6+ ; Test single object file case
67; RUN: llc -filetype=obj %t/a.ll -O3 -o %t/a.o -enable-machine-outliner=never -mtriple arm64-apple-macos -addrsig
78; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks -dylib -o %t/a.dylib %t/a.o
89
2627; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks --keep-icf-stabs -dylib -o %t/a_thunks.dylib %t/a.o
2728; RUN: dsymutil -s %t/a_thunks.dylib > %t/a_thunks.txt
2829
30+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;; Test multiple object files with identical functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31+
32+ ; RUN: llc -filetype=obj %t/b.ll -O3 -o %t/b.o -enable-machine-outliner=never -mtriple arm64-apple-macos -addrsig
33+ ; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks --keep-icf-stabs -dylib -o %t/multi_thunks.dylib %t/a.o %t/b.o
34+ ; RUN: dsymutil -s %t/multi_thunks.dylib | FileCheck %s --check-prefix=VERIFY-MULTI-STABS
35+
36+ # Check that STABS entries correctly associate functions with their originating object files
37+ # VERIFY-MULTI-STABS-LABEL: Symbol table for: '{{.*}}/multi_thunks.dylib'
38+
39+ # First object file's source and object file entries
40+ # VERIFY-MULTI-STABS: N_SO{{.*}}a.cpp
41+ # VERIFY-MULTI-STABS: N_OSO{{.*}}a.o
42+
43+ # Functions from the first object file - all functions share the same address but belong to a.o
44+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR:[0 -9a-f]+]] '_func_A'
45+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
46+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_B'
47+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
48+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_C'
49+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
50+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[0 -9a-f]+ '_take_func_addr'
51+
52+ # End of first object file's entries
53+ # VERIFY-MULTI-STABS: N_SO{{.*}}01 0000 0000000000000000
54+
55+ # Second object file's source and object file entries
56+ # VERIFY-MULTI-STABS: N_SO{{.*}}b.cpp
57+ # VERIFY-MULTI-STABS: N_OSO{{.*}}b.o
58+
59+ # Functions from the second object file - same addresses but different object file
60+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_D'
61+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
62+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_E'
63+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
64+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_F'
65+ # VERIFY-MULTI-STABS: N_FUN{{.*}}00 0000 {{.*}}
66+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[0 -9a-f]+ '_take_func_addr_b'
67+
2968
3069; RUN: dsymutil --flat --verify-dwarf=none %t/a_thunks.dylib -o %t/a_thunks.dSYM
3170; RUN: dsymutil -s %t/a_thunks.dSYM >> %t/a_thunks.txt
73112# VERIFY-THUNK-NEXT: {{ +}}DW_AT_low_pc (0x[[MERGED_FUN_ADDR]])
74113# VERIFY-THUNK-NEXT-NEXT-NEXT-NEXT-NEXT: {{ +}}DW_AT_name ("func_C" )
75114
115+
116+
117+
76118;--- a.cpp
77119#define ATTR __attribute__((noinline )) extern "C"
78120typedef unsigned long long ULL;
@@ -89,40 +131,64 @@ ATTR ULL take_func_addr() {
89131 return val;
90132}
91133
134+ ;--- b.cpp
135+ #define ATTR __attribute__((noinline )) extern "C"
136+ typedef unsigned long long ULL;
137+
138+ // Identical functions in a different object file
139+ ATTR int func_D() { return 1 ; }
140+ ATTR int func_E() { return 1 ; }
141+ ATTR int func_F() { return 1 ; }
142+
143+ ATTR ULL take_func_addr_b() {
144+ ULL val = 0 ;
145+ val += (ULL)(void *)func_D;
146+ val += (ULL)(void *)func_E;
147+ val += (ULL)(void *)func_F;
148+ return val;
149+ }
150+
92151;--- gen
93- clang -target arm64-apple-macos11.0 -S -emit-llvm a.cpp -O3 -g -o -
152+ clang -target arm64-apple-macos11.0 -S -emit-llvm a.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -
153+ echo ""
154+ echo ";--- b.ll"
155+ clang -target arm64-apple-macos11.0 -S -emit-llvm b.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -
94156
95157;--- a.ll
96158; ModuleID = 'a.cpp'
97159source_filename = "a.cpp"
98- target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
160+ target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64- i64:64-i128:128-n32:64-S128-Fn32"
99161target triple = "arm64-apple-macosx11.0.0"
100162
101163; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
102164define noundef i32 @func_A () #0 !dbg !12 {
165+ entry:
103166 ret i32 1 , !dbg !16
104167}
105168
106169; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
107170define noundef i32 @func_B () #0 !dbg !17 {
171+ entry:
108172 ret i32 1 , !dbg !18
109173}
110174
111175; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
112176define noundef i32 @func_C () #0 !dbg !19 {
177+ entry:
113178 ret i32 1 , !dbg !20
114179}
115180
116181; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
117182define noundef i64 @take_func_addr () local_unnamed_addr #0 !dbg !21 {
183+ entry:
118184 #dbg_value(i64 0 , !25 , !DIExpression (), !26 )
119185 #dbg_value(i64 ptrtoint (ptr @func_A to i64 ), !25 , !DIExpression (), !26 )
120186 #dbg_value(i64 add (i64 ptrtoint (ptr @func_A to i64 ), i64 ptrtoint (ptr @func_B to i64 )), !25 , !DIExpression (), !26 )
121187 #dbg_value(i64 add (i64 add (i64 ptrtoint (ptr @func_A to i64 ), i64 ptrtoint (ptr @func_B to i64 )), i64 ptrtoint (ptr @func_C to i64 )), !25 , !DIExpression (), !26 )
122188 ret i64 add (i64 add (i64 ptrtoint (ptr @func_A to i64 ), i64 ptrtoint (ptr @func_B to i64 )), i64 ptrtoint (ptr @func_C to i64 )), !dbg !27
123189}
124190
125- attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable (sync) "frame-pointer" ="non-leaf" "no-trapping-math" ="true" "stack-protector-buffer-size" ="8" "target-cpu" ="apple-m1" "target-features" ="+aes,+altnzcv,+ccdp,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fptoint,+fullfp16,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+sha3,+specrestrict,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,+zcm,+zcz" }
191+ attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable (sync) "frame-pointer" ="non-leaf" "no-trapping-math" ="true" "stack-protector-buffer-size" ="8" "target-cpu" ="apple-m1" "target-features" ="+aes,+altnzcv,+ccdp,+ccidx,+ccpp,+ complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fptoint,+fullfp16,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+sha3,+specrestrict,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,+zcm,+zcz" }
126192
127193!llvm.dbg.cu = !{!0 }
128194!llvm.module.flags = !{!6 , !7 , !8 , !9 , !10 , !11 }
@@ -155,3 +221,71 @@ attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind ssp wil
155221!25 = !DILocalVariable (name: "val" , scope: !21 , file: !1 , line: 9 , type: !3 )
156222!26 = !DILocation (line: 0 , scope: !21 )
157223!27 = !DILocation (line: 13 , column: 5 , scope: !21 )
224+
225+ ;--- b.ll
226+ ; ModuleID = 'b.cpp'
227+ source_filename = "b.cpp"
228+ target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
229+ target triple = "arm64-apple-macosx11.0.0"
230+
231+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
232+ define noundef i32 @func_D () #0 !dbg !12 {
233+ entry:
234+ ret i32 1 , !dbg !16
235+ }
236+
237+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
238+ define noundef i32 @func_E () #0 !dbg !17 {
239+ entry:
240+ ret i32 1 , !dbg !18
241+ }
242+
243+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
244+ define noundef i32 @func_F () #0 !dbg !19 {
245+ entry:
246+ ret i32 1 , !dbg !20
247+ }
248+
249+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
250+ define noundef i64 @take_func_addr_b () local_unnamed_addr #0 !dbg !21 {
251+ entry:
252+ #dbg_value(i64 0 , !25 , !DIExpression (), !26 )
253+ #dbg_value(i64 ptrtoint (ptr @func_D to i64 ), !25 , !DIExpression (), !26 )
254+ #dbg_value(i64 add (i64 ptrtoint (ptr @func_D to i64 ), i64 ptrtoint (ptr @func_E to i64 )), !25 , !DIExpression (), !26 )
255+ #dbg_value(i64 add (i64 add (i64 ptrtoint (ptr @func_D to i64 ), i64 ptrtoint (ptr @func_E to i64 )), i64 ptrtoint (ptr @func_F to i64 )), !25 , !DIExpression (), !26 )
256+ ret i64 add (i64 add (i64 ptrtoint (ptr @func_D to i64 ), i64 ptrtoint (ptr @func_E to i64 )), i64 ptrtoint (ptr @func_F to i64 )), !dbg !27
257+ }
258+
259+ attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable (sync) "frame-pointer" ="non-leaf" "no-trapping-math" ="true" "stack-protector-buffer-size" ="8" "target-cpu" ="apple-m1" "target-features" ="+aes,+altnzcv,+ccdp,+ccidx,+ccpp,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fptoint,+fullfp16,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+sha3,+specrestrict,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,+zcm,+zcz" }
260+
261+ !llvm.dbg.cu = !{!0 }
262+ !llvm.module.flags = !{!6 , !7 , !8 , !9 , !10 , !11 }
263+
264+ !0 = distinct !DICompileUnit (language: DW_LANG_C_plus_plus_14, file: !1 , isOptimized: true , runtimeVersion: 0 , emissionKind: FullDebug, retainedTypes: !2 , splitDebugInlining: false , nameTableKind: Apple, sysroot: "/" )
265+ !1 = !DIFile (filename: "b.cpp" , directory: "/proc/self/cwd" )
266+ !2 = !{!3 , !5 }
267+ !3 = !DIDerivedType (tag: DW_TAG_typedef, name: "ULL" , file: !1 , line: 2 , baseType: !4 )
268+ !4 = !DIBasicType (name: "unsigned long long" , size: 64 , encoding: DW_ATE_unsigned)
269+ !5 = !DIDerivedType (tag: DW_TAG_pointer_type, baseType: null , size: 64 )
270+ !6 = !{i32 7 , !"Dwarf Version" , i32 4 }
271+ !7 = !{i32 2 , !"Debug Info Version" , i32 3 }
272+ !8 = !{i32 1 , !"wchar_size" , i32 4 }
273+ !9 = !{i32 8 , !"PIC Level" , i32 2 }
274+ !10 = !{i32 7 , !"uwtable" , i32 1 }
275+ !11 = !{i32 7 , !"frame-pointer" , i32 1 }
276+ !12 = distinct !DISubprogram (name: "func_D" , scope: !1 , file: !1 , line: 5 , type: !13 , scopeLine: 5 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
277+ !13 = !DISubroutineType (types: !14 )
278+ !14 = !{!15 }
279+ !15 = !DIBasicType (name: "int" , size: 32 , encoding: DW_ATE_signed)
280+ !16 = !DILocation (line: 5 , column: 21 , scope: !12 )
281+ !17 = distinct !DISubprogram (name: "func_E" , scope: !1 , file: !1 , line: 6 , type: !13 , scopeLine: 6 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
282+ !18 = !DILocation (line: 6 , column: 21 , scope: !17 )
283+ !19 = distinct !DISubprogram (name: "func_F" , scope: !1 , file: !1 , line: 7 , type: !13 , scopeLine: 7 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
284+ !20 = !DILocation (line: 7 , column: 21 , scope: !19 )
285+ !21 = distinct !DISubprogram (name: "take_func_addr_b" , scope: !1 , file: !1 , line: 9 , type: !22 , scopeLine: 9 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 , retainedNodes: !24 )
286+ !22 = !DISubroutineType (types: !23 )
287+ !23 = !{!3 }
288+ !24 = !{!25 }
289+ !25 = !DILocalVariable (name: "val" , scope: !21 , file: !1 , line: 10 , type: !3 )
290+ !26 = !DILocation (line: 0 , scope: !21 )
291+ !27 = !DILocation (line: 14 , column: 5 , scope: !21 )
0 commit comments