LLVM 17.0.0git
BPFPreserveDIType.cpp
Go to the documentation of this file.
1//===----------- BPFPreserveDIType.cpp - Preserve DebugInfo Types ---------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Preserve Debuginfo types encoded in __builtin_btf_type_id() metadata.
10//
11//===----------------------------------------------------------------------===//
12
13#include "BPF.h"
14#include "BPFCORE.h"
18#include "llvm/IR/Instruction.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IR/PassManager.h"
22#include "llvm/IR/Type.h"
23#include "llvm/IR/User.h"
24#include "llvm/IR/Value.h"
25#include "llvm/Pass.h"
27
28#define DEBUG_TYPE "bpf-preserve-di-type"
29
30namespace llvm {
32} // namespace llvm
33
34using namespace llvm;
35
36namespace {
37
38static bool BPFPreserveDITypeImpl(Function &F) {
39 LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n");
40
41 Module *M = F.getParent();
42
43 // Bail out if no debug info.
44 if (M->debug_compile_units().empty())
45 return false;
46
47 std::vector<CallInst *> PreserveDITypeCalls;
48
49 for (auto &BB : F) {
50 for (auto &I : BB) {
51 auto *Call = dyn_cast<CallInst>(&I);
52 if (!Call)
53 continue;
54
55 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
56 if (!GV)
57 continue;
58
59 if (GV->getName().startswith("llvm.bpf.btf.type.id")) {
60 if (!Call->getMetadata(LLVMContext::MD_preserve_access_index))
62 "Missing metadata for llvm.bpf.btf.type.id intrinsic");
63 PreserveDITypeCalls.push_back(Call);
64 }
65 }
66 }
67
68 if (PreserveDITypeCalls.empty())
69 return false;
70
71 std::string BaseName = "llvm.btf_type_id.";
72 static int Count = 0;
73 for (auto *Call : PreserveDITypeCalls) {
74 const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(1));
75 assert(Flag);
76 uint64_t FlagValue = Flag->getValue().getZExtValue();
77
79 report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic");
80
81 MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index);
82
83 uint32_t Reloc;
86 } else {
88 DIType *Ty = cast<DIType>(MD);
89 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
90 unsigned Tag = DTy->getTag();
91 if (Tag != dwarf::DW_TAG_const_type &&
92 Tag != dwarf::DW_TAG_volatile_type)
93 break;
94 Ty = DTy->getBaseType();
95 }
96
97 if (Ty->getName().empty()) {
98 if (isa<DISubroutineType>(Ty))
100 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc");
101 else
102 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc");
103 }
104 MD = Ty;
105 }
106
107 BasicBlock *BB = Call->getParent();
108 IntegerType *VarType = Type::getInt64Ty(BB->getContext());
109 std::string GVName =
110 BaseName + std::to_string(Count) + "$" + std::to_string(Reloc);
112 *M, VarType, false, GlobalVariable::ExternalLinkage, nullptr, GVName);
114 GV->setMetadata(LLVMContext::MD_preserve_access_index, MD);
115
116 // Load the global variable which represents the type info.
117 auto *LDInst =
118 new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call);
119 Instruction *PassThroughInst =
120 BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call);
121 Call->replaceAllUsesWith(PassThroughInst);
122 Call->eraseFromParent();
123 Count++;
124 }
125
126 return true;
127}
128
129class BPFPreserveDIType final : public FunctionPass {
130 bool runOnFunction(Function &F) override;
131
132public:
133 static char ID;
134 BPFPreserveDIType() : FunctionPass(ID) {}
135};
136} // End anonymous namespace
137
138char BPFPreserveDIType::ID = 0;
139INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "BPF Preserve Debuginfo Type",
140 false, false)
141
143 return new BPFPreserveDIType();
144}
145
146bool BPFPreserveDIType::runOnFunction(Function &F) {
147 return BPFPreserveDITypeImpl(F);
148}
149
152 return BPFPreserveDITypeImpl(F) ? PreservedAnalyses::none()
154}
#define DEBUG_TYPE
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file contains constants used for implementing Dwarf debug support.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
Definition: BPFCORE.h:65
static Instruction * insertPassThrough(Module *M, BasicBlock *BB, Instruction *Input, Instruction *Before)
Insert a bpf passthrough builtin function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:35
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
Base class for types.
StringRef getName() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
Definition: Metadata.cpp:1325
void addAttribute(Attribute::AttrKind Kind)
Add attribute to this global.
Class to represent integer types.
Definition: DerivedTypes.h:40
An instruction for reading from memory.
Definition: Instructions.h:177
Metadata node.
Definition: Metadata.h:943
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
static IntegerType * getInt64Ty(LLVMContext &C)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
FunctionPass * createBPFPreserveDIType()