// RUN: split-file %s %t // Assemble the input assembly code into an object file // RUN: llc -enable-machine-outliner=never -mtriple arm64-apple-darwin -filetype=obj %t/call_sites.ll -o %t/call_sites.o // RUN: llvm-gsymutil --num-threads=1 --convert=%t/call_sites.o --callsites-yaml-file=%t/callsites.yaml -o %t/call_sites_obj.gsym // Dump the GSYM file and check the output for callsite information // RUN: llvm-gsymutil %t/call_sites_obj.gsym | FileCheck --check-prefix=CHECK-GSYM %s // CHECK-GSYM: FunctionInfo @ 0x[[#%x,FUNC_INFO:]]: [0x[[#%x,FUNC_START:]] - 0x[[#%x,FUNC_END:]]) "func_mainBin_dec_call_everything" // CHECK-GSYM-NEXT: LineTable: // func_mainBin_dec_call_everything() { // CHECK-GSYM-NEXT: 0x[[#%x,ENTRY:]] {{.*}}/call_sites.cpp:16 // func_mainBin_dec_01(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_01_CALL:]] {{.*}}/call_sites.cpp:17 // func_mainBin_dec_02(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_02_CALL:]] {{.*}}/call_sites.cpp:18 // func_mainBin_dec_03(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_DEC_03_CALL:]] {{.*}}/call_sites.cpp:19 // func_mainBin_inc_01(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_01_CALL:]] {{.*}}/call_sites.cpp:21 // func_mainBin_inc_02(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_02_CALL:]] {{.*}}/call_sites.cpp:22 // func_mainBin_inc_03(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_INC_03_CALL:]] {{.*}}/call_sites.cpp:23 // g_func_ptr(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_FUNC_CALL:]] {{.*}}/call_sites.cpp:25 // g_extern_func_ptr(); // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_EXTERN_FUNC_CALL:]] {{.*}}/call_sites.cpp:26 // g_volatile_var = 0; // CHECK-GSYM-NEXT: 0x[[#%x,ADDR_VAR_ASSIGN:]] {{.*}}/call_sites.cpp:28 // } // CHECK-GSYM-NEXT: 0x[[#%x,]] {{.*}}/call_sites.cpp:29 // CHECK-GSYM-NEXT: CallSites (by relative return offset): // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_DEC_02_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_01] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_DEC_03_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_02] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_01_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_dec_03] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_02_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_01] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_INC_03_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_02] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_FUNC_CALL,FUNC_START)]] Flags[InternalCall] MatchRegex[func_mainBin_inc_03] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_EXTERN_FUNC_CALL,FUNC_START)]] Flags[None] MatchRegex[.*func.*] // CHECK-GSYM-NEXT: 0x[[#%.4x,sub(ADDR_VAR_ASSIGN,FUNC_START)]] Flags[ExternalCall] MatchRegex[.*extern_func.*] //--- callsites.yaml functions: - name: func_mainBin_dec_call_everything callsites: - return_offset: 0x0C match_regex: ["func_mainBin_dec_01"] flags: - "InternalCall" - return_offset: 0x10 match_regex: ["func_mainBin_dec_02"] flags: - "InternalCall" - return_offset: 0x14 match_regex: ["func_mainBin_dec_03"] flags: - "InternalCall" - return_offset: 24 match_regex: ["func_mainBin_inc_01"] flags: - "InternalCall" - return_offset: 28 match_regex: ["func_mainBin_inc_02"] flags: - "InternalCall" - return_offset: 32 match_regex: ["func_mainBin_inc_03"] flags: - "InternalCall" - return_offset: 44 match_regex: [".*func.*"] - return_offset: 56 match_regex: [".*extern_func.*"] flags: - "ExternalCall" //--- call_sites.ll ; ModuleID = 'call_sites.cpp' source_filename = "call_sites.cpp" target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32" target triple = "arm64-unknown-macosx10.4.0" @g_volatile_var = global i32 0, align 4, !dbg !0 @g_func_ptr = global ptr null, align 8, !dbg !5 @g_extern_func_ptr = global ptr null, align 8, !dbg !12 ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_dec_01() local_unnamed_addr #0 !dbg !21 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !24, !tbaa !25 %dec = add nsw i32 %0, -1, !dbg !24 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !24, !tbaa !25 ret void, !dbg !29 } ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_dec_02() local_unnamed_addr #0 !dbg !30 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !31, !tbaa !25 %dec = add nsw i32 %0, -1, !dbg !31 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !31, !tbaa !25 ret void, !dbg !32 } ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_dec_03() local_unnamed_addr #0 !dbg !33 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !34, !tbaa !25 %dec = add nsw i32 %0, -1, !dbg !34 store volatile i32 %dec, ptr @g_volatile_var, align 4, !dbg !34, !tbaa !25 ret void, !dbg !35 } ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_inc_01() local_unnamed_addr #0 !dbg !36 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !37, !tbaa !25 %inc = add nsw i32 %0, 1, !dbg !37 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !37, !tbaa !25 ret void, !dbg !38 } ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_inc_02() local_unnamed_addr #0 !dbg !39 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !40, !tbaa !25 %inc = add nsw i32 %0, 1, !dbg !40 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !40, !tbaa !25 ret void, !dbg !41 } ; Function Attrs: minsize mustprogress nofree noinline norecurse nounwind optsize ssp memory(readwrite, argmem: none) define void @func_mainBin_inc_03() local_unnamed_addr #0 !dbg !42 { entry: %0 = load volatile i32, ptr @g_volatile_var, align 4, !dbg !43, !tbaa !25 %inc = add nsw i32 %0, 1, !dbg !43 store volatile i32 %inc, ptr @g_volatile_var, align 4, !dbg !43, !tbaa !25 ret void, !dbg !44 } ; Function Attrs: minsize mustprogress noinline nounwind optsize ssp define void @func_mainBin_dec_call_everything() local_unnamed_addr #1 !dbg !45 { entry: tail call void @func_mainBin_dec_01() #3, !dbg !46 tail call void @func_mainBin_dec_02() #3, !dbg !47 tail call void @func_mainBin_dec_03() #3, !dbg !48 tail call void @func_mainBin_inc_01() #3, !dbg !49 tail call void @func_mainBin_inc_02() #3, !dbg !50 tail call void @func_mainBin_inc_03() #3, !dbg !51 %0 = load volatile ptr, ptr @g_func_ptr, align 8, !dbg !52, !tbaa !53 %call = tail call noundef i32 %0() #4, !dbg !52 %1 = load volatile ptr, ptr @g_extern_func_ptr, align 8, !dbg !55, !tbaa !53 %call1 = tail call noundef i32 %1() #4, !dbg !55 store volatile i32 0, ptr @g_volatile_var, align 4, !dbg !56, !tbaa !25 ret void, !dbg !57 } ; Function Attrs: minsize mustprogress norecurse nounwind optsize ssp define noundef i32 @main() local_unnamed_addr #2 !dbg !58 { entry: tail call void @func_mainBin_dec_call_everything() #3, !dbg !59 ret i32 0, !dbg !60 } 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" } 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" } 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" } attributes #3 = { minsize optsize } attributes #4 = { minsize nounwind optsize } !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!15, !16, !17, !18, !19} !llvm.ident = !{!20} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "g_volatile_var", scope: !2, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true) !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: "/") !3 = !DIFile(filename: "call_sites.cpp", directory: "/tmp/tst") !4 = !{!0, !5, !12} !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) !6 = distinct !DIGlobalVariable(name: "g_func_ptr", scope: !2, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true) !7 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !8) !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) !9 = !DISubroutineType(types: !10) !10 = !{!11} !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) !13 = distinct !DIGlobalVariable(name: "g_extern_func_ptr", scope: !2, file: !3, line: 6, type: !7, isLocal: false, isDefinition: true) !14 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !11) !15 = !{i32 7, !"Dwarf Version", i32 4} !16 = !{i32 2, !"Debug Info Version", i32 3} !17 = !{i32 1, !"wchar_size", i32 4} !18 = !{i32 8, !"PIC Level", i32 2} !19 = !{i32 7, !"frame-pointer", i32 1} !20 = !{!"clang version 20.0.0git (https://github.com/alx32/llvm-project.git f41f6ea1f33c4f5e7c94f3d155e44292d1809c50)"} !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) !22 = !DISubroutineType(types: !23) !23 = !{null} !24 = !DILocation(line: 8, column: 54, scope: !21) !25 = !{!26, !26, i64 0} !26 = !{!"int", !27, i64 0} !27 = !{!"omnipotent char", !28, i64 0} !28 = !{!"Simple C++ TBAA"} !29 = !DILocation(line: 8, column: 58, scope: !21) !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) !31 = !DILocation(line: 9, column: 54, scope: !30) !32 = !DILocation(line: 9, column: 58, scope: !30) !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) !34 = !DILocation(line: 10, column: 54, scope: !33) !35 = !DILocation(line: 10, column: 58, scope: !33) !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) !37 = !DILocation(line: 12, column: 54, scope: !36) !38 = !DILocation(line: 12, column: 58, scope: !36) !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) !40 = !DILocation(line: 13, column: 54, scope: !39) !41 = !DILocation(line: 13, column: 58, scope: !39) !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) !43 = !DILocation(line: 14, column: 54, scope: !42) !44 = !DILocation(line: 14, column: 58, scope: !42) !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) !46 = !DILocation(line: 17, column: 5, scope: !45) !47 = !DILocation(line: 18, column: 5, scope: !45) !48 = !DILocation(line: 19, column: 5, scope: !45) !49 = !DILocation(line: 21, column: 5, scope: !45) !50 = !DILocation(line: 22, column: 5, scope: !45) !51 = !DILocation(line: 23, column: 5, scope: !45) !52 = !DILocation(line: 25, column: 5, scope: !45) !53 = !{!54, !54, i64 0} !54 = !{!"any pointer", !27, i64 0} !55 = !DILocation(line: 26, column: 5, scope: !45) !56 = !DILocation(line: 28, column: 20, scope: !45) !57 = !DILocation(line: 29, column: 1, scope: !45) !58 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 31, type: !9, scopeLine: 31, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2) !59 = !DILocation(line: 32, column: 3, scope: !58) !60 = !DILocation(line: 33, column: 3, scope: !58) //--- generate-callsite-test-data.sh #!/bin/bash ## This is provided for reference only, if we need to modify the file and regenerate the assembly code set -ex TOOLCHAIN_DIR="llvm-project/build/Debug/bin" # Create call_sites.cpp cat > call_sites.cpp < call_sites_binary.yaml # Dump the dSYM to YAML "$TOOLCHAIN_DIR"/obj2yaml call_sites.dSYM/Contents/Resources/DWARF/call_sites > call_sites_dsym.yaml