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().startswith("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
;
89 DIType
*Ty
= cast
<DIType
>(MD
);
90 while (auto *DTy
= dyn_cast
<DIDerivedType
>(Ty
)) {
91 unsigned Tag
= DTy
->getTag();
92 if (Tag
!= dwarf::DW_TAG_const_type
&&
93 Tag
!= dwarf::DW_TAG_volatile_type
)
95 Ty
= DTy
->getBaseType();
98 if (Ty
->getName().empty()) {
99 if (isa
<DISubroutineType
>(Ty
))
101 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc");
103 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc");
108 BasicBlock
*BB
= Call
->getParent();
109 IntegerType
*VarType
= Type::getInt64Ty(BB
->getContext());
111 BaseName
+ std::to_string(Count
) + "$" + std::to_string(Reloc
);
112 GlobalVariable
*GV
= new GlobalVariable(
113 *M
, VarType
, false, GlobalVariable::ExternalLinkage
, nullptr, GVName
);
114 GV
->addAttribute(BPFCoreSharedInfo::TypeIdAttr
);
115 GV
->setMetadata(LLVMContext::MD_preserve_access_index
, MD
);
117 // Load the global variable which represents the type info.
119 new LoadInst(Type::getInt64Ty(BB
->getContext()), GV
, "", Call
);
120 Instruction
*PassThroughInst
=
121 BPFCoreSharedInfo::insertPassThrough(M
, BB
, LDInst
, Call
);
122 Call
->replaceAllUsesWith(PassThroughInst
);
123 Call
->eraseFromParent();
129 } // End anonymous namespace
131 PreservedAnalyses
BPFPreserveDITypePass::run(Function
&F
,
132 FunctionAnalysisManager
&AM
) {
133 return BPFPreserveDITypeImpl(F
) ? PreservedAnalyses::none()
134 : PreservedAnalyses::all();