290 lines · plain
1; NOTE: Code has been autogenerated by utils/update_test_body.py2; REQUIRES: aarch643 4; RUN: rm -rf %t && split-file %s %t5 6; Test single object file case7; RUN: llc -filetype=obj %t/a.ll -O3 -o %t/a.o -enable-machine-outliner=never -mtriple arm64-apple-macos -addrsig8; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks -dylib -o %t/a.dylib %t/a.o9 10;;; Check that we generate valid dSYM11; RUN: dsymutil %t/a.dylib -o %t/a.dSYM12; RUN: llvm-dwarfdump --verify %t/a.dSYM | FileCheck %s --check-prefix=VERIFY-DSYM13; VERIFY-DSYM: No errors.14 15;;; Check that we don't generate STABS entries (N_FUN) for ICF'ed function thunks16; RUN: dsymutil -s %t/a.dylib | FileCheck %s --check-prefix=VERIFY-STABS17; VERIFY-STABS-NOT: N_FUN{{.*}}_func_B18; VERIFY-STABS-NOT: N_FUN{{.*}}_func_C19 20;;; Check that we do generate STABS entries (N_FUN) for non-ICF'ed functions21; VERIFY-STABS: N_FUN{{.*}}_func_A22; VERIFY-STABS: N_FUN{{.*}}_take_func_addr23 24;;;;;;;;;;;;;;;;;;;;;;;;;;;; Check safe_thunks ICF + keeping STABS entries ;;;;;;;;;;;;;;;;;;;;;;;;;;;;25 26;;; Check scenario with where we do safe_thunks ICF and also generate STABS entries27; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks --keep-icf-stabs -dylib -o %t/a_thunks.dylib %t/a.o28; RUN: dsymutil -s %t/a_thunks.dylib > %t/a_thunks.txt29 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 -addrsig33; RUN: %lld -arch arm64 -lSystem --icf=safe_thunks --keep-icf-stabs -dylib -o %t/multi_thunks.dylib %t/a.o %t/b.o34; RUN: dsymutil -s %t/multi_thunks.dylib | FileCheck %s --check-prefix=VERIFY-MULTI-STABS35# Check that STABS entries correctly associate functions with their originating object files36# VERIFY-MULTI-STABS-LABEL: Symbol table for: '{{.*}}/multi_thunks.dylib'37 38# First object file's source and object file entries39# VERIFY-MULTI-STABS: N_SO{{.*}}a.cpp40# VERIFY-MULTI-STABS-NEXT: N_OSO{{.*}}a.o41 42# Functions from the first object file - all functions share the same address but belong to a.o43# 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 entries52# VERIFY-MULTI-STABS: N_SO{{.*}}01 0000 000000000000000053 54# Second object file's source and object file entries55# VERIFY-MULTI-STABS: N_SO{{.*}}b.cpp56# VERIFY-MULTI-STABS-NEXT: N_OSO{{.*}}b.o57 58# Functions from the second object file - same addresses but different object file59# 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'66 67; RUN: dsymutil --flat --verify-dwarf=none %t/a_thunks.dylib -o %t/a_thunks.dSYM68; RUN: dsymutil -s %t/a_thunks.dSYM >> %t/a_thunks.txt69; RUN: llvm-dwarfdump -a %t/a_thunks.dSYM >> %t/a_thunks.txt70 71; RUN: cat %t/a_thunks.txt | FileCheck %s --check-prefix=VERIFY-THUNK72 73# VERIFY-THUNK-LABEL: Symbol table for: '{{.*}}/a_thunks.dylib'74# Capture the 'n_value's for N_FUN entries of _func_A, _func_B, and _func_C75# VERIFY-THUNK: [[MERGED_FUN_ADDR:[0-9a-f]+]] '_func_A'76# VERIFY-THUNK: [[MERGED_FUN_ADDR]] '_func_B'77# VERIFY-THUNK: [[MERGED_FUN_ADDR]] '_func_C'78 79# Capture the 'n_value's for SECT EXT entries in the first part80# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_A_NVALUE:[0-9a-f]+]] '_func_A'81# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_B_NVALUE:[0-9a-f]+]] '_func_B'82# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_C_NVALUE:[0-9a-f]+]] '_func_C'83 84# VERIFY-THUNK: ----------------------------------------------------------------------85# VERIFY-THUNK-LABEL: Symbol table for: '{{.*}}/a_thunks.dSYM'86 87# Verify that the SECT EXT 'n_value's in the second part match the first part88# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_A_NVALUE]] '_func_A'89# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_B_NVALUE]] '_func_B'90# VERIFY-THUNK: SECT EXT{{.*}} [[SECT_EXT_C_NVALUE]] '_func_C'91 92# Ensure that N_FUN 'n_value's match the DW_TAG_subprogram's DW_AT_low_pc93# and that the DW_AT_name is at a specific relative position94 95# VERIFY-THUNK-LABEL: .debug_info contents:96# VERIFY-THUNK: Compile Unit: length = {{.*}}97 98# Match the subprogram for func_A99# VERIFY-THUNK: : DW_TAG_subprogram100# VERIFY-THUNK-NEXT: {{ +}}DW_AT_low_pc (0x[[MERGED_FUN_ADDR]])101# VERIFY-THUNK-NEXT-NEXT-NEXT-NEXT-NEXT: {{ +}}DW_AT_name ("func_A")102 103# Match the subprogram for func_B104# VERIFY-THUNK: : DW_TAG_subprogram105# VERIFY-THUNK-NEXT: {{ +}}DW_AT_low_pc (0x[[MERGED_FUN_ADDR]])106# VERIFY-THUNK-NEXT-NEXT-NEXT-NEXT-NEXT: {{ +}}DW_AT_name ("func_B")107 108# Match the subprogram for func_C109# VERIFY-THUNK: : DW_TAG_subprogram110# VERIFY-THUNK-NEXT: {{ +}}DW_AT_low_pc (0x[[MERGED_FUN_ADDR]])111# VERIFY-THUNK-NEXT-NEXT-NEXT-NEXT-NEXT: {{ +}}DW_AT_name ("func_C")112 113 114 115 116;--- a.cpp117#define ATTR __attribute__((noinline)) extern "C"118typedef unsigned long long ULL;119 120ATTR int func_A() { return 1; }121ATTR int func_B() { return 1; }122ATTR int func_C() { return 1; }123 124ATTR ULL take_func_addr() {125 ULL val = 0;126 val += (ULL)(void*)func_A;127 val += (ULL)(void*)func_B;128 val += (ULL)(void*)func_C;129 return val;130}131 132;--- b.cpp133#define ATTR __attribute__((noinline)) extern "C"134typedef unsigned long long ULL;135 136// Identical functions in a different object file137ATTR int func_D() { return 1; }138ATTR int func_E() { return 1; }139ATTR int func_F() { return 1; }140 141ATTR 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 149;--- gen150clang -target arm64-apple-macos11.0 -S -emit-llvm a.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -151echo ""152echo ";--- b.ll"153clang -target arm64-apple-macos11.0 -S -emit-llvm b.cpp -O3 -g -fdebug-compilation-dir=/proc/self/cwd -o -154 155;--- a.ll156; ModuleID = 'a.cpp'157source_filename = "a.cpp"158target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"159target triple = "arm64-apple-macosx11.0.0"160 161; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)162define noundef i32 @func_A() #0 !dbg !12 {163entry:164 ret i32 1, !dbg !16165}166 167; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)168define noundef i32 @func_B() #0 !dbg !17 {169entry:170 ret i32 1, !dbg !18171}172 173; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)174define noundef i32 @func_C() #0 !dbg !19 {175entry:176 ret i32 1, !dbg !20177}178 179; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)180define noundef i64 @take_func_addr() local_unnamed_addr #0 !dbg !21 {181entry:182 #dbg_value(i64 0, !25, !DIExpression(), !26)183 #dbg_value(i64 ptrtoint (ptr @func_A to i64), !25, !DIExpression(), !26)184 #dbg_value(i64 add (i64 ptrtoint (ptr @func_A to i64), i64 ptrtoint (ptr @func_B to i64)), !25, !DIExpression(), !26)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)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 !27187}188 189attributes #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" }190 191!llvm.dbg.cu = !{!0}192!llvm.module.flags = !{!6, !7, !8, !9, !10, !11}193 194!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: "/")195!1 = !DIFile(filename: "a.cpp", directory: "/proc/self/cwd")196!2 = !{!3, !5}197!3 = !DIDerivedType(tag: DW_TAG_typedef, name: "ULL", file: !1, line: 2, baseType: !4)198!4 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned)199!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)200!6 = !{i32 7, !"Dwarf Version", i32 4}201!7 = !{i32 2, !"Debug Info Version", i32 3}202!8 = !{i32 1, !"wchar_size", i32 4}203!9 = !{i32 8, !"PIC Level", i32 2}204!10 = !{i32 7, !"uwtable", i32 1}205!11 = !{i32 7, !"frame-pointer", i32 1}206!12 = distinct !DISubprogram(name: "func_A", scope: !1, file: !1, line: 4, type: !13, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)207!13 = !DISubroutineType(types: !14)208!14 = !{!15}209!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)210!16 = !DILocation(line: 4, column: 21, scope: !12)211!17 = distinct !DISubprogram(name: "func_B", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)212!18 = !DILocation(line: 5, column: 21, scope: !17)213!19 = distinct !DISubprogram(name: "func_C", scope: !1, file: !1, line: 6, type: !13, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)214!20 = !DILocation(line: 6, column: 21, scope: !19)215!21 = distinct !DISubprogram(name: "take_func_addr", scope: !1, file: !1, line: 8, type: !22, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !24)216!22 = !DISubroutineType(types: !23)217!23 = !{!3}218!24 = !{!25}219!25 = !DILocalVariable(name: "val", scope: !21, file: !1, line: 9, type: !3)220!26 = !DILocation(line: 0, scope: !21)221!27 = !DILocation(line: 13, column: 5, scope: !21)222 223;--- b.ll224; ModuleID = 'b.cpp'225source_filename = "b.cpp"226target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"227target triple = "arm64-apple-macosx11.0.0"228 229; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)230define noundef i32 @func_D() #0 !dbg !12 {231entry:232 ret i32 1, !dbg !16233}234 235; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)236define noundef i32 @func_E() #0 !dbg !17 {237entry:238 ret i32 1, !dbg !18239}240 241; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)242define noundef i32 @func_F() #0 !dbg !19 {243entry:244 ret i32 1, !dbg !20245}246 247; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)248define noundef i64 @take_func_addr_b() local_unnamed_addr #0 !dbg !21 {249entry: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 !27255}256 257attributes #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" }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)290