llvm.org GIT mirror llvm / 2bf02e6
Merging r367062: ------------------------------------------------------------------------ r367062 | yhs | 2019-07-25 23:47:27 +0200 (Thu, 25 Jul 2019) | 30 lines [BPF] fix typedef issue for offset relocation Currently, the CO-RE offset relocation does not work if any struct/union member or array element is a typedef. For example, typedef const int arr_t[7]; struct input { arr_t a; }; func(...) { struct input *in = ...; ... __builtin_preserve_access_index(&in->a[1]) ... } The BPF backend calculated default offset is 0 while 4 is the correct answer. Similar issues exist for struct/union typedef's. When getting struct/union member or array element type, we should trace down to the type by skipping typedef and qualifiers const/volatile as this is what clang did to generate getelementptr instructions. (const/volatile member type qualifiers are already ignored by clang.) This patch fixed this issue, for each access index, skipping typedef and const/volatile/restrict BTF types. Signed-off-by: Yonghong Song <yhs@fb.com> Differential Revision: https://reviews.llvm.org/D65259 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_90@367211 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 1 year, 4 months ago
6 changed file(s) with 428 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
2828 #define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
2929 #include "BTF.def"
3030 };
31
32 static const DIType * stripQualifiers(const DIType *Ty) {
33 while (const auto *DTy = dyn_cast(Ty)) {
34 unsigned Tag = DTy->getTag();
35 if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
36 Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type)
37 break;
38 Ty = DTy->getBaseType();
39 }
40
41 return Ty;
42 }
3143
3244 /// Emit a BTF common type.
3345 void BTFTypeBase::emitType(MCStreamer &OS) {
183195 }
184196 }
185197
186 BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize,
187 uint32_t NumElems)
188 : ElemSize(ElemSize) {
198 BTFTypeArray::BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
199 uint32_t ElemSize, uint32_t NumElems)
200 : ElemTyNoQual(Ty), ElemSize(ElemSize) {
189201 Kind = BTF::BTF_KIND_ARRAY;
190202 BTFType.NameOff = 0;
191203 BTFType.Info = Kind << 24;
206218 // created during initial type traversal. Just
207219 // retrieve that type id.
208220 ArrayInfo.IndexType = BDebug.getArrayIndexTypeId();
221
222 ElemTypeNoQual = ElemTyNoQual ? BDebug.getTypeId(ElemTyNoQual)
223 : ArrayInfo.ElemType;
209224 }
210225
211226 void BTFTypeArray::emitType(MCStreamer &OS) {
217232
218233 void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset,
219234 uint32_t &ElementTypeId) {
220 ElementTypeId = ArrayInfo.ElemType;
235 ElementTypeId = ElemTypeNoQual;
221236 LocOffset = Loc * ElemSize;
222237 }
223238
250265 } else {
251266 BTFMember.Offset = DDTy->getOffsetInBits();
252267 }
253 BTFMember.Type = BDebug.getTypeId(DDTy->getBaseType());
268 const auto *BaseTy = DDTy->getBaseType();
269 BTFMember.Type = BDebug.getTypeId(BaseTy);
270 MemberTypeNoQual.push_back(BDebug.getTypeId(stripQualifiers(BaseTy)));
254271 Members.push_back(BTFMember);
255272 }
256273 }
269286
270287 void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset,
271288 uint32_t &MemberType) {
272 MemberType = Members[Loc].Type;
289 MemberType = MemberTypeNoQual[Loc];
273290 MemberOffset =
274291 HasBitField ? Members[Loc].Offset & 0xffffff : Members[Loc].Offset;
275292 }
491508 uint32_t ElemTypeId, ElemSize;
492509 const DIType *ElemType = CTy->getBaseType();
493510 visitTypeEntry(ElemType, ElemTypeId, false, false);
511
512 // Strip qualifiers from element type to get accurate element size.
513 ElemType = stripQualifiers(ElemType);
494514 ElemSize = ElemType->getSizeInBits() >> 3;
495515
496516 if (!CTy->getSizeInBits()) {
497 auto TypeEntry = llvm::make_unique(ElemTypeId, 0, 0);
517 auto TypeEntry = llvm::make_unique(ElemType, ElemTypeId, 0, 0);
498518 ArrayTypes.push_back(TypeEntry.get());
499519 ElemTypeId = addType(std::move(TypeEntry), CTy);
500520 } else {
506526 const DISubrange *SR = cast(Element);
507527 auto *CI = SR->getCount().dyn_cast();
508528 int64_t Count = CI->getSExtValue();
529 const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr;
509530
510531 auto TypeEntry =
511 llvm::make_unique(ElemTypeId, ElemSize, Count);
532 llvm::make_unique(ArrayElemTy, ElemTypeId,
533 ElemSize, Count);
512534 ArrayTypes.push_back(TypeEntry.get());
513535 if (I == 0)
514536 ElemTypeId = addType(std::move(TypeEntry), CTy);
10381060 Offset += LocOffset;
10391061 PrevArrayType = nullptr;
10401062 setTypeFromId(ElementTypeId, &PrevStructType, &PrevArrayType);
1063 } else {
1064 llvm_unreachable("Internal Error: BTF offset relocation type traversal error");
10411065 }
1066
10421067 Start = End + 1;
10431068 End = Start;
10441069 }
103103
104104 /// Handle array type.
105105 class BTFTypeArray : public BTFTypeBase {
106 const DIType *ElemTyNoQual;
106107 uint32_t ElemSize;
107108 struct BTF::BTFArray ArrayInfo;
108
109 public:
110 BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, uint32_t NumElems);
109 uint32_t ElemTypeNoQual;
110
111 public:
112 BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId,
113 uint32_t ElemSize, uint32_t NumElems);
111114 uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
112115 void completeType(BTFDebug &BDebug);
113116 void emitType(MCStreamer &OS);
119122 const DICompositeType *STy;
120123 bool HasBitField;
121124 std::vector Members;
125 std::vector MemberTypeNoQual;
122126
123127 public:
124128 BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
0 ; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
1 ; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
2 ;
3 ; Source code:
4 ; typedef const int arr_t[7];
5 ; typedef arr_t __arr;
6 ; typedef __arr _arr;
7 ; struct __s { _arr a; };
8 ; typedef struct __s s;
9 ; #define _(x) (__builtin_preserve_access_index(x))
10 ; int get_value(const void *addr);
11 ; int test(s *arg) {
12 ; return get_value(_(&arg->a[1]));
13 ; }
14 ; clang -target bpf -S -O2 -g -emit-llvm test.c
15
16 %struct.__s = type { [7 x i32] }
17
18 ; Function Attrs: nounwind
19 define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 {
20 entry:
21 call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !24, metadata !DIExpression()), !dbg !25
22 %0 = tail call [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s* %arg, i32 0, i32 0), !dbg !26, !llvm.preserve.access.index !13
23 %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]* %0, i32 1, i32 1), !dbg !26
24 %2 = bitcast i32* %1 to i8*, !dbg !26
25 %call = tail call i32 @get_value(i8* %2) #4, !dbg !27
26 ret i32 %call, !dbg !28
27 }
28
29 ; CHECK: .cfi_startproc
30 ; CHECK: [[RELOC:.Ltmp[0-9]+]]:
31 ; CHECK: r2 = 4
32 ; CHECK: r1 += r2
33 ; CHECK: call get_value
34
35 ; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]])
36 ; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]]
37 ; CHECK-NEXT: .byte 0
38 ; CHECK: .ascii "0:0:1" # string offset=[[ACCESS_STR:[0-9]+]]
39 ; CHECK-NEXT: .byte 0
40 ; CHECK: .long 12 # OffsetReloc
41 ; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]]
42 ; CHECK-NEXT: .long 1
43 ; CHECK-NEXT: .long [[RELOC]]
44 ; CHECK-NEXT: .long [[TYPE_ID]]
45 ; CHECK-NEXT: .long [[ACCESS_STR]]
46
47 declare dso_local i32 @get_value(i8*) local_unnamed_addr #1
48
49 ; Function Attrs: nounwind readnone
50 declare [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2
51
52 ; Function Attrs: nounwind readnone
53 declare i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]*, i32 immarg, i32 immarg) #2
54
55 ; Function Attrs: nounwind readnone speculatable
56 declare void @llvm.dbg.value(metadata, metadata, metadata) #3
57
58 attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
59 attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
60 attributes #2 = { nounwind readnone }
61 attributes #3 = { nounwind readnone speculatable }
62 attributes #4 = { nounwind }
63
64 !llvm.dbg.cu = !{!0}
65 !llvm.module.flags = !{!3, !4, !5}
66 !llvm.ident = !{!6}
67
68 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
69 !1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs")
70 !2 = !{}
71 !3 = !{i32 2, !"Dwarf Version", i32 4}
72 !4 = !{i32 2, !"Debug Info Version", i32 3}
73 !5 = !{i32 1, !"wchar_size", i32 4}
74 !6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"}
75 !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !23)
76 !8 = !DISubroutineType(types: !9)
77 !9 = !{!10, !11}
78 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
79 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
80 !12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13)
81 !13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 4, size: 224, elements: !14)
82 !14 = !{!15}
83 !15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !1, line: 4, baseType: !16, size: 224)
84 !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "_arr", file: !1, line: 3, baseType: !17)
85 !17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 2, baseType: !18)
86 !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 1, baseType: !19)
87 !19 = !DICompositeType(tag: DW_TAG_array_type, baseType: !20, size: 224, elements: !21)
88 !20 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10)
89 !21 = !{!22}
90 !22 = !DISubrange(count: 7)
91 !23 = !{!24}
92 !24 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11)
93 !25 = !DILocation(line: 0, scope: !7)
94 !26 = !DILocation(line: 9, column: 20, scope: !7)
95 !27 = !DILocation(line: 9, column: 10, scope: !7)
96 !28 = !DILocation(line: 9, column: 3, scope: !7)
0 ; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
1 ; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
2 ;
3 ; Source code:
4 ; typedef int _int;
5 ; typedef _int __int;
6 ; struct __s { __int a; __int b; };
7 ; typedef struct __s _s;
8 ; typedef _s s;
9 ; #define _(x) (__builtin_preserve_access_index(x))
10 ; int get_value(const void *addr);
11 ; int test(s *arg) {
12 ; return get_value(_(&arg->b));
13 ; }
14 ; clang -target bpf -S -O2 -g -emit-llvm test.c
15
16 %struct.__s = type { i32, i32 }
17
18 ; Function Attrs: nounwind
19 define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 {
20 entry:
21 call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !22
22 %0 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ss(%struct.__s* %arg, i32 1, i32 1), !dbg !23, !llvm.preserve.access.index !14
23 %1 = bitcast i32* %0 to i8*, !dbg !23
24 %call = tail call i32 @get_value(i8* %1) #4, !dbg !24
25 ret i32 %call, !dbg !25
26 }
27
28 ; CHECK: .cfi_startproc
29 ; CHECK: [[RELOC:.Ltmp[0-9]+]]:
30 ; CHECK: r2 = 4
31 ; CHECK: r1 += r2
32 ; CHECK: call get_value
33
34 ; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]])
35 ; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]]
36 ; CHECK-NEXT: .byte 0
37 ; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]]
38 ; CHECK-NEXT: .byte 0
39 ; CHECK: .long 12 # OffsetReloc
40 ; CHECK-NEXT: .long [[SEC_STR]] # Offset reloc section string offset={{[0-9]+}}
41 ; CHECK-NEXT: .long 1
42 ; CHECK-NEXT: .long [[RELOC]]
43 ; CHECK-NEXT: .long [[TYPE_ID]]
44 ; CHECK-NEXT: .long [[ACCESS_STR]]
45
46 declare dso_local i32 @get_value(i8*) local_unnamed_addr #1
47
48 ; Function Attrs: nounwind readnone
49 declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2
50
51 ; Function Attrs: nounwind readnone speculatable
52 declare void @llvm.dbg.value(metadata, metadata, metadata) #3
53
54 attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
55 attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
56 attributes #2 = { nounwind readnone }
57 attributes #3 = { nounwind readnone speculatable }
58 attributes #4 = { nounwind }
59
60 !llvm.dbg.cu = !{!0}
61 !llvm.module.flags = !{!3, !4, !5}
62 !llvm.ident = !{!6}
63
64 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
65 !1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs")
66 !2 = !{}
67 !3 = !{i32 2, !"Dwarf Version", i32 4}
68 !4 = !{i32 2, !"Debug Info Version", i32 3}
69 !5 = !{i32 1, !"wchar_size", i32 4}
70 !6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"}
71 !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !20)
72 !8 = !DISubroutineType(types: !9)
73 !9 = !{!10, !11}
74 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
75 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
76 !12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13)
77 !13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14)
78 !14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 3, size: 64, elements: !15)
79 !15 = !{!16, !19}
80 !16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32)
81 !17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18)
82 !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10)
83 !19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32, offset: 32)
84 !20 = !{!21}
85 !21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11)
86 !22 = !DILocation(line: 0, scope: !7)
87 !23 = !DILocation(line: 9, column: 20, scope: !7)
88 !24 = !DILocation(line: 9, column: 10, scope: !7)
89 !25 = !DILocation(line: 9, column: 3, scope: !7)
0 ; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
1 ; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
2 ;
3 ; Source code:
4 ; typedef int _int;
5 ; typedef _int __int;
6 ; union __s { __int a; __int b; };
7 ; typedef union __s _s;
8 ; typedef _s s;
9 ; #define _(x) (__builtin_preserve_access_index(x))
10 ; int get_value(const void *addr);
11 ; int test(s *arg) {
12 ; return get_value(_(&arg->b));
13 ; }
14 ; clang -target bpf -S -O2 -g -emit-llvm test.c
15
16 %union.__s = type { i32 }
17
18 ; Function Attrs: nounwind
19 define dso_local i32 @test(%union.__s* %arg) local_unnamed_addr #0 !dbg !7 {
20 entry:
21 call void @llvm.dbg.value(metadata %union.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !22
22 %0 = tail call %union.__s* @llvm.preserve.union.access.index.p0s_union.__ss.p0s_union.__ss(%union.__s* %arg, i32 1), !dbg !23, !llvm.preserve.access.index !14
23 %1 = bitcast %union.__s* %0 to i8*, !dbg !23
24 %call = tail call i32 @get_value(i8* %1) #4, !dbg !24
25 ret i32 %call, !dbg !25
26 }
27
28 ; CHECK: .cfi_startproc
29 ; CHECK: [[RELOC:.Ltmp[0-9]+]]:
30 ; CHECK: r2 = 0
31 ; CHECK: r1 += r2
32 ; CHECK: call get_value
33
34 ; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]])
35 ; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]]
36 ; CHECK-NEXT: .byte 0
37 ; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]]
38 ; CHECK-NEXT: .byte 0
39 ; CHECK: .long 12 # OffsetReloc
40 ; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]]
41 ; CHECK-NEXT: .long 1
42 ; CHECK-NEXT: .long [[RELOC]]
43 ; CHECK-NEXT: .long [[TYPE_ID]]
44 ; CHECK-NEXT: .long [[ACCESS_STR]]
45
46 declare dso_local i32 @get_value(i8*) local_unnamed_addr #1
47
48 ; Function Attrs: nounwind readnone
49 declare %union.__s* @llvm.preserve.union.access.index.p0s_union.__ss.p0s_union.__ss(%union.__s*, i32 immarg) #2
50
51 ; Function Attrs: nounwind readnone speculatable
52 declare void @llvm.dbg.value(metadata, metadata, metadata) #3
53
54 attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
55 attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
56 attributes #2 = { nounwind readnone }
57 attributes #3 = { nounwind readnone speculatable }
58 attributes #4 = { nounwind }
59
60 !llvm.dbg.cu = !{!0}
61 !llvm.module.flags = !{!3, !4, !5}
62 !llvm.ident = !{!6}
63
64 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
65 !1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs")
66 !2 = !{}
67 !3 = !{i32 2, !"Dwarf Version", i32 4}
68 !4 = !{i32 2, !"Debug Info Version", i32 3}
69 !5 = !{i32 1, !"wchar_size", i32 4}
70 !6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"}
71 !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !20)
72 !8 = !DISubroutineType(types: !9)
73 !9 = !{!10, !11}
74 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
75 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
76 !12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13)
77 !13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14)
78 !14 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "__s", file: !1, line: 3, size: 32, elements: !15)
79 !15 = !{!16, !19}
80 !16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32)
81 !17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18)
82 !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10)
83 !19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32)
84 !20 = !{!21}
85 !21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11)
86 !22 = !DILocation(line: 0, scope: !7)
87 !23 = !DILocation(line: 9, column: 20, scope: !7)
88 !24 = !DILocation(line: 9, column: 10, scope: !7)
89 !25 = !DILocation(line: 9, column: 3, scope: !7)
0 ; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
1 ; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
2 ;
3 ; Source code:
4 ; struct s { int a; int b; };
5 ; typedef struct s __s;
6 ; union u { __s c; __s d; };
7 ; typedef union u __u;
8 ; typedef __u arr_t[7];
9 ; typedef arr_t __arr;
10 ;
11 ; #define _(x) (__builtin_preserve_access_index(x))
12 ; int get_value(const void *addr);
13 ; int test(__arr *arg) {
14 ; return get_value(_(&arg[1]->d.b));
15 ; }
16 ; clang -target bpf -S -O2 -g -emit-llvm test.c
17 ; The offset reloc offset should be 12 from the base "arg".
18
19 %union.u = type { %struct.s }
20 %struct.s = type { i32, i32 }
21
22 ; Function Attrs: nounwind
23 define dso_local i32 @test([7 x %union.u]* %arg) local_unnamed_addr #0 !dbg !7 {
24 entry:
25 call void @llvm.dbg.value(metadata [7 x %union.u]* %arg, metadata !28, metadata !DIExpression()), !dbg !29
26 %0 = tail call [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]* %arg, i32 0, i32 1), !dbg !30
27 %arraydecay = getelementptr inbounds [7 x %union.u], [7 x %union.u]* %0, i64 0, i64 0, !dbg !30
28 %1 = tail call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %arraydecay, i32 1), !dbg !30, !llvm.preserve.access.index !16
29 %d = getelementptr inbounds %union.u, %union.u* %1, i64 0, i32 0, !dbg !30
30 %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %d, i32 1, i32 1), !dbg !30, !llvm.preserve.access.index !20
31 %3 = bitcast i32* %2 to i8*, !dbg !30
32 %call = tail call i32 @get_value(i8* %3) #4, !dbg !31
33 ret i32 %call, !dbg !32
34 }
35
36 ; CHECK: .cfi_startproc
37 ; CHECK: [[RELOC:.Ltmp[0-9]+]]:
38 ; CHECK: r2 = 12
39 ; CHECK: r1 += r2
40 ; CHECK: call get_value
41
42 ; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]])
43 ; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]]
44 ; CHECK-NEXT: .byte 0
45 ; CHECK: .ascii "1:1:1" # string offset=[[ACCESS_STR:[0-9]+]]
46 ; CHECK-NEXT: .byte 0
47 ; CHECK: .long 12 # OffsetReloc
48 ; CHECK-NEXT: .long [[SEC_STR:[0-9]+]] # Offset reloc section string offset=[[SEC_STR:[0-9]+]]
49 ; CHECK-NEXT: .long 1
50 ; CHECK-NEXT: .long [[RELOC:.Ltmp[0-9]+]]
51 ; CHECK-NEXT: .long [[TYPE_ID:[0-9]+]]
52 ; CHECK-NEXT: .long [[ACCESS_STR:[0-9]+]]
53
54 declare dso_local i32 @get_value(i8*) local_unnamed_addr #1
55
56 ; Function Attrs: nounwind readnone
57 declare [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]*, i32 immarg, i32 immarg) #2
58
59 ; Function Attrs: nounwind readnone
60 declare %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u*, i32 immarg) #2
61
62 ; Function Attrs: nounwind readnone
63 declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s*, i32 immarg, i32 immarg) #2
64
65 ; Function Attrs: nounwind readnone speculatable
66 declare void @llvm.dbg.value(metadata, metadata, metadata) #3
67
68 attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
69 attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
70 attributes #2 = { nounwind readnone }
71 attributes #3 = { nounwind readnone speculatable }
72 attributes #4 = { nounwind }
73
74 !llvm.dbg.cu = !{!0}
75 !llvm.module.flags = !{!3, !4, !5}
76 !llvm.ident = !{!6}
77
78 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
79 !1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs")
80 !2 = !{}
81 !3 = !{i32 2, !"Dwarf Version", i32 4}
82 !4 = !{i32 2, !"Debug Info Version", i32 3}
83 !5 = !{i32 1, !"wchar_size", i32 4}
84 !6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"}
85 !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 10, type: !8, scopeLine: 10, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27)
86 !8 = !DISubroutineType(types: !9)
87 !9 = !{!10, !11}
88 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
89 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
90 !12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 6, baseType: !13)
91 !13 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 5, baseType: !14)
92 !14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 448, elements: !25)
93 !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u", file: !1, line: 4, baseType: !16)
94 !16 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u", file: !1, line: 3, size: 64, elements: !17)
95 !17 = !{!18, !24}
96 !18 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !16, file: !1, line: 3, baseType: !19, size: 64)
97 !19 = !DIDerivedType(tag: DW_TAG_typedef, name: "__s", file: !1, line: 2, baseType: !20)
98 !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 64, elements: !21)
99 !21 = !{!22, !23}
100 !22 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !20, file: !1, line: 1, baseType: !10, size: 32)
101 !23 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !20, file: !1, line: 1, baseType: !10, size: 32, offset: 32)
102 !24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !16, file: !1, line: 3, baseType: !19, size: 64)
103 !25 = !{!26}
104 !26 = !DISubrange(count: 7)
105 !27 = !{!28}
106 !28 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 10, type: !11)
107 !29 = !DILocation(line: 0, scope: !7)
108 !30 = !DILocation(line: 11, column: 20, scope: !7)
109 !31 = !DILocation(line: 11, column: 10, scope: !7)
110 !32 = !DILocation(line: 11, column: 3, scope: !7)