1 // RUN: split-file %s %t
3 // Assemble the input assembly code into an object file
4 // RUN: llc -enable-machine-outliner=never -mtriple arm64-apple-darwin -filetype=obj %t/call_sites.ll -o %t/call_sites.o
5 // RUN: llvm-gsymutil --convert=%t/call_sites.o --callsites-yaml-file=%t/callsites.yaml -o %t/call_sites_obj.gsym
7 // Dump the GSYM file and check the output for callsite information
8 // RUN: llvm-gsymutil %t/call_sites_obj.gsym | FileCheck --check-prefix=CHECK-GSYM %s
11 // CHECK-GSYM: FunctionInfo @ 0x[[#%x,FUNC_INFO:]]: [0x[[#%x,FUNC_START:]] - 0x[[#%x,FUNC_END:]]) "func_mainBin_dec_call_everything"
12 // CHECK-GSYM-NEXT: LineTable:
13 // func_mainBin_dec_call_everything() {
14 // CHECK-GSYM-NEXT: 0x[[#%x,ENTRY:]] {{.*}}/call_sites.cpp:16
15 // func_mainBin_dec_01();
16 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_01_CALL:]] {{.*}}/call_sites.cpp:17
17 // func_mainBin_dec_02();
18 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_02_CALL:]] {{.*}}/call_sites.cpp:18
19 // func_mainBin_dec_03();
20 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_03_CALL:]] {{.*}}/call_sites.cpp:19
21 // func_mainBin_inc_01();
22 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_01_CALL:]] {{.*}}/call_sites.cpp:21
23 // func_mainBin_inc_02();
24 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_02_CALL:]] {{.*}}/call_sites.cpp:22
25 // func_mainBin_inc_03();
26 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_03_CALL:]] {{.*}}/call_sites.cpp:23
28 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_FUNC_CALL:]] {{.*}}/call_sites.cpp:25
29 // g_extern_func_ptr();
30 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_EXTERN_FUNC_CALL:]] {{.*}}/call_sites.cpp:26
31 // g_volatile_var = 0;
32 // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_VAR_ASSIGN:]] {{.*}}/call_sites.cpp:28
34 // CHECK-GSYM-NEXT: 0x[[#%x,]] {{.*}}/call_sites.cpp:29
35 // CHECK-GSYM-NEXT: CallSites (by relative return offset):
36 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_DEC_02_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_01]
37 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_DEC_03_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_02]
38 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_01_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_03]
39 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_02_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_01]
40 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_03_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_02]
41 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_FUNC_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_03]
42 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_EXTERN_FUNC_CALL,FUNC_START)]] Flags[None] MatchRegex[.*func.*]
43 // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_VAR_ASSIGN,FUNC_START)]] Flags[ExternalCall] MatchRegex[.*extern_func.*]
48 - name: func_mainBin_dec_call_everything
51 match_regex: ["func_mainBin_dec_01"]
55 match_regex: ["func_mainBin_dec_02"]
59 match_regex: ["func_mainBin_dec_03"]
63 match_regex: ["func_mainBin_inc_01"]
67 match_regex: ["func_mainBin_inc_02"]
71 match_regex: ["func_mainBin_inc_03"]
75 match_regex: [".*func.*"]
77 match_regex: [".*extern_func.*"]
83 ; ModuleID = 'call_sites.cpp'
84 source_filename = "call_sites.cpp"
85 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
86 target triple = "arm64-unknown-macosx10.4.0"
88 @g_volatile_var = global i32 0, align 4, !dbg !0
89 @g_func_ptr = global ptr null, align 8, !dbg !5
90 @g_extern_func_ptr = global ptr null, align 8, !dbg !12
92 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
93 define void @func_mainBin_dec_01() local_unnamed_addr #0 !dbg !21 {
95 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !24, !tbaa !25
96 %dec = add nsw i32 %0, -1, !dbg !24
97 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !24, !tbaa !25
101 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
102 define void @func_mainBin_dec_02() local_unnamed_addr #0 !dbg !30 {
104 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !31, !tbaa !25
105 %dec = add nsw i32 %0, -1, !dbg !31
106 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !31, !tbaa !25
110 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
111 define void @func_mainBin_dec_03() local_unnamed_addr #0 !dbg !33 {
113 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !34, !tbaa !25
114 %dec = add nsw i32 %0, -1, !dbg !34
115 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !34, !tbaa !25
119 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
120 define void @func_mainBin_inc_01() local_unnamed_addr #0 !dbg !36 {
122 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !37, !tbaa !25
123 %inc = add nsw i32 %0, 1, !dbg !37
124 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !37, !tbaa !25
128 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
129 define void @func_mainBin_inc_02() local_unnamed_addr #0 !dbg !39 {
131 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !40, !tbaa !25
132 %inc = add nsw i32 %0, 1, !dbg !40
133 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !40, !tbaa !25
137 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none)
138 define void @func_mainBin_inc_03() local_unnamed_addr #0 !dbg !42 {
140 %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !43, !tbaa !25
141 %inc = add nsw i32 %0, 1, !dbg !43
142 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !43, !tbaa !25
146 ; Function Attrs: minsize mustprogress noinline nounwind optsize ssp
147 define void @func_mainBin_dec_call_everything() local_unnamed_addr #1 !dbg !45 {
149 tail call void @func_mainBin_dec_01() #3, !dbg !46
150 tail call void @func_mainBin_dec_02() #3, !dbg !47
151 tail call void @func_mainBin_dec_03() #3, !dbg !48
152 tail call void @func_mainBin_inc_01() #3, !dbg !49
153 tail call void @func_mainBin_inc_02() #3, !dbg !50
154 tail call void @func_mainBin_inc_03() #3, !dbg !51
155 %0 = load volatile ptr, ptr @g_func_ptr, align 8, !dbg !52, !tbaa !53
156 %call = tail call noundef i32 %0() #4, !dbg !52
157 %1 = load volatile ptr, ptr @g_extern_func_ptr, align 8, !dbg !55, !tbaa !53
158 %call1 = tail call noundef i32 %1() #4, !dbg !55
159 store volatile i32 0, ptr @g_volatile_var, align 4, !dbg !56, !tbaa !25
163 ; Function Attrs: minsize mustprogress norecurse nounwind optsize ssp
164 define noundef i32 @main() local_unnamed_addr #2 !dbg !58 {
166 tail call void @func_mainBin_dec_call_everything() #3, !dbg !59
170 attributes #0 = { minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) "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" }
171 attributes #1 = { minsize mustprogress noinline nounwind optsize ssp "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" }
172 attributes #2 = { minsize mustprogress norecurse nounwind optsize ssp "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" }
173 attributes #3 = { minsize optsize }
174 attributes #4 = { minsize nounwind optsize }
177 !llvm.module.flags = !{!15, !16, !17, !18, !19}
180 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
181 !1 = distinct !DIGlobalVariable(name: "g_volatile_var", scope: !2, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true)
182 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 20.0.0git (https://github.com/alx32/llvm-project.git f41f6ea1f33c4f5e7c94f3d155e44292d1809c50)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None, sysroot: "/")
183 !3 = !DIFile(filename: "call_sites.cpp", directory: "/tmp/tst")
185 !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
186 !6 = distinct !DIGlobalVariable(name: "g_func_ptr", scope: !2, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true)
187 !7 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !8)
188 !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
189 !9 = !DISubroutineType(types: !10)
191 !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
192 !12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression())
193 !13 = distinct !DIGlobalVariable(name: "g_extern_func_ptr", scope: !2, file: !3, line: 6, type: !7, isLocal: false, isDefinition: true)
194 !14 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !11)
195 !15 = !{i32 7, !"Dwarf Version", i32 4}
196 !16 = !{i32 2, !"Debug Info Version", i32 3}
197 !17 = !{i32 1, !"wchar_size", i32 4}
198 !18 = !{i32 8, !"PIC Level", i32 2}
199 !19 = !{i32 7, !"frame-pointer", i32 1}
200 !20 = !{!"clang version 20.0.0git (https://github.com/alx32/llvm-project.git f41f6ea1f33c4f5e7c94f3d155e44292d1809c50)"}
201 !21 = distinct !DISubprogram(name: "func_mainBin_dec_01", scope: !3, file: !3, line: 8, type: !22, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
202 !22 = !DISubroutineType(types: !23)
204 !24 = !DILocation(line: 8, column: 54, scope: !21)
205 !25 = !{!26, !26, i64 0}
206 !26 = !{!"int", !27, i64 0}
207 !27 = !{!"omnipotent char", !28, i64 0}
208 !28 = !{!"Simple C++ TBAA"}
209 !29 = !DILocation(line: 8, column: 58, scope: !21)
210 !30 = distinct !DISubprogram(name: "func_mainBin_dec_02", scope: !3, file: !3, line: 9, type: !22, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
211 !31 = !DILocation(line: 9, column: 54, scope: !30)
212 !32 = !DILocation(line: 9, column: 58, scope: !30)
213 !33 = distinct !DISubprogram(name: "func_mainBin_dec_03", scope: !3, file: !3, line: 10, type: !22, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
214 !34 = !DILocation(line: 10, column: 54, scope: !33)
215 !35 = !DILocation(line: 10, column: 58, scope: !33)
216 !36 = distinct !DISubprogram(name: "func_mainBin_inc_01", scope: !3, file: !3, line: 12, type: !22, scopeLine: 12, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
217 !37 = !DILocation(line: 12, column: 54, scope: !36)
218 !38 = !DILocation(line: 12, column: 58, scope: !36)
219 !39 = distinct !DISubprogram(name: "func_mainBin_inc_02", scope: !3, file: !3, line: 13, type: !22, scopeLine: 13, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
220 !40 = !DILocation(line: 13, column: 54, scope: !39)
221 !41 = !DILocation(line: 13, column: 58, scope: !39)
222 !42 = distinct !DISubprogram(name: "func_mainBin_inc_03", scope: !3, file: !3, line: 14, type: !22, scopeLine: 14, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
223 !43 = !DILocation(line: 14, column: 54, scope: !42)
224 !44 = !DILocation(line: 14, column: 58, scope: !42)
225 !45 = distinct !DISubprogram(name: "func_mainBin_dec_call_everything", scope: !3, file: !3, line: 16, type: !22, scopeLine: 16, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
226 !46 = !DILocation(line: 17, column: 5, scope: !45)
227 !47 = !DILocation(line: 18, column: 5, scope: !45)
228 !48 = !DILocation(line: 19, column: 5, scope: !45)
229 !49 = !DILocation(line: 21, column: 5, scope: !45)
230 !50 = !DILocation(line: 22, column: 5, scope: !45)
231 !51 = !DILocation(line: 23, column: 5, scope: !45)
232 !52 = !DILocation(line: 25, column: 5, scope: !45)
233 !53 = !{!54, !54, i64 0}
234 !54 = !{!"any pointer", !27, i64 0}
235 !55 = !DILocation(line: 26, column: 5, scope: !45)
236 !56 = !DILocation(line: 28, column: 20, scope: !45)
237 !57 = !DILocation(line: 29, column: 1, scope: !45)
238 !58 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 31, type: !9, scopeLine: 31, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
239 !59 = !DILocation(line: 32, column: 3, scope: !58)
240 !60 = !DILocation(line: 33, column: 3, scope: !58)
243 //--- generate-callsite-test-data.sh
245 ## This is provided for reference only, if we need to modify the file and regenerate the assembly code
248 TOOLCHAIN_DIR="llvm-project/build/Debug/bin"
250 # Create call_sites.cpp
251 cat > call_sites.cpp <<EOF
253 #define FUNC_ATTR extern "C" __attribute__((noinline))
255 volatile int g_volatile_var;
256 int (*volatile g_func_ptr)();
257 int (*volatile g_extern_func_ptr)();
259 FUNC_ATTR void func_mainBin_dec_01() { g_volatile_var--; }
260 FUNC_ATTR void func_mainBin_dec_02() { g_volatile_var--; }
261 FUNC_ATTR void func_mainBin_dec_03() { g_volatile_var--; }
263 FUNC_ATTR void func_mainBin_inc_01() { g_volatile_var++; }
264 FUNC_ATTR void func_mainBin_inc_02() { g_volatile_var++; }
265 FUNC_ATTR void func_mainBin_inc_03() { g_volatile_var++; }
267 FUNC_ATTR void func_mainBin_dec_call_everything() {
268 func_mainBin_dec_01();
269 func_mainBin_dec_02();
270 func_mainBin_dec_03();
272 func_mainBin_inc_01();
273 func_mainBin_inc_02();
274 func_mainBin_inc_03();
283 func_mainBin_dec_call_everything();
288 # Generate IR from call_sites.cpp
289 "$TOOLCHAIN_DIR"/clang++ -mno-outline -target arm64-apple-macos -g -Oz -fno-exceptions -S -emit-llvm call_sites.cpp -o call_sites.ll
291 # Compile the assembly into an object file
292 "$TOOLCHAIN_DIR"/llc -filetype=obj call_sites.ll -o call_sites.o
294 # Link the object file into an executable using lld directly
295 "$TOOLCHAIN_DIR"/ld64.lld -arch arm64 -platform_version macos 11.0.0 11.0.0 -o call_sites call_sites.o -lSystem
298 "$TOOLCHAIN_DIR"/dsymutil call_sites -o call_sites.dSYM
300 # Dump the binary to YAML
301 "$TOOLCHAIN_DIR"/obj2yaml call_sites > call_sites_binary.yaml
303 # Dump the dSYM to YAML
304 "$TOOLCHAIN_DIR"/obj2yaml call_sites.dSYM/Contents/Resources/DWARF/call_sites > call_sites_dsym.yaml