1//===-- BPFTargetMachine.cpp - Define TargetMachine for BPF ---------------===//
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// Implements the info about BPF target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "BPFTargetMachine.h"
14#include "BPF.h"
15#include "BPFTargetLoweringObjectFile.h"
16#include "BPFTargetTransformInfo.h"
17#include "MCTargetDesc/BPFMCAsmInfo.h"
18#include "TargetInfo/BPFTargetInfo.h"
19#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
20#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
21#include "llvm/CodeGen/GlobalISel/Legalizer.h"
22#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
23#include "llvm/CodeGen/Passes.h"
24#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
25#include "llvm/CodeGen/TargetPassConfig.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/InitializePasses.h"
28#include "llvm/MC/TargetRegistry.h"
29#include "llvm/Passes/PassBuilder.h"
30#include "llvm/Support/Compiler.h"
31#include "llvm/Target/TargetOptions.h"
32#include "llvm/Transforms/Scalar.h"
33#include "llvm/Transforms/Scalar/SimplifyCFG.h"
34#include "llvm/Transforms/Utils/SimplifyCFGOptions.h"
35#include <optional>
36using namespace llvm;
37
38static cl::
39opt<bool> DisableMIPeephole("disable-bpf-peephole", cl::Hidden,
40 cl::desc("Disable machine peepholes for BPF"));
41
42static cl::opt<bool>
43 DisableCheckUnreachable("bpf-disable-trap-unreachable", cl::Hidden,
44 cl::desc("Disable Trap Unreachable for BPF"));
45
46extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() {
47 // Register the target.
48 RegisterTargetMachine<BPFTargetMachine> X(getTheBPFleTarget());
49 RegisterTargetMachine<BPFTargetMachine> Y(getTheBPFbeTarget());
50 RegisterTargetMachine<BPFTargetMachine> Z(getTheBPFTarget());
51
52 PassRegistry &PR = *PassRegistry::getPassRegistry();
53 initializeGlobalISel(PR);
54 initializeBPFAsmPrinterPass(PR);
55 initializeBPFCheckAndAdjustIRPass(PR);
56 initializeBPFMIPeepholePass(PR);
57 initializeBPFMIPreEmitPeepholePass(PR);
58 initializeBPFDAGToDAGISelLegacyPass(PR);
59 initializeBPFMISimplifyPatchablePass(PR);
60 initializeBPFMIPreEmitCheckingPass(PR);
61}
62
63static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
64 return RM.value_or(u: Reloc::PIC_);
65}
66
67BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT,
68 StringRef CPU, StringRef FS,
69 const TargetOptions &Options,
70 std::optional<Reloc::Model> RM,
71 std::optional<CodeModel::Model> CM,
72 CodeGenOptLevel OL, bool JIT)
73 : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
74 getEffectiveRelocModel(RM),
75 getEffectiveCodeModel(CM, Default: CodeModel::Small), OL),
76 TLOF(std::make_unique<BPFTargetLoweringObjectFileELF>()),
77 Subtarget(TT, std::string(CPU), std::string(FS), *this) {
78 if (!DisableCheckUnreachable) {
79 this->Options.TrapUnreachable = true;
80 this->Options.NoTrapAfterNoreturn = true;
81 }
82
83 initAsmInfo();
84
85 BPFMCAsmInfo *MAI =
86 static_cast<BPFMCAsmInfo *>(const_cast<MCAsmInfo *>(AsmInfo.get()));
87 MAI->setDwarfUsesRelocationsAcrossSections(!Subtarget.getUseDwarfRIS());
88}
89
90namespace {
91// BPF Code Generator Pass Configuration Options.
92class BPFPassConfig : public TargetPassConfig {
93public:
94 BPFPassConfig(BPFTargetMachine &TM, PassManagerBase &PM)
95 : TargetPassConfig(TM, PM) {}
96
97 BPFTargetMachine &getBPFTargetMachine() const {
98 return getTM<BPFTargetMachine>();
99 }
100
101 void addIRPasses() override;
102 bool addInstSelector() override;
103 void addMachineSSAOptimization() override;
104 void addPreEmitPass() override;
105
106 bool addIRTranslator() override;
107 bool addLegalizeMachineIR() override;
108 bool addRegBankSelect() override;
109 bool addGlobalInstructionSelect() override;
110};
111}
112
113TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) {
114 return new BPFPassConfig(*this, PM);
115}
116
117static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) {
118 return PassBuilder::parseSinglePassOption(Params, OptionName: "allow-partial",
119 PassName: "BPFPreserveStaticOffsetPass");
120}
121
122void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
123#define GET_PASS_REGISTRY "BPFPassRegistry.def"
124#include "llvm/Passes/TargetPassRegistry.inc"
125
126 PB.registerPipelineStartEPCallback(
127 C: [=](ModulePassManager &MPM, OptimizationLevel) {
128 FunctionPassManager FPM;
129 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(true));
130 FPM.addPass(Pass: BPFAbstractMemberAccessPass(this));
131 FPM.addPass(Pass: BPFPreserveDITypePass());
132 FPM.addPass(Pass: BPFIRPeepholePass());
133 MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM)));
134 });
135 PB.registerPeepholeEPCallback(C: [=](FunctionPassManager &FPM,
136 OptimizationLevel Level) {
137 FPM.addPass(Pass: SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(B: true)));
138 FPM.addPass(Pass: BPFASpaceCastSimplifyPass());
139 });
140 PB.registerScalarOptimizerLateEPCallback(
141 C: [=](FunctionPassManager &FPM, OptimizationLevel Level) {
142 // Run this after loop unrolling but before
143 // SimplifyCFGPass(... .sinkCommonInsts(true))
144 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(false));
145 });
146 PB.registerPipelineEarlySimplificationEPCallback(
147 C: [=](ModulePassManager &MPM, OptimizationLevel, ThinOrFullLTOPhase) {
148 MPM.addPass(Pass: BPFAdjustOptPass());
149 });
150}
151
152void BPFPassConfig::addIRPasses() {
153 addPass(P: createAtomicExpandLegacyPass());
154 addPass(P: createBPFCheckAndAdjustIR());
155
156 TargetPassConfig::addIRPasses();
157}
158
159TargetTransformInfo
160BPFTargetMachine::getTargetTransformInfo(const Function &F) const {
161 return TargetTransformInfo(std::make_unique<BPFTTIImpl>(args: this, args: F));
162}
163
164// Install an instruction selector pass using
165// the ISelDag to gen BPF code.
166bool BPFPassConfig::addInstSelector() {
167 addPass(P: createBPFISelDag(TM&: getBPFTargetMachine()));
168
169 return false;
170}
171
172void BPFPassConfig::addMachineSSAOptimization() {
173 addPass(P: createBPFMISimplifyPatchablePass());
174
175 // The default implementation must be called first as we want eBPF
176 // Peephole ran at last.
177 TargetPassConfig::addMachineSSAOptimization();
178
179 const BPFSubtarget *Subtarget = getBPFTargetMachine().getSubtargetImpl();
180 if (!DisableMIPeephole) {
181 if (Subtarget->getHasAlu32())
182 addPass(P: createBPFMIPeepholePass());
183 }
184}
185
186void BPFPassConfig::addPreEmitPass() {
187 addPass(P: createBPFMIPreEmitCheckingPass());
188 if (getOptLevel() != CodeGenOptLevel::None)
189 if (!DisableMIPeephole)
190 addPass(P: createBPFMIPreEmitPeepholePass());
191}
192
193bool BPFPassConfig::addIRTranslator() {
194 addPass(P: new IRTranslator());
195 return false;
196}
197
198bool BPFPassConfig::addLegalizeMachineIR() {
199 addPass(P: new Legalizer());
200 return false;
201}
202
203bool BPFPassConfig::addRegBankSelect() {
204 addPass(P: new RegBankSelect());
205 return false;
206}
207
208bool BPFPassConfig::addGlobalInstructionSelect() {
209 addPass(P: new InstructionSelect(getOptLevel()));
210 return false;
211}
212