diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -10992,68 +10992,7 @@ {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(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"); @@ -11068,10 +11007,14 @@ 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; } diff --git a/clang/test/CodeGen/builtin-bpf-btf-type-id.c b/clang/test/CodeGen/builtin-bpf-btf-type-id.c --- a/clang/test/CodeGen/builtin-bpf-btf-type-id.c +++ b/clang/test/CodeGen/builtin-bpf-btf-type-id.c @@ -4,10 +4,22 @@ 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" diff --git a/llvm/include/llvm/IR/IntrinsicsBPF.td b/llvm/include/llvm/IR/IntrinsicsBPF.td --- a/llvm/include/llvm/IR/IntrinsicsBPF.td +++ b/llvm/include/llvm/IR/IntrinsicsBPF.td @@ -24,7 +24,7 @@ Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i64_ty], [IntrNoMem, ImmArg>]>; def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">, - Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty], + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], [IntrNoMem]>; def int_bpf_preserve_type_info : GCCBuiltin<"__builtin_bpf_preserve_type_info">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], diff --git a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp --- a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp +++ b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp @@ -95,18 +95,24 @@ std::string BaseName = "llvm.btf_type_id."; int Count = 0; for (auto Call : PreserveDITypeCalls) { - const ConstantInt *Flag = dyn_cast(Call->getArgOperand(2)); + const ConstantInt *Flag = dyn_cast(Call->getArgOperand(1)); assert(Flag); uint64_t FlagValue = Flag->getValue().getZExtValue(); if (FlagValue >= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG) report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic"); + MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); + uint32_t Reloc; - if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) + if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) { Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL; - else + } else { Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE; + DIType *Ty = cast(MD); + if (Ty->getName().empty()) + report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc"); + } BasicBlock *BB = Call->getParent(); IntegerType *VarType = Type::getInt32Ty(BB->getContext()); @@ -116,7 +122,6 @@ new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage, NULL, GVName); GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); - MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); // Load the global variable which represents the type info. diff --git a/llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll b/llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll --- a/llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll +++ b/llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll @@ -13,7 +13,7 @@ ; 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)); @@ -21,25 +21,23 @@ ; 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 } @@ -47,56 +45,55 @@ ; 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 } @@ -106,7 +103,7 @@ !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} @@ -131,7 +128,7 @@ !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}