//===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This pass targets a subset of instructions like below // ld_imm64 r1, @global // ldd r2, r1, 0 // add r3, struct_base_reg, r2 // // Here @global should represent an AMA (abstruct member access). // Such an access is subject to bpf load time patching. After this pass, the // code becomes // ld_imm64 r1, @global // add r3, struct_base_reg, r1 // // Eventually, at BTF output stage, a relocation record will be generated // for ld_imm64 which should be replaced later by bpf loader: // r1 = <calculated field_info> // add r3, struct_base_reg, r1 // // This pass also removes the intermediate load generated in IR pass for // __builtin_btf_type_id() intrinsic. // //===----------------------------------------------------------------------===// #include "BPF.h" #include "BPFCORE.h" #include "BPFInstrInfo.h" #include "BPFTargetMachine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/Support/Debug.h" #include <set> usingnamespacellvm; #define DEBUG_TYPE … namespace { struct BPFMISimplifyPatchable : public MachineFunctionPass { … }; // Initialize class variables. void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) { … } static bool isST(unsigned Opcode) { … } static bool isSTX32(unsigned Opcode) { … } static bool isSTX64(unsigned Opcode) { … } static bool isLDX32(unsigned Opcode) { … } static bool isLDX64(unsigned Opcode) { … } static bool isLDSX(unsigned Opcode) { … } bool BPFMISimplifyPatchable::isLoadInst(unsigned Opcode) { … } void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp, const GlobalValue *GVal) { … } void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineOperand *RelocOp, const GlobalValue *GVal, unsigned Opcode) { … } void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, Register &DstReg, const GlobalValue *GVal, bool IsAma) { … } void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI, Register &DstReg, Register &SrcReg, const GlobalValue *GVal, bool doSrcRegProp, bool IsAma) { … } // Check to see whether we could do some optimization // to attach relocation to downstream dependent instructions. // Two kinds of patterns are recognized below: // Pattern 1: // %1 = LD_imm64 @"llvm.b:0:4$0:1" <== patch_imm = 4 // %2 = LDD %1, 0 <== this insn will be removed // %3 = ADD_rr %0, %2 // %4 = LDW[32] %3, 0 OR STW[32] %4, %3, 0 // The `%4 = ...` will be transformed to // CORE_[ALU32_]MEM(%4, mem_opcode, %0, @"llvm.b:0:4$0:1") // and later on, BTF emit phase will translate to // %4 = LDW[32] %0, 4 STW[32] %4, %0, 4 // and attach a relocation to it. // Pattern 2: // %15 = LD_imm64 @"llvm.t:5:63$0:2" <== relocation type 5 // %16 = LDD %15, 0 <== this insn will be removed // %17 = SRA_rr %14, %16 // The `%17 = ...` will be transformed to // %17 = CORE_SHIFT(SRA_ri, %14, @"llvm.t:5:63$0:2") // and later on, BTF emit phase will translate to // %r4 = SRA_ri %r4, 63 void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI, MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal) { … } /// Remove unneeded Load instructions. bool BPFMISimplifyPatchable::removeLD() { … } } // namespace INITIALIZE_PASS(…) char BPFMISimplifyPatchable::ID = …; FunctionPass *llvm::createBPFMISimplifyPatchablePass() { … }