brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · abe081c Raw
257 lines · cpp
1//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to the BPF assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "BPFAsmPrinter.h"15#include "BPF.h"16#include "BPFInstrInfo.h"17#include "BPFMCInstLower.h"18#include "BTFDebug.h"19#include "MCTargetDesc/BPFInstPrinter.h"20#include "TargetInfo/BPFTargetInfo.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/CodeGen/AsmPrinter.h"23#include "llvm/CodeGen/MachineConstantPool.h"24#include "llvm/CodeGen/MachineInstr.h"25#include "llvm/CodeGen/MachineJumpTableInfo.h"26#include "llvm/CodeGen/MachineModuleInfo.h"27#include "llvm/CodeGen/TargetLowering.h"28#include "llvm/IR/Module.h"29#include "llvm/MC/MCAsmInfo.h"30#include "llvm/MC/MCExpr.h"31#include "llvm/MC/MCInst.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/MCSymbol.h"34#include "llvm/MC/MCSymbolELF.h"35#include "llvm/MC/TargetRegistry.h"36#include "llvm/Support/Compiler.h"37#include "llvm/Support/raw_ostream.h"38#include "llvm/Target/TargetLoweringObjectFile.h"39using namespace llvm;40 41#define DEBUG_TYPE "asm-printer"42 43bool BPFAsmPrinter::doInitialization(Module &M) {44  AsmPrinter::doInitialization(M);45 46  // Only emit BTF when debuginfo available.47  if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {48    BTF = new BTFDebug(this);49    Handlers.push_back(std::unique_ptr<BTFDebug>(BTF));50  }51 52  return false;53}54 55const BPFTargetMachine &BPFAsmPrinter::getBTM() const {56  return static_cast<const BPFTargetMachine &>(TM);57}58 59bool BPFAsmPrinter::doFinalization(Module &M) {60  // Remove unused globals which are previously used for jump table.61  const BPFSubtarget *Subtarget = getBTM().getSubtargetImpl();62  if (Subtarget->hasGotox()) {63    std::vector<GlobalVariable *> Targets;64    for (GlobalVariable &Global : M.globals()) {65      if (Global.getLinkage() != GlobalValue::PrivateLinkage)66        continue;67      if (!Global.isConstant() || !Global.hasInitializer())68        continue;69 70      Constant *CV = dyn_cast<Constant>(Global.getInitializer());71      if (!CV)72        continue;73      ConstantArray *CA = dyn_cast<ConstantArray>(CV);74      if (!CA)75        continue;76 77      for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {78        if (!dyn_cast<BlockAddress>(CA->getOperand(i)))79          continue;80      }81      Targets.push_back(&Global);82    }83 84    for (GlobalVariable *GV : Targets) {85      GV->replaceAllUsesWith(PoisonValue::get(GV->getType()));86      GV->dropAllReferences();87      GV->eraseFromParent();88    }89  }90 91  for (GlobalObject &GO : M.global_objects()) {92    if (!GO.hasExternalWeakLinkage())93      continue;94 95    if (!SawTrapCall && GO.getName() == BPF_TRAP) {96      GO.eraseFromParent();97      break;98    }99  }100 101  return AsmPrinter::doFinalization(M);102}103 104void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,105                                 raw_ostream &O) {106  const MachineOperand &MO = MI->getOperand(OpNum);107 108  switch (MO.getType()) {109  case MachineOperand::MO_Register:110    O << BPFInstPrinter::getRegisterName(MO.getReg());111    break;112 113  case MachineOperand::MO_Immediate:114    O << MO.getImm();115    break;116 117  case MachineOperand::MO_MachineBasicBlock:118    O << *MO.getMBB()->getSymbol();119    break;120 121  case MachineOperand::MO_GlobalAddress:122    O << *getSymbol(MO.getGlobal());123    break;124 125  case MachineOperand::MO_BlockAddress: {126    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());127    O << BA->getName();128    break;129  }130 131  case MachineOperand::MO_ExternalSymbol:132    O << *GetExternalSymbolSymbol(MO.getSymbolName());133    break;134 135  case MachineOperand::MO_JumpTableIndex:136  case MachineOperand::MO_ConstantPoolIndex:137  default:138    llvm_unreachable("<unknown operand type>");139  }140}141 142bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,143                                    const char *ExtraCode, raw_ostream &O) {144  if (ExtraCode && ExtraCode[0])145    return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);146 147  printOperand(MI, OpNo, O);148  return false;149}150 151bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,152                                          unsigned OpNum, const char *ExtraCode,153                                          raw_ostream &O) {154  assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");155  const MachineOperand &BaseMO = MI->getOperand(OpNum);156  const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);157  assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");158  assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");159  int Offset = OffsetMO.getImm();160 161  if (ExtraCode)162    return true; // Unknown modifier.163 164  if (Offset < 0)165    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";166  else167    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";168 169  return false;170}171 172void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) {173  if (MI->isCall()) {174    for (const MachineOperand &Op : MI->operands()) {175      if (Op.isGlobal()) {176        if (const GlobalValue *GV = Op.getGlobal())177          if (GV->getName() == BPF_TRAP)178            SawTrapCall = true;179      }180    }181  }182 183  BPF_MC::verifyInstructionPredicates(MI->getOpcode(),184                                      getSubtargetInfo().getFeatureBits());185 186  MCInst TmpInst;187 188  if (!BTF || !BTF->InstLower(MI, TmpInst)) {189    BPFMCInstLower MCInstLowering(OutContext, *this);190    MCInstLowering.Lower(MI, TmpInst);191  }192  EmitToStreamer(*OutStreamer, TmpInst);193}194 195MCSymbol *BPFAsmPrinter::getJTPublicSymbol(unsigned JTI) {196  SmallString<60> Name;197  raw_svector_ostream(Name)198      << "BPF.JT." << MF->getFunctionNumber() << '.' << JTI;199  MCSymbol *S = OutContext.getOrCreateSymbol(Name);200  if (auto *ES = static_cast<MCSymbolELF *>(S)) {201    ES->setBinding(ELF::STB_GLOBAL);202    ES->setType(ELF::STT_OBJECT);203  }204  return S;205}206 207void BPFAsmPrinter::emitJumpTableInfo() {208  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();209  if (!MJTI)210    return;211 212  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();213  if (JT.empty())214    return;215 216  const TargetLoweringObjectFile &TLOF = getObjFileLowering();217  const Function &F = MF->getFunction();218 219  MCSection *Sec = OutStreamer->getCurrentSectionOnly();220  MCSymbol *SecStart = Sec->getBeginSymbol();221 222  MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);223  assert(MJTI->getEntryKind() == MachineJumpTableInfo::EK_BlockAddress);224  unsigned EntrySize = MJTI->getEntrySize(getDataLayout());225  OutStreamer->switchSection(JTS);226  for (unsigned JTI = 0; JTI < JT.size(); JTI++) {227    ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;228    if (JTBBs.empty())229      continue;230 231    MCSymbol *JTStart = getJTPublicSymbol(JTI);232    OutStreamer->emitLabel(JTStart);233    for (const MachineBasicBlock *MBB : JTBBs) {234      const MCExpr *Diff = MCBinaryExpr::createSub(235          MCSymbolRefExpr::create(MBB->getSymbol(), OutContext),236          MCSymbolRefExpr::create(SecStart, OutContext), OutContext);237      OutStreamer->emitValue(Diff, EntrySize);238    }239    const MCExpr *JTSize =240        MCConstantExpr::create(JTBBs.size() * EntrySize, OutContext);241    OutStreamer->emitELFSize(JTStart, JTSize);242  }243}244 245char BPFAsmPrinter::ID = 0;246 247INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,248                false)249 250// Force static initialization.251extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void252LLVMInitializeBPFAsmPrinter() {253  RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());254  RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());255  RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());256}257