3
3
4
4
; RUN: rm -rf %t && split-file %s %t
5
5
6
+ ; Test single object file case
6
7
; RUN: llc -filetype=obj %t/a.ll -O3 -o %t/a.o -enable-machine-outliner=never -mtriple arm64-apple-macos -addrsig
7
8
; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks -dylib -o %t/a.dylib %t/a.o
8
9
26
27
; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks --keep-icf-stabs -dylib -o %t/a_thunks.dylib %t/a.o
27
28
; RUN: dsymutil -s %t/a_thunks.dylib > %t/a_thunks.txt
28
29
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
+ # Check that STABS entries correctly associate functions with their originating object files
36
+ # VERIFY-MULTI-STABS-LABEL: Symbol table for: '{{.*}}/multi_thunks.dylib'
37
+
38
+ # First object file's source and object file entries
39
+ # VERIFY-MULTI-STABS: N_SO{{.*}}a.cpp
40
+ # VERIFY-MULTI-STABS-NEXT: N_OSO{{.*}}a.o
41
+
42
+ # Functions from the first object file - all functions share the same address but belong to a.o
43
+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR:[0 -9a-f]+]] '_func_A'
44
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
45
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}[[FUNC_ADDR]] '_func_B'
46
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
47
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}[[FUNC_ADDR]] '_func_C'
48
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
49
+ # VERIFY-MULTI-STABS-NEXT-NEXT: N_FUN{{.*}}[0 -9a-f]+ '_take_func_addr'
50
+
51
+ # End of first object file's entries
52
+ # VERIFY-MULTI-STABS: N_SO{{.*}}01 0000 0000000000000000
53
+
54
+ # Second object file's source and object file entries
55
+ # VERIFY-MULTI-STABS: N_SO{{.*}}b.cpp
56
+ # VERIFY-MULTI-STABS-NEXT: N_OSO{{.*}}b.o
57
+
58
+ # Functions from the second object file - same addresses but different object file
59
+ # VERIFY-MULTI-STABS: N_FUN{{.*}}[[FUNC_ADDR]] '_func_D'
60
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
61
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}[[FUNC_ADDR]] '_func_E'
62
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
63
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}[[FUNC_ADDR]] '_func_F'
64
+ # VERIFY-MULTI-STABS-NEXT: N_FUN{{.*}}00 0000 {{.*}}
65
+ # VERIFY-MULTI-STABS-NEXT-NEXT: N_FUN{{.*}}[0 -9a-f]+ '_take_func_addr_b'
29
66
30
67
; RUN: dsymutil --flat --verify-dwarf=none %t/a_thunks.dylib -o %t/a_thunks.dSYM
31
68
; RUN: dsymutil -s %t/a_thunks.dSYM >> %t/a_thunks.txt
73
110
# VERIFY-THUNK-NEXT: {{ +}}DW_AT_low_pc (0x[[MERGED_FUN_ADDR]])
74
111
# VERIFY-THUNK-NEXT-NEXT-NEXT-NEXT-NEXT: {{ +}}DW_AT_name ("func_C" )
75
112
113
+
114
+
115
+
76
116
;--- a.cpp
77
117
#define ATTR __attribute__((noinline )) extern "C"
78
118
typedef unsigned long long ULL;
@@ -89,40 +129,64 @@ ATTR ULL take_func_addr() {
89
129
return val;
90
130
}
91
131
132
+ ;--- b.cpp
133
+ #define ATTR __attribute__((noinline )) extern "C"
134
+ typedef unsigned long long ULL;
135
+
136
+ // Identical functions in a different object file
137
+ ATTR int func_D() { return 1 ; }
138
+ ATTR int func_E() { return 1 ; }
139
+ ATTR int func_F() { return 1 ; }
140
+
141
+ ATTR ULL take_func_addr_b() {
142
+ ULL val = 0 ;
143
+ val += (ULL)(void *)func_D;
144
+ val += (ULL)(void *)func_E;
145
+ val += (ULL)(void *)func_F;
146
+ return val;
147
+ }
148
+
92
149
;--- gen
93
- clang -target arm64-apple-macos11.0 -S -emit-llvm a.cpp -O3 -g -o -
150
+ clang -target arm64-apple-macos11.0 -S -emit-llvm a.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -
151
+ echo ""
152
+ echo ";--- b.ll"
153
+ clang -target arm64-apple-macos11.0 -S -emit-llvm b.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -
94
154
95
155
;--- a.ll
96
156
; ModuleID = 'a.cpp'
97
157
source_filename = "a.cpp"
98
- target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
158
+ target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64- i64:64-i128:128-n32:64-S128-Fn32"
99
159
target triple = "arm64-apple-macosx11.0.0"
100
160
101
161
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
102
162
define noundef i32 @func_A () #0 !dbg !12 {
163
+ entry:
103
164
ret i32 1 , !dbg !16
104
165
}
105
166
106
167
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
107
168
define noundef i32 @func_B () #0 !dbg !17 {
169
+ entry:
108
170
ret i32 1 , !dbg !18
109
171
}
110
172
111
173
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
112
174
define noundef i32 @func_C () #0 !dbg !19 {
175
+ entry:
113
176
ret i32 1 , !dbg !20
114
177
}
115
178
116
179
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
117
180
define noundef i64 @take_func_addr () local_unnamed_addr #0 !dbg !21 {
181
+ entry:
118
182
#dbg_value(i64 0 , !25 , !DIExpression (), !26 )
119
183
#dbg_value(i64 ptrtoint (ptr @func_A to i64 ), !25 , !DIExpression (), !26 )
120
184
#dbg_value(i64 add (i64 ptrtoint (ptr @func_A to i64 ), i64 ptrtoint (ptr @func_B to i64 )), !25 , !DIExpression (), !26 )
121
185
#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 )
122
186
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
123
187
}
124
188
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" }
189
+ 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" }
126
190
127
191
!llvm.dbg.cu = !{!0 }
128
192
!llvm.module.flags = !{!6 , !7 , !8 , !9 , !10 , !11 }
@@ -155,3 +219,71 @@ attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind ssp wil
155
219
!25 = !DILocalVariable (name: "val" , scope: !21 , file: !1 , line: 9 , type: !3 )
156
220
!26 = !DILocation (line: 0 , scope: !21 )
157
221
!27 = !DILocation (line: 13 , column: 5 , scope: !21 )
222
+
223
+ ;--- b.ll
224
+ ; ModuleID = 'b.cpp'
225
+ source_filename = "b.cpp"
226
+ target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
227
+ target triple = "arm64-apple-macosx11.0.0"
228
+
229
+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
230
+ define noundef i32 @func_D () #0 !dbg !12 {
231
+ entry:
232
+ ret i32 1 , !dbg !16
233
+ }
234
+
235
+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
236
+ define noundef i32 @func_E () #0 !dbg !17 {
237
+ entry:
238
+ ret i32 1 , !dbg !18
239
+ }
240
+
241
+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
242
+ define noundef i32 @func_F () #0 !dbg !19 {
243
+ entry:
244
+ ret i32 1 , !dbg !20
245
+ }
246
+
247
+ ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
248
+ define noundef i64 @take_func_addr_b () local_unnamed_addr #0 !dbg !21 {
249
+ entry:
250
+ #dbg_value(i64 0 , !25 , !DIExpression (), !26 )
251
+ #dbg_value(i64 ptrtoint (ptr @func_D to i64 ), !25 , !DIExpression (), !26 )
252
+ #dbg_value(i64 add (i64 ptrtoint (ptr @func_D to i64 ), i64 ptrtoint (ptr @func_E to i64 )), !25 , !DIExpression (), !26 )
253
+ #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 )
254
+ 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
255
+ }
256
+
257
+ 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" }
258
+
259
+ !llvm.dbg.cu = !{!0 }
260
+ !llvm.module.flags = !{!6 , !7 , !8 , !9 , !10 , !11 }
261
+
262
+ !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: "/" )
263
+ !1 = !DIFile (filename: "b.cpp" , directory: "/proc/self/cwd" )
264
+ !2 = !{!3 , !5 }
265
+ !3 = !DIDerivedType (tag: DW_TAG_typedef, name: "ULL" , file: !1 , line: 2 , baseType: !4 )
266
+ !4 = !DIBasicType (name: "unsigned long long" , size: 64 , encoding: DW_ATE_unsigned)
267
+ !5 = !DIDerivedType (tag: DW_TAG_pointer_type, baseType: null , size: 64 )
268
+ !6 = !{i32 7 , !"Dwarf Version" , i32 4 }
269
+ !7 = !{i32 2 , !"Debug Info Version" , i32 3 }
270
+ !8 = !{i32 1 , !"wchar_size" , i32 4 }
271
+ !9 = !{i32 8 , !"PIC Level" , i32 2 }
272
+ !10 = !{i32 7 , !"uwtable" , i32 1 }
273
+ !11 = !{i32 7 , !"frame-pointer" , i32 1 }
274
+ !12 = distinct !DISubprogram (name: "func_D" , scope: !1 , file: !1 , line: 5 , type: !13 , scopeLine: 5 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
275
+ !13 = !DISubroutineType (types: !14 )
276
+ !14 = !{!15 }
277
+ !15 = !DIBasicType (name: "int" , size: 32 , encoding: DW_ATE_signed)
278
+ !16 = !DILocation (line: 5 , column: 21 , scope: !12 )
279
+ !17 = distinct !DISubprogram (name: "func_E" , scope: !1 , file: !1 , line: 6 , type: !13 , scopeLine: 6 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
280
+ !18 = !DILocation (line: 6 , column: 21 , scope: !17 )
281
+ !19 = distinct !DISubprogram (name: "func_F" , scope: !1 , file: !1 , line: 7 , type: !13 , scopeLine: 7 , flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0 )
282
+ !20 = !DILocation (line: 7 , column: 21 , scope: !19 )
283
+ !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 )
284
+ !22 = !DISubroutineType (types: !23 )
285
+ !23 = !{!3 }
286
+ !24 = !{!25 }
287
+ !25 = !DILocalVariable (name: "val" , scope: !21 , file: !1 , line: 10 , type: !3 )
288
+ !26 = !DILocation (line: 0 , scope: !21 )
289
+ !27 = !DILocation (line: 14 , column: 5 , scope: !21 )
0 commit comments