1 //===------------ BPFCheckAndAdjustIR.cpp - Check and Adjust IR -----------===// 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 // Check IR and adjust IR for verifier friendly codes. 10 // The following are done for IR checking: 11 // - no relocation globals in PHI node. 12 // The following are done for IR adjustment: 13 // - remove __builtin_bpf_passthrough builtins. Target independent IR 14 // optimizations are done and those builtins can be removed. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #include "BPF.h" 19 #include "BPFCORE.h" 20 #include "BPFTargetMachine.h" 21 #include "llvm/IR/DebugInfoMetadata.h" 22 #include "llvm/IR/GlobalVariable.h" 23 #include "llvm/IR/Instruction.h" 24 #include "llvm/IR/Instructions.h" 25 #include "llvm/IR/Module.h" 26 #include "llvm/IR/Type.h" 27 #include "llvm/IR/User.h" 28 #include "llvm/IR/Value.h" 29 #include "llvm/Pass.h" 30 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 31 32 #define DEBUG_TYPE "bpf-check-and-opt-ir" 33 34 using namespace llvm; 35 36 namespace { 37 38 class BPFCheckAndAdjustIR final : public ModulePass { 39 bool runOnModule(Module &F) override; 40 41 public: 42 static char ID; 43 BPFCheckAndAdjustIR() : ModulePass(ID) {} 44 45 private: 46 void checkIR(Module &M); 47 bool adjustIR(Module &M); 48 bool removePassThroughBuiltin(Module &M); 49 }; 50 } // End anonymous namespace 51 52 char BPFCheckAndAdjustIR::ID = 0; 53 INITIALIZE_PASS(BPFCheckAndAdjustIR, DEBUG_TYPE, "BPF Check And Adjust IR", 54 false, false) 55 56 ModulePass *llvm::createBPFCheckAndAdjustIR() { 57 return new BPFCheckAndAdjustIR(); 58 } 59 60 void BPFCheckAndAdjustIR::checkIR(Module &M) { 61 // Ensure relocation global won't appear in PHI node 62 // This may happen if the compiler generated the following code: 63 // B1: 64 // g1 = @llvm.skb_buff:0:1... 65 // ... 66 // goto B_COMMON 67 // B2: 68 // g2 = @llvm.skb_buff:0:2... 69 // ... 70 // goto B_COMMON 71 // B_COMMON: 72 // g = PHI(g1, g2) 73 // x = load g 74 // ... 75 // If anything likes the above "g = PHI(g1, g2)", issue a fatal error. 76 for (Function &F : M) 77 for (auto &BB : F) 78 for (auto &I : BB) { 79 PHINode *PN = dyn_cast<PHINode>(&I); 80 if (!PN || PN->use_empty()) 81 continue; 82 for (int i = 0, e = PN->getNumIncomingValues(); i < e; ++i) { 83 auto *GV = dyn_cast<GlobalVariable>(PN->getIncomingValue(i)); 84 if (!GV) 85 continue; 86 if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) || 87 GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) 88 report_fatal_error("relocation global in PHI node"); 89 } 90 } 91 } 92 93 bool BPFCheckAndAdjustIR::removePassThroughBuiltin(Module &M) { 94 // Remove __builtin_bpf_passthrough()'s which are used to prevent 95 // certain IR optimizations. Now major IR optimizations are done, 96 // remove them. 97 bool Changed = false; 98 CallInst *ToBeDeleted = nullptr; 99 for (Function &F : M) 100 for (auto &BB : F) 101 for (auto &I : BB) { 102 if (ToBeDeleted) { 103 ToBeDeleted->eraseFromParent(); 104 ToBeDeleted = nullptr; 105 } 106 107 auto *Call = dyn_cast<CallInst>(&I); 108 if (!Call) 109 continue; 110 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 111 if (!GV) 112 continue; 113 if (!GV->getName().startswith("llvm.bpf.passthrough")) 114 continue; 115 Changed = true; 116 Value *Arg = Call->getArgOperand(1); 117 Call->replaceAllUsesWith(Arg); 118 ToBeDeleted = Call; 119 } 120 return Changed; 121 } 122 123 bool BPFCheckAndAdjustIR::adjustIR(Module &M) { 124 return removePassThroughBuiltin(M); 125 } 126 127 bool BPFCheckAndAdjustIR::runOnModule(Module &M) { 128 checkIR(M); 129 return adjustIR(M); 130 } 131