brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 24e4fc3 Raw
250 lines · cpp
1//===-- LanaiAsmPrinter.cpp - Lanai 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 Lanai assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "LanaiAluCode.h"15#include "LanaiCondCode.h"16#include "LanaiMCInstLower.h"17#include "LanaiTargetMachine.h"18#include "MCTargetDesc/LanaiInstPrinter.h"19#include "TargetInfo/LanaiTargetInfo.h"20#include "llvm/CodeGen/AsmPrinter.h"21#include "llvm/CodeGen/MachineConstantPool.h"22#include "llvm/CodeGen/MachineInstr.h"23#include "llvm/IR/Mangler.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/MC/MCInst.h"26#include "llvm/MC/MCInstBuilder.h"27#include "llvm/MC/MCStreamer.h"28#include "llvm/MC/MCSymbol.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Support/raw_ostream.h"32 33#define DEBUG_TYPE "asm-printer"34 35using namespace llvm;36 37namespace {38class LanaiAsmPrinter : public AsmPrinter {39public:40  explicit LanaiAsmPrinter(TargetMachine &TM,41                           std::unique_ptr<MCStreamer> Streamer)42      : AsmPrinter(TM, std::move(Streamer), ID) {}43 44  StringRef getPassName() const override { return "Lanai Assembly Printer"; }45 46  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);47  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,48                       const char *ExtraCode, raw_ostream &O) override;49  void emitInstruction(const MachineInstr *MI) override;50  bool isBlockOnlyReachableByFallthrough(51      const MachineBasicBlock *MBB) const override;52 53private:54  void customEmitInstruction(const MachineInstr *MI);55  void emitCallInstruction(const MachineInstr *MI);56 57public:58  static char ID;59};60} // end of anonymous namespace61 62void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,63                                   raw_ostream &O) {64  const MachineOperand &MO = MI->getOperand(OpNum);65 66  switch (MO.getType()) {67  case MachineOperand::MO_Register:68    O << LanaiInstPrinter::getRegisterName(MO.getReg());69    break;70 71  case MachineOperand::MO_Immediate:72    O << MO.getImm();73    break;74 75  case MachineOperand::MO_MachineBasicBlock:76    O << *MO.getMBB()->getSymbol();77    break;78 79  case MachineOperand::MO_GlobalAddress:80    O << *getSymbol(MO.getGlobal());81    break;82 83  case MachineOperand::MO_BlockAddress: {84    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());85    O << BA->getName();86    break;87  }88 89  case MachineOperand::MO_ExternalSymbol:90    O << *GetExternalSymbolSymbol(MO.getSymbolName());91    break;92 93  case MachineOperand::MO_JumpTableIndex:94    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'95      << MO.getIndex();96    break;97 98  case MachineOperand::MO_ConstantPoolIndex:99    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'100      << MO.getIndex();101    return;102 103  default:104    llvm_unreachable("<unknown operand type>");105  }106}107 108// PrintAsmOperand - Print out an operand for an inline asm expression.109bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,110                                      const char *ExtraCode, raw_ostream &O) {111  // Does this asm operand have a single letter operand modifier?112  if (ExtraCode && ExtraCode[0]) {113    if (ExtraCode[1])114      return true; // Unknown modifier.115 116    switch (ExtraCode[0]) {117    // The highest-numbered register of a pair.118    case 'H': {119      if (OpNo == 0)120        return true;121      const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);122      if (!FlagsOP.isImm())123        return true;124      const InlineAsm::Flag Flags(FlagsOP.getImm());125      const unsigned NumVals = Flags.getNumOperandRegisters();126      if (NumVals != 2)127        return true;128      unsigned RegOp = OpNo + 1;129      if (RegOp >= MI->getNumOperands())130        return true;131      const MachineOperand &MO = MI->getOperand(RegOp);132      if (!MO.isReg())133        return true;134      Register Reg = MO.getReg();135      O << LanaiInstPrinter::getRegisterName(Reg);136      return false;137    }138    default:139      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);140    }141  }142  printOperand(MI, OpNo, O);143  return false;144}145 146//===----------------------------------------------------------------------===//147void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {148  assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&149         "Unsupported call function");150 151  LanaiMCInstLower MCInstLowering(OutContext, *this);152  MCSubtargetInfo STI = getSubtargetInfo();153  // Insert save rca instruction immediately before the call.154  // TODO: We should generate a pc-relative mov instruction here instead155  // of pc + 16 (should be mov .+16 %rca).156  OutStreamer->emitInstruction(MCInstBuilder(Lanai::ADD_I_LO)157                                   .addReg(Lanai::RCA)158                                   .addReg(Lanai::PC)159                                   .addImm(16),160                               STI);161 162  // Push rca onto the stack.163  //   st %rca, [--%sp]164  OutStreamer->emitInstruction(MCInstBuilder(Lanai::SW_RI)165                                   .addReg(Lanai::RCA)166                                   .addReg(Lanai::SP)167                                   .addImm(-4)168                                   .addImm(LPAC::makePreOp(LPAC::ADD)),169                               STI);170 171  // Lower the call instruction.172  if (MI->getOpcode() == Lanai::CALL) {173    MCInst TmpInst;174    MCInstLowering.Lower(MI, TmpInst);175    TmpInst.setOpcode(Lanai::BT);176    OutStreamer->emitInstruction(TmpInst, STI);177  } else {178    OutStreamer->emitInstruction(MCInstBuilder(Lanai::ADD_R)179                                     .addReg(Lanai::PC)180                                     .addReg(MI->getOperand(0).getReg())181                                     .addReg(Lanai::R0)182                                     .addImm(LPCC::ICC_T),183                                 STI);184  }185}186 187void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {188  LanaiMCInstLower MCInstLowering(OutContext, *this);189  MCSubtargetInfo STI = getSubtargetInfo();190  MCInst TmpInst;191  MCInstLowering.Lower(MI, TmpInst);192  OutStreamer->emitInstruction(TmpInst, STI);193}194 195void LanaiAsmPrinter::emitInstruction(const MachineInstr *MI) {196  Lanai_MC::verifyInstructionPredicates(MI->getOpcode(),197                                        getSubtargetInfo().getFeatureBits());198 199  MachineBasicBlock::const_instr_iterator I = MI->getIterator();200  MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();201 202  do {203    if (I->isCall()) {204      emitCallInstruction(&*I);205      continue;206    }207 208    customEmitInstruction(&*I);209  } while ((++I != E) && I->isInsideBundle());210}211 212// isBlockOnlyReachableByFallthough - Return true if the basic block has213// exactly one predecessor and the control transfer mechanism between214// the predecessor and this block is a fall-through.215// FIXME: could the overridden cases be handled in analyzeBranch?216bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(217    const MachineBasicBlock *MBB) const {218  // The predecessor has to be immediately before this block.219  const MachineBasicBlock *Pred = *MBB->pred_begin();220 221  // If the predecessor is a switch statement, assume a jump table222  // implementation, so it is not a fall through.223  if (const BasicBlock *B = Pred->getBasicBlock())224    if (isa<SwitchInst>(B->getTerminator()))225      return false;226 227  // Check default implementation228  if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))229    return false;230 231  // Otherwise, check the last instruction.232  // Check if the last terminator is an unconditional branch.233  MachineBasicBlock::const_iterator I = Pred->end();234  while (I != Pred->begin() && !(--I)->isTerminator()) {235  }236 237  return !I->isBarrier();238}239 240char LanaiAsmPrinter::ID = 0;241 242INITIALIZE_PASS(LanaiAsmPrinter, "lanai-asm-printer", "Lanai Assembly Printer",243                false, false)244 245// Force static initialization.246extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void247LLVMInitializeLanaiAsmPrinter() {248  RegisterAsmPrinter<LanaiAsmPrinter> X(getTheLanaiTarget());249}250