Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / BPF / BPFPreserveDIType.cpp
blob78e1bf90f1bd5243693606062de6b7a53994e3c6
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.
11 //===----------------------------------------------------------------------===//
13 #include "BPF.h"
14 #include "BPFCORE.h"
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"
31 namespace llvm {
32 constexpr StringRef BPFCoreSharedInfo::TypeIdAttr;
33 } // namespace llvm
35 using namespace llvm;
37 namespace {
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())
46 return false;
48 std::vector<CallInst *> PreserveDITypeCalls;
50 for (auto &BB : F) {
51 for (auto &I : BB) {
52 auto *Call = dyn_cast<CallInst>(&I);
53 if (!Call)
54 continue;
56 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
57 if (!GV)
58 continue;
60 if (GV->getName().startswith("llvm.bpf.btf.type.id")) {
61 if (!Call->getMetadata(LLVMContext::MD_preserve_access_index))
62 report_fatal_error(
63 "Missing metadata for llvm.bpf.btf.type.id intrinsic");
64 PreserveDITypeCalls.push_back(Call);
69 if (PreserveDITypeCalls.empty())
70 return false;
72 std::string BaseName = "llvm.btf_type_id.";
73 static int Count = 0;
74 for (auto *Call : PreserveDITypeCalls) {
75 const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(1));
76 assert(Flag);
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);
84 uint32_t Reloc;
85 if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) {
86 Reloc = BTF::BTF_TYPE_ID_LOCAL;
87 } else {
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)
94 break;
95 Ty = DTy->getBaseType();
98 if (Ty->getName().empty()) {
99 if (isa<DISubroutineType>(Ty))
100 report_fatal_error(
101 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc");
102 else
103 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc");
105 MD = Ty;
108 BasicBlock *BB = Call->getParent();
109 IntegerType *VarType = Type::getInt64Ty(BB->getContext());
110 std::string GVName =
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.
118 auto *LDInst =
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();
124 Count++;
127 return true;
129 } // End anonymous namespace
131 PreservedAnalyses BPFPreserveDITypePass::run(Function &F,
132 FunctionAnalysisManager &AM) {
133 return BPFPreserveDITypeImpl(F) ? PreservedAnalyses::none()
134 : PreservedAnalyses::all();