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/IR/DebugInfoMetadata.h"
16 #include "llvm/IR/GlobalVariable.h"
17 #include "llvm/IR/Instruction.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/IR/Type.h"
22 #include "llvm/IR/User.h"
23 #include "llvm/IR/Value.h"
24 #include "llvm/Pass.h"
25 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
27 #define DEBUG_TYPE "bpf-preserve-di-type"
30 constexpr StringRef
BPFCoreSharedInfo::TypeIdAttr
;
37 static bool BPFPreserveDITypeImpl(Function
&F
) {
38 LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n");
40 Module
*M
= F
.getParent();
42 // Bail out if no debug info.
43 if (M
->debug_compile_units().empty())
46 std::vector
<CallInst
*> PreserveDITypeCalls
;
50 auto *Call
= dyn_cast
<CallInst
>(&I
);
54 const auto *GV
= dyn_cast
<GlobalValue
>(Call
->getCalledOperand());
58 if (GV
->getName().startswith("llvm.bpf.btf.type.id")) {
59 if (!Call
->getMetadata(LLVMContext::MD_preserve_access_index
))
61 "Missing metadata for llvm.bpf.btf.type.id intrinsic");
62 PreserveDITypeCalls
.push_back(Call
);
67 if (PreserveDITypeCalls
.empty())
70 std::string BaseName
= "llvm.btf_type_id.";
72 for (auto Call
: PreserveDITypeCalls
) {
73 const ConstantInt
*Flag
= dyn_cast
<ConstantInt
>(Call
->getArgOperand(1));
75 uint64_t FlagValue
= Flag
->getValue().getZExtValue();
77 if (FlagValue
>= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG
)
78 report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic");
80 MDNode
*MD
= Call
->getMetadata(LLVMContext::MD_preserve_access_index
);
83 if (FlagValue
== BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC
) {
84 Reloc
= BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL
;
86 Reloc
= BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE
;
87 DIType
*Ty
= cast
<DIType
>(MD
);
88 while (auto *DTy
= dyn_cast
<DIDerivedType
>(Ty
)) {
89 unsigned Tag
= DTy
->getTag();
90 if (Tag
!= dwarf::DW_TAG_const_type
&&
91 Tag
!= dwarf::DW_TAG_volatile_type
)
93 Ty
= DTy
->getBaseType();
96 if (Ty
->getName().empty())
97 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc");
101 BasicBlock
*BB
= Call
->getParent();
102 IntegerType
*VarType
= Type::getInt64Ty(BB
->getContext());
103 std::string GVName
= BaseName
+ std::to_string(Count
) + "$" +
104 std::to_string(Reloc
);
105 GlobalVariable
*GV
= new GlobalVariable(
106 *M
, VarType
, false, GlobalVariable::ExternalLinkage
, NULL
, GVName
);
107 GV
->addAttribute(BPFCoreSharedInfo::TypeIdAttr
);
108 GV
->setMetadata(LLVMContext::MD_preserve_access_index
, MD
);
110 // Load the global variable which represents the type info.
112 new LoadInst(Type::getInt64Ty(BB
->getContext()), GV
, "", Call
);
113 Instruction
*PassThroughInst
=
114 BPFCoreSharedInfo::insertPassThrough(M
, BB
, LDInst
, Call
);
115 Call
->replaceAllUsesWith(PassThroughInst
);
116 Call
->eraseFromParent();
123 class BPFPreserveDIType final
: public FunctionPass
{
124 bool runOnFunction(Function
&F
) override
;
128 BPFPreserveDIType() : FunctionPass(ID
) {}
130 } // End anonymous namespace
132 char BPFPreserveDIType::ID
= 0;
133 INITIALIZE_PASS(BPFPreserveDIType
, DEBUG_TYPE
, "BPF Preserve Debuginfo Type",
136 FunctionPass
*llvm::createBPFPreserveDIType() {
137 return new BPFPreserveDIType();
140 bool BPFPreserveDIType::runOnFunction(Function
&F
) {
141 return BPFPreserveDITypeImpl(F
);
144 PreservedAnalyses
BPFPreserveDITypePass::run(Function
&F
,
145 FunctionAnalysisManager
&AM
) {
146 return BPFPreserveDITypeImpl(F
) ? PreservedAnalyses::none()
147 : PreservedAnalyses::all();