Index: lib/Target/BPF/BTFDebug.h =================================================================== --- lib/Target/BPF/BTFDebug.h +++ lib/Target/BPF/BTFDebug.h @@ -104,11 +104,14 @@ /// Handle array type. class BTFTypeArray : public BTFTypeBase { + const DIType *ElemTyNoQual; uint32_t ElemSize; struct BTF::BTFArray ArrayInfo; + uint32_t ElemTypeNoQual; public: - BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, uint32_t NumElems); + BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId, + uint32_t ElemSize, uint32_t NumElems); uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; } void completeType(BTFDebug &BDebug); void emitType(MCStreamer &OS); @@ -120,6 +123,7 @@ const DICompositeType *STy; bool HasBitField; std::vector Members; + std::vector MemberTypeNoQual; public: BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, Index: lib/Target/BPF/BTFDebug.cpp =================================================================== --- lib/Target/BPF/BTFDebug.cpp +++ lib/Target/BPF/BTFDebug.cpp @@ -30,6 +30,18 @@ #include "BTF.def" }; +static const DIType * stripQualifiers(const DIType *Ty) { + while (const auto *DTy = dyn_cast(Ty)) { + unsigned Tag = DTy->getTag(); + if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && Tag == dwarf::DW_TAG_restrict_type) + break; + Ty = DTy->getBaseType(); + } + + return Ty; +} + /// Emit a BTF common type. void BTFTypeBase::emitType(MCStreamer &OS) { OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + @@ -40,6 +52,7 @@ OS.EmitIntValue(BTFType.Size, 4); } + BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag, bool NeedsFixup) : DTy(DTy), NeedsFixup(NeedsFixup) { @@ -184,9 +197,9 @@ } } -BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, - uint32_t NumElems) - : ElemSize(ElemSize) { +BTFTypeArray::BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId, + uint32_t ElemSize, uint32_t NumElems) + : ElemTyNoQual(Ty), ElemSize(ElemSize) { Kind = BTF::BTF_KIND_ARRAY; BTFType.NameOff = 0; BTFType.Info = Kind << 24; @@ -207,6 +220,9 @@ // created during initial type traversal. Just // retrieve that type id. ArrayInfo.IndexType = BDebug.getArrayIndexTypeId(); + + ElemTypeNoQual = ElemTyNoQual ? BDebug.getTypeId(ElemTyNoQual) + : ArrayInfo.ElemType; } void BTFTypeArray::emitType(MCStreamer &OS) { @@ -218,7 +234,7 @@ void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset, uint32_t &ElementTypeId) { - ElementTypeId = ArrayInfo.ElemType; + ElementTypeId = ElemTypeNoQual; LocOffset = Loc * ElemSize; } @@ -251,7 +267,9 @@ } else { BTFMember.Offset = DDTy->getOffsetInBits(); } - BTFMember.Type = BDebug.getTypeId(DDTy->getBaseType()); + const auto *BaseTy = DDTy->getBaseType(); + BTFMember.Type = BDebug.getTypeId(BaseTy); + MemberTypeNoQual.push_back(BDebug.getTypeId(stripQualifiers(BaseTy))); Members.push_back(BTFMember); } } @@ -270,7 +288,7 @@ void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset, uint32_t &MemberType) { - MemberType = Members[Loc].Type; + MemberType = MemberTypeNoQual[Loc]; MemberOffset = HasBitField ? Members[Loc].Offset & 0xffffff : Members[Loc].Offset; } @@ -492,10 +510,13 @@ uint32_t ElemTypeId, ElemSize; const DIType *ElemType = CTy->getBaseType(); visitTypeEntry(ElemType, ElemTypeId, false, false); + + // Strip qualifiers from element type to get accurate element size. + ElemType = stripQualifiers(ElemType); ElemSize = ElemType->getSizeInBits() >> 3; if (!CTy->getSizeInBits()) { - auto TypeEntry = llvm::make_unique(ElemTypeId, 0, 0); + auto TypeEntry = llvm::make_unique(ElemType, ElemTypeId, 0, 0); ArrayTypes.push_back(TypeEntry.get()); ElemTypeId = addType(std::move(TypeEntry), CTy); } else { @@ -507,9 +528,11 @@ const DISubrange *SR = cast(Element); auto *CI = SR->getCount().dyn_cast(); int64_t Count = CI->getSExtValue(); + const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr; auto TypeEntry = - llvm::make_unique(ElemTypeId, ElemSize, Count); + llvm::make_unique(ArrayElemTy, ElemTypeId, + ElemSize, Count); ArrayTypes.push_back(TypeEntry.get()); if (I == 0) ElemTypeId = addType(std::move(TypeEntry), CTy); @@ -1039,7 +1062,10 @@ Offset += LocOffset; PrevArrayType = nullptr; setTypeFromId(ElementTypeId, &PrevStructType, &PrevArrayType); + } else { + llvm_unreachable("Internal Error: BTF offset relocation type traversal error"); } + Start = End + 1; End = Start; } Index: test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll @@ -0,0 +1,97 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef const int arr_t[7]; +; typedef arr_t __arr; +; typedef __arr _arr; +; struct __s { _arr a; }; +; typedef struct __s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->a[1])); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%struct.__s = type { [7 x i32] } + +; Function Attrs: nounwind +define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !24, metadata !DIExpression()), !dbg !25 + %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 + %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]* %0, i32 1, i32 1), !dbg !26 + %2 = bitcast i32* %1 to i8*, !dbg !26 + %call = tail call i32 @get_value(i8* %2) #4, !dbg !27 + ret i32 %call, !dbg !28 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 4 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +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" } +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" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!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) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!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) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 4, size: 224, elements: !14) +!14 = !{!15} +!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !1, line: 4, baseType: !16, size: 224) +!16 = !DIDerivedType(tag: DW_TAG_typedef, name: "_arr", file: !1, line: 3, baseType: !17) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 1, baseType: !19) +!19 = !DICompositeType(tag: DW_TAG_array_type, baseType: !20, size: 224, elements: !21) +!20 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!21 = !{!22} +!22 = !DISubrange(count: 7) +!23 = !{!24} +!24 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!25 = !DILocation(line: 0, scope: !7) +!26 = !DILocation(line: 9, column: 20, scope: !7) +!27 = !DILocation(line: 9, column: 10, scope: !7) +!28 = !DILocation(line: 9, column: 3, scope: !7) Index: test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef int _int; +; typedef _int __int; +; struct __s { __int a; __int b; }; +; typedef struct __s _s; +; typedef _s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%struct.__s = type { i32, i32 } + +; Function Attrs: nounwind +define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !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 + %1 = bitcast i32* %0 to i8*, !dbg !23 + %call = tail call i32 @get_value(i8* %1) #4, !dbg !24 + ret i32 %call, !dbg !25 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 4 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_STR]] # Offset reloc section string offset={{[0-9]+}} +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +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" } +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" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!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) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!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) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14) +!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 3, size: 64, elements: !15) +!15 = !{!16, !19} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32, offset: 32) +!20 = !{!21} +!21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!22 = !DILocation(line: 0, scope: !7) +!23 = !DILocation(line: 9, column: 20, scope: !7) +!24 = !DILocation(line: 9, column: 10, scope: !7) +!25 = !DILocation(line: 9, column: 3, scope: !7) Index: test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef int _int; +; typedef _int __int; +; union __s { __int a; __int b; }; +; typedef union __s _s; +; typedef _s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%union.__s = type { i32 } + +; Function Attrs: nounwind +define dso_local i32 @test(%union.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %union.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !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 + %1 = bitcast %union.__s* %0 to i8*, !dbg !23 + %call = tail call i32 @get_value(i8* %1) #4, !dbg !24 + ret i32 %call, !dbg !25 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 0 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare %union.__s* @llvm.preserve.union.access.index.p0s_union.__ss.p0s_union.__ss(%union.__s*, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +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" } +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" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!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) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!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) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14) +!14 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "__s", file: !1, line: 3, size: 32, elements: !15) +!15 = !{!16, !19} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!20 = !{!21} +!21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!22 = !DILocation(line: 0, scope: !7) +!23 = !DILocation(line: 9, column: 20, scope: !7) +!24 = !DILocation(line: 9, column: 10, scope: !7) +!25 = !DILocation(line: 9, column: 3, scope: !7) Index: test/CodeGen/BPF/CORE/offset-reloc-typedef.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/CORE/offset-reloc-typedef.ll @@ -0,0 +1,111 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; struct s { int a; int b; }; +; typedef struct s __s; +; union u { __s c; __s d; }; +; typedef union u __u; +; typedef __u arr_t[7]; +; typedef arr_t __arr; +; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(__arr *arg) { +; return get_value(_(&arg[1]->d.b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c +; The offset reloc offset should be 12 from the base "arg". + +%union.u = type { %struct.s } +%struct.s = type { i32, i32 } + +; Function Attrs: nounwind +define dso_local i32 @test([7 x %union.u]* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata [7 x %union.u]* %arg, metadata !28, metadata !DIExpression()), !dbg !29 + %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 + %arraydecay = getelementptr inbounds [7 x %union.u], [7 x %union.u]* %0, i64 0, i64 0, !dbg !30 + %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 + %d = getelementptr inbounds %union.u, %union.u* %1, i64 0, i32 0, !dbg !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 + %3 = bitcast i32* %2 to i8*, !dbg !30 + %call = tail call i32 @get_value(i8* %3) #4, !dbg !31 + ret i32 %call, !dbg !32 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 12 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "1:1:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_STR:[0-9]+]] # Offset reloc section string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC:.Ltmp[0-9]+]] +; CHECK-NEXT: .long [[TYPE_ID:[0-9]+]] +; CHECK-NEXT: .long [[ACCESS_STR:[0-9]+]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +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 + +; Function Attrs: nounwind readnone +declare %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u*, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +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" } +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" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!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) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!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) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 6, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 5, baseType: !14) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 448, elements: !25) +!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u", file: !1, line: 4, baseType: !16) +!16 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u", file: !1, line: 3, size: 64, elements: !17) +!17 = !{!18, !24} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !16, file: !1, line: 3, baseType: !19, size: 64) +!19 = !DIDerivedType(tag: DW_TAG_typedef, name: "__s", file: !1, line: 2, baseType: !20) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 64, elements: !21) +!21 = !{!22, !23} +!22 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !20, file: !1, line: 1, baseType: !10, size: 32) +!23 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !20, file: !1, line: 1, baseType: !10, size: 32, offset: 32) +!24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !16, file: !1, line: 3, baseType: !19, size: 64) +!25 = !{!26} +!26 = !DISubrange(count: 7) +!27 = !{!28} +!28 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 10, type: !11) +!29 = !DILocation(line: 0, scope: !7) +!30 = !DILocation(line: 11, column: 20, scope: !7) +!31 = !DILocation(line: 11, column: 10, scope: !7) +!32 = !DILocation(line: 11, column: 3, scope: !7)