1 //===----------- BPFPreserveDIType.cpp - Preserve DebugInfo Types ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Preserve Debuginfo types encoded in __builtin_btf_type_id() metadata.
11 //===----------------------------------------------------------------------===//
15 #include "llvm/BinaryFormat/Dwarf.h"
16 #include "llvm/DebugInfo/BTF/BTF.h"
17 #include "llvm/IR/DebugInfoMetadata.h"
18 #include "llvm/IR/GlobalVariable.h"
19 #include "llvm/IR/Instruction.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/PassManager.h"
23 #include "llvm/IR/Type.h"
24 #include "llvm/IR/User.h"
25 #include "llvm/IR/Value.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
29 #define DEBUG_TYPE "bpf-preserve-di-type"
32 constexpr StringRef
BPFCoreSharedInfo::TypeIdAttr
;
39 static bool BPFPreserveDITypeImpl(Function
&F
) {
40 LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n");
42 Module
*M
= F
.getParent();
44 // Bail out if no debug info.
45 if (M
->debug_compile_units().empty())
48 std::vector
<CallInst
*> PreserveDITypeCalls
;
52 auto *Call
= dyn_cast
<CallInst
>(&I
);
56 const auto *GV
= dyn_cast
<GlobalValue
>(Call
->getCalledOperand());
60 if (GV
->getName().starts_with("llvm.bpf.btf.type.id")) {
61 if (!Call
->getMetadata(LLVMContext::MD_preserve_access_index
))
63 "Missing metadata for llvm.bpf.btf.type.id intrinsic");
64 PreserveDITypeCalls
.push_back(Call
);
69 if (PreserveDITypeCalls
.empty())
72 std::string BaseName
= "llvm.btf_type_id.";
74 for (auto *Call
: PreserveDITypeCalls
) {
75 const ConstantInt
*Flag
= dyn_cast
<ConstantInt
>(Call
->getArgOperand(1));
77 uint64_t FlagValue
= Flag
->getValue().getZExtValue();
79 if (FlagValue
>= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG
)
80 report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic");
82 MDNode
*MD
= Call
->getMetadata(LLVMContext::MD_preserve_access_index
);
85 if (FlagValue
== BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC
) {
86 Reloc
= BTF::BTF_TYPE_ID_LOCAL
;
88 Reloc
= BTF::BTF_TYPE_ID_REMOTE
;
90 DIType
*Ty
= cast
<DIType
>(MD
);
91 while (auto *DTy
= dyn_cast
<DIDerivedType
>(Ty
)) {
92 unsigned Tag
= DTy
->getTag();
93 if (Tag
!= dwarf::DW_TAG_const_type
&& Tag
!= dwarf::DW_TAG_volatile_type
)
95 Ty
= DTy
->getBaseType();
98 if (Reloc
== BTF::BTF_TYPE_ID_REMOTE
) {
99 if (Ty
->getName().empty()) {
100 if (isa
<DISubroutineType
>(Ty
))
102 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc");
104 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc");
109 BasicBlock
*BB
= Call
->getParent();
110 IntegerType
*VarType
= Type::getInt64Ty(BB
->getContext());
112 BaseName
+ std::to_string(Count
) + "$" + std::to_string(Reloc
);
113 GlobalVariable
*GV
= new GlobalVariable(
114 *M
, VarType
, false, GlobalVariable::ExternalLinkage
, nullptr, GVName
);
115 GV
->addAttribute(BPFCoreSharedInfo::TypeIdAttr
);
116 GV
->setMetadata(LLVMContext::MD_preserve_access_index
, MD
);
118 // Load the global variable which represents the type info.
120 new LoadInst(Type::getInt64Ty(BB
->getContext()), GV
, "", Call
);
121 Instruction
*PassThroughInst
=
122 BPFCoreSharedInfo::insertPassThrough(M
, BB
, LDInst
, Call
);
123 Call
->replaceAllUsesWith(PassThroughInst
);
124 Call
->eraseFromParent();
130 } // End anonymous namespace
132 PreservedAnalyses
BPFPreserveDITypePass::run(Function
&F
,
133 FunctionAnalysisManager
&AM
) {
134 return BPFPreserveDITypeImpl(F
) ? PreservedAnalyses::none()
135 : PreservedAnalyses::all();