1//===----------------------------------------------------------------------===//
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#include "BPF.h"
10#include "BPFAsmPrinter.h"
11#include "BPFSubtarget.h"
12#include "BPFTargetMachine.h"
13#include "llvm/CodeGen/AtomicExpand.h"
14#include "llvm/IR/PassInstrumentation.h"
15#include "llvm/MC/MCStreamer.h"
16#include "llvm/Passes/CodeGenPassBuilder.h"
17#include "llvm/Passes/PassBuilder.h"
18#include "llvm/Support/Error.h"
19#include "llvm/Target/CGPassBuilderOption.h"
20#include "llvm/Transforms/Scalar/SimplifyCFG.h"
21#include "llvm/Transforms/Utils/SimplifyCFGOptions.h"
22
23using namespace llvm;
24
25extern cl::opt<bool> DisableMIPeephole;
26
27namespace {
28
29class BPFCodeGenPassBuilder
30 : public CodeGenPassBuilder<BPFCodeGenPassBuilder, BPFTargetMachine> {
31 using Base = CodeGenPassBuilder<BPFCodeGenPassBuilder, BPFTargetMachine>;
32
33public:
34 explicit BPFCodeGenPassBuilder(BPFTargetMachine &TM,
35 const CGPassBuilderOption &Opts,
36 PassInstrumentationCallbacks *PIC)
37 : CodeGenPassBuilder(TM, Opts, PIC) {}
38
39 void addIRPasses(PassManagerWrapper &PMW) const;
40 Error addInstSelector(PassManagerWrapper &PMW) const;
41 void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
42 void addPreEmitPass(PassManagerWrapper &PMW) const;
43 void addAsmPrinterBegin(PassManagerWrapper &PMW) const;
44 void addAsmPrinter(PassManagerWrapper &PMW) const;
45 void addAsmPrinterEnd(PassManagerWrapper &PMW) const;
46};
47
48void BPFCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
49 addFunctionPass(Pass: AtomicExpandPass(TM), PMW);
50 flushFPMsToMPM(PMW);
51 addModulePass(Pass: BPFCheckAndAdjustIRPass(), PMW);
52
53 Base::addIRPasses(PMW);
54}
55
56Error BPFCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
57 addMachineFunctionPass(Pass: BPFISelDAGToDAGPass(TM), PMW);
58 return Error::success();
59}
60
61void BPFCodeGenPassBuilder::addMachineSSAOptimization(
62 PassManagerWrapper &PMW) const {
63 addMachineFunctionPass(Pass: BPFMISimplifyPatchablePass(), PMW);
64
65 Base::addMachineSSAOptimization(PMW);
66
67 const BPFSubtarget *Subtarget = TM.getSubtargetImpl();
68 if (!DisableMIPeephole) {
69 if (Subtarget->getHasAlu32())
70 addMachineFunctionPass(Pass: BPFMIPeepholePass(), PMW);
71 }
72}
73
74void BPFCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) const {
75 addMachineFunctionPass(Pass: BPFMIPreEmitCheckingPass(), PMW);
76 if (!DisableMIPeephole) {
77 addMachineFunctionPass(Pass: BPFMIExpandStackArgPseudosPass(), PMW);
78 addMachineFunctionPass(Pass: BPFMIPreEmitPeepholePass(), PMW);
79 }
80}
81
82void BPFCodeGenPassBuilder::addAsmPrinterBegin(PassManagerWrapper &PMW) const {
83 addModulePass(Pass: BPFAsmPrinterBeginPass(), PMW, /*Force=*/true);
84}
85
86void BPFCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) const {
87 addMachineFunctionPass(Pass: BPFAsmPrinterPass(), PMW);
88}
89
90void BPFCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) const {
91 addModulePass(Pass: BPFAsmPrinterEndPass(), PMW);
92}
93
94} // namespace
95
96static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) {
97 return PassBuilder::parseSinglePassOption(Params, OptionName: "allow-partial",
98 PassName: "BPFPreserveStaticOffsetPass");
99}
100
101void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
102#define GET_PASS_REGISTRY "BPFPassRegistry.def"
103#include "llvm/Passes/TargetPassRegistry.inc"
104 // TODO(boomanaiden154): Move this into the base CodeGenPassBuilder once all
105 // targets that currently implement it have a ported asm-printer pass.
106 if (PIC) {
107 PIC->addClassToPassName(ClassName: BPFAsmPrinterBeginPass::name(),
108 PassName: "bpf-asm-printer-begin");
109 PIC->addClassToPassName(ClassName: BPFAsmPrinterPass::name(), PassName: "bpf-asmprinter");
110 PIC->addClassToPassName(ClassName: BPFAsmPrinterEndPass::name(),
111 PassName: "bpf-asm-printer-end");
112 }
113
114 PB.registerPipelineStartEPCallback(
115 C: [=](ModulePassManager &MPM, OptimizationLevel) {
116 FunctionPassManager FPM;
117 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(true));
118 FPM.addPass(Pass: BPFAbstractMemberAccessPass(this));
119 FPM.addPass(Pass: BPFPreserveDITypePass());
120 FPM.addPass(Pass: BPFIRPeepholePass());
121 MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM)));
122 });
123 PB.registerPeepholeEPCallback(C: [=](FunctionPassManager &FPM,
124 OptimizationLevel Level) {
125 FPM.addPass(Pass: SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(B: true)));
126 FPM.addPass(Pass: BPFASpaceCastSimplifyPass());
127 });
128 PB.registerScalarOptimizerLateEPCallback(
129 C: [=](FunctionPassManager &FPM, OptimizationLevel Level) {
130 // Run this after loop unrolling but before
131 // SimplifyCFGPass(... .sinkCommonInsts(true))
132 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(false));
133 });
134 PB.registerPipelineEarlySimplificationEPCallback(
135 C: [=](ModulePassManager &MPM, OptimizationLevel, ThinOrFullLTOPhase) {
136 MPM.addPass(Pass: BPFAdjustOptPass());
137 });
138}
139
140Error BPFTargetMachine::buildCodeGenPipeline(
141 ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
142 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
143 const CGPassBuilderOption &Opt, MCContext &Ctx,
144 PassInstrumentationCallbacks *PIC) {
145 auto CGPB = BPFCodeGenPassBuilder(*this, Opt, PIC);
146 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
147}
148