{FieldAddr->getType()});
return Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
}
- case BPF::BI__builtin_btf_type_id: {
- Value *FieldVal = nullptr;
-
- // The LValue cannot be converted Value in order to be used as the function
- // parameter. If it is a structure, it is the "alloca" result of the LValue
- // (a pointer) is used in the parameter. If it is a simple type,
- // the value will be loaded from its corresponding "alloca" and used as
- // the parameter. In our case, let us just get a pointer of the LValue
- // since we do not really use the parameter. The purpose of parameter
- // is to prevent the generated IR llvm.bpf.btf.type.id intrinsic call,
- // which carries metadata, from being changed.
- bool IsLValue = E->getArg(0)->isLValue();
- if (IsLValue)
- FieldVal = EmitLValue(E->getArg(0)).getPointer(*this);
- else
- FieldVal = EmitScalarExpr(E->getArg(0));
-
- if (!getDebugInfo()) {
- CGM.Error(E->getExprLoc(), "using __builtin_btf_type_id() without -g");
- return nullptr;
- }
-
- // Generate debuginfo type for the first argument.
- llvm::DIType *DbgInfo =
- getDebugInfo()->getOrCreateStandaloneType(E->getArg(0)->getType(),
- E->getArg(0)->getExprLoc());
-
- ConstantInt *Flag = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
- Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
-
- // Built the IR for the btf_type_id intrinsic.
- //
- // In the above, we converted LValue argument to a pointer to LValue.
- // For example, the following
- // int v;
- // C1: __builtin_btf_type_id(v, flag);
- // will be converted to
- // L1: llvm.bpf.btf.type.id(&v, flag)
- // This makes it hard to differentiate from
- // C2: __builtin_btf_type_id(&v, flag);
- // to
- // L2: llvm.bpf.btf.type.id(&v, flag)
- //
- // If both C1 and C2 are present in the code, the llvm may later
- // on do CSE on L1 and L2, which will result in incorrect tagged types.
- //
- // The C1->L1 transformation only happens if the argument of
- // __builtin_btf_type_id() is a LValue. So Let us put whether
- // the argument is an LValue or not into generated IR. This should
- // prevent potential CSE from causing debuginfo type loss.
- //
- // The generated IR intrinsics will hence look like
- // L1: llvm.bpf.btf.type.id(&v, 1, flag) !di_type_for_{v};
- // L2: llvm.bpf.btf.type.id(&v, 0, flag) !di_type_for_{&v};
- Constant *CV = ConstantInt::get(IntTy, IsLValue);
- llvm::Function *FnBtfTypeId = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::bpf_btf_type_id,
- {FieldVal->getType(), CV->getType()});
- CallInst *Fn = Builder.CreateCall(FnBtfTypeId, {FieldVal, CV, FlagValue});
- Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
- return Fn;
- }
+ case BPF::BI__builtin_btf_type_id:
case BPF::BI__builtin_preserve_type_info: {
if (!getDebugInfo()) {
CGM.Error(E->getExprLoc(), "using builtin function without -g");
Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
Value *SeqNumVal = ConstantInt::get(Int32Ty, BuiltinSeqNum++);
- llvm::Function *FnPreserveTypeInfo = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::bpf_preserve_type_info, {});
- CallInst *Fn =
- Builder.CreateCall(FnPreserveTypeInfo, {SeqNumVal, FlagValue});
+ llvm::Function *FnDecl;
+ if (BuiltinID == BPF::BI__builtin_btf_type_id)
+ FnDecl = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::bpf_btf_type_id, {});
+ else
+ FnDecl = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::bpf_preserve_type_info, {});
+ CallInst *Fn = Builder.CreateCall(FnDecl, {SeqNumVal, FlagValue});
Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
return Fn;
}
unsigned test1(int a) { return __builtin_btf_type_id(a, 0); }
unsigned test2(int a) { return __builtin_btf_type_id(&a, 0); }
+struct t1 { int a; };
+typedef struct t1 __t1;
+unsigned test3() {
+ return __builtin_btf_type_id(*(struct t1 *)0, 1) +
+ __builtin_btf_type_id(*(__t1 *)0, 1);
+}
+
// CHECK: define dso_local i32 @test1
-// CHECK: call i32 @llvm.bpf.btf.type.id.p0i32.i32(i32* %{{[0-9a-z.]+}}, i32 1, i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.btf.type.id(i32 0, i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT:[0-9]+]]
// CHECK: define dso_local i32 @test2
-// CHECK: call i32 @llvm.bpf.btf.type.id.p0i32.i32(i32* %{{[0-9a-z.]+}}, i32 0, i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT_POINTER:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.btf.type.id(i32 1, i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT_POINTER:[0-9]+]]
+// CHECK: define dso_local i32 @test3
+// CHECK: call i32 @llvm.bpf.btf.type.id(i32 2, i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_T1:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.btf.type.id(i32 3, i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_T1:[0-9]+]]
//
// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
// CHECK: ![[INT_POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[INT]], size: 64
+// CHECK: ![[TYPEDEF_T1]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__t1"
+// CHECK: ![[STRUCT_T1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1"
; bpf_log(__builtin_btf_type_id(tmp__abc, 0), &tmp__abc, sizeof(tmp__abc));
; }
; void prog2() {
-; bpf_log(__builtin_btf_type_id(&tmp__abc, 1), &tmp__abc, sizeof(tmp__abc));
+; bpf_log(__builtin_btf_type_id(&tmp__abc, 0), &tmp__abc, sizeof(tmp__abc));
; }
; void prog3() {
; bpf_log(__builtin_btf_type_id(tmp__abc.f1[3], 1), &tmp__abc, sizeof(tmp__abc));
; Compilation flag:
; clang -target bpf -O2 -g -S -emit-llvm test.c
-%struct.anon = type { [100 x i8], i32 }
-
@tmp__abc = dso_local global { <{ i8, i8, [98 x i8] }>, i32 } { <{ i8, i8, [98 x i8] }> <{ i8 1, i8 3, [98 x i8] zeroinitializer }>, i32 0 }, align 4, !dbg !0
; Function Attrs: nounwind
define dso_local void @prog1() local_unnamed_addr #0 !dbg !28 {
entry:
- %0 = tail call i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon* bitcast ({ <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc to %struct.anon*), i32 1, i64 0), !dbg !31, !llvm.preserve.access.index !7
+ %0 = tail call i32 @llvm.bpf.btf.type.id(i32 0, i64 0), !dbg !31, !llvm.preserve.access.index !7
%call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !32
ret void, !dbg !33
}
; Function Attrs: nounwind readnone
-declare i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon*, i32, i64) #1
+declare i32 @llvm.bpf.btf.type.id(i32, i64) #1
; Function Attrs: nounwind
define dso_local void @prog2() local_unnamed_addr #0 !dbg !34 {
entry:
- %0 = tail call i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon* bitcast ({ <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc to %struct.anon*), i32 0, i64 1), !dbg !35, !llvm.preserve.access.index !6
+ %0 = tail call i32 @llvm.bpf.btf.type.id(i32 1, i64 0), !dbg !35, !llvm.preserve.access.index !6
%call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !36
ret void, !dbg !37
}
; Function Attrs: nounwind
define dso_local void @prog3() local_unnamed_addr #0 !dbg !38 {
entry:
- %0 = tail call i32 @llvm.bpf.btf.type.id.p0i8.i32(i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 2, i64 1), i32 1, i64 1), !dbg !39, !llvm.preserve.access.index !11
+ %0 = tail call i32 @llvm.bpf.btf.type.id(i32 2, i64 1), !dbg !39, !llvm.preserve.access.index !11
%call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !40
ret void, !dbg !41
}
-; CHECK-LABEL: prog1
-; CHECK: r1 = 3
-; CHECK-LABEL: prog2
-; CHECK: r1 = 10
-; CHECK-LABEL: prog3
-; CHECK: r1 = 4
-;
-; CHECK: .long 0 # BTF_KIND_STRUCT(id = 3)
-; CHECK-NEXT: .long 67108866 # 0x4000002
-; CHECK-NEXT: .long 104
-; CHECK-NEXT: .long 13
-; CHECK-NEXT: .long 5
-; CHECK-NEXT: .long 0 # 0x0
-; CHECK-NEXT: .long 16
-; CHECK-NEXT: .long 7
-; CHECK-NEXT: .long 800 # 0x320
-; CHECK-NEXT: .long 19 # BTF_KIND_INT(id = 4)
-; CHECK-NEXT: .long 16777216 # 0x1000000
-; CHECK-NEXT: .long 1
-; CHECK-NEXT: .long 16777224 # 0x1000008
-; CHECK: .long 0 # BTF_KIND_PTR(id = 10)
-; CHECK-NEXT: .long 33554432 # 0x2000000
-; CHECK-NEXT: .long 3
+; CHECK-LABEL: prog1
+; CHECK: r1 = 3
+; CHECK-LABEL: prog2
+; CHECK: r1 = 10
+; CHECK-LABEL: prog3
+; CHECK: r1 = 4
-; CHECK: .long 16 # FieldReloc
-; CHECK-NEXT: .long {{[0-9]+}} # Field reloc section string offset={{[0-9]+}}
-; CHECK-NEXT: .long 3
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .long 3
-; CHECK-NEXT: .long {{[0-9]+}}
-; CHECK-NEXT: .long 6
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .long 10
-; CHECK-NEXT: .long {{[0-9]+}}
-; CHECK-NEXT: .long 7
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .long 4
-; CHECK-NEXT: .long {{[0-9]+}}
-; CHECK-NEXT: .long 7
+; CHECK: .long 0 # BTF_KIND_STRUCT(id = 3)
+; CHECK-NEXT: .long 67108866 # 0x4000002
+; CHECK-NEXT: .long 104
+; CHECK-NEXT: .long 13
+; CHECK-NEXT: .long 5
+; CHECK-NEXT: .long 0 # 0x0
+; CHECK-NEXT: .long 16
+; CHECK-NEXT: .long 7
+; CHECK-NEXT: .long 800 # 0x320
+; CHECK: .long 19 # BTF_KIND_INT(id = 4)
+; CHECK: .long 0 # BTF_KIND_PTR(id = 10)
+; CHECK-NEXT: .long 33554432 # 0x2000000
+; CHECK-NEXT: .long 3
+; CHECK: .ascii ".text" # string offset=7
+; CHECK: .ascii "f1" # string offset=13
+; CHECK: .ascii "f2" # string offset=16
+; CHECK: .ascii "char" # string offset=19
+; CHECK: .byte 48 # string offset=48
-; Function Attrs: nounwind readnone
-declare i32 @llvm.bpf.btf.type.id.p0i8.i32(i8*, i32, i64) #1
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long 7 # Field reloc section string offset=7
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 48
+; CHECK-NEXT: .long 6
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 10
+; CHECK-NEXT: .long 48
+; CHECK-NEXT: .long 6
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long 48
+; CHECK-NEXT: .long 7
-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 #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"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone }
attributes #2 = { nounwind }
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "tmp__abc", scope: !2, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true)
-!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 95253d8f16b8085b4b85cb3a6106ccbfe8a6d9b2)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !16, splitDebugInlining: false, nameTableKind: None)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git f39aae11dca3f8f8c2c755a871726ed2fa82fd57)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !16, splitDebugInlining: false, nameTableKind: None)
!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
!4 = !{}
!5 = !{!6, !11}
!24 = !{i32 7, !"Dwarf Version", i32 4}
!25 = !{i32 2, !"Debug Info Version", i32 3}
!26 = !{i32 1, !"wchar_size", i32 4}
-!27 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 95253d8f16b8085b4b85cb3a6106ccbfe8a6d9b2)"}
+!27 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git f39aae11dca3f8f8c2c755a871726ed2fa82fd57)"}
!28 = distinct !DISubprogram(name: "prog1", scope: !3, file: !3, line: 6, type: !29, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!29 = !DISubroutineType(types: !30)
!30 = !{null}