brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.6 KiB · ba8cf78 Raw
426 lines · cpp
1//===-- VEAsmPrinter.cpp - VE 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 GAS-format VE assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/VEInstPrinter.h"15#include "MCTargetDesc/VEMCAsmInfo.h"16#include "MCTargetDesc/VETargetStreamer.h"17#include "TargetInfo/VETargetInfo.h"18#include "VE.h"19#include "VEInstrInfo.h"20#include "llvm/CodeGen/AsmPrinter.h"21#include "llvm/CodeGen/MachineInstr.h"22#include "llvm/CodeGen/MachineModuleInfoImpls.h"23#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"24#include "llvm/IR/Mangler.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCContext.h"27#include "llvm/MC/MCInst.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSymbol.h"30#include "llvm/MC/TargetRegistry.h"31#include "llvm/Support/Compiler.h"32#include "llvm/Support/raw_ostream.h"33using namespace llvm;34 35#define DEBUG_TYPE "ve-asmprinter"36 37namespace {38class VEAsmPrinter : public AsmPrinter {39  VETargetStreamer &getTargetStreamer() {40    return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());41  }42 43public:44  explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)45      : AsmPrinter(TM, std::move(Streamer), ID) {}46 47  StringRef getPassName() const override { return "VE Assembly Printer"; }48 49  void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,50                                 const MCSubtargetInfo &STI);51  void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,52                                    const MCSubtargetInfo &STI);53  void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,54                                     const MCSubtargetInfo &STI);55 56  void emitInstruction(const MachineInstr *MI) override;57 58  static const char *getRegisterName(MCRegister Reg) {59    return VEInstPrinter::getRegisterName(Reg);60  }61  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);62  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,63                       const char *ExtraCode, raw_ostream &O) override;64  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,65                             const char *ExtraCode, raw_ostream &O) override;66 67  static char ID;68};69} // end of anonymous namespace70 71static MCOperand createVEMCOperand(VE::Specifier Kind, MCSymbol *Sym,72                                   MCContext &OutContext) {73  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);74  return MCOperand::createExpr(75      MCSpecifierExpr::create(MCSym, Kind, OutContext));76}77 78static MCOperand createGOTRelExprOp(VE::Specifier Kind, MCSymbol *GOTLabel,79                                    MCContext &OutContext) {80  const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);81  return MCOperand::createExpr(MCSpecifierExpr::create(GOT, Kind, OutContext));82}83 84static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,85                    const MCSubtargetInfo &STI) {86  MCInst SICInst;87  SICInst.setOpcode(VE::SIC);88  SICInst.addOperand(RD);89  OutStreamer.emitInstruction(SICInst, STI);90}91 92static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,93                     const MCSubtargetInfo &STI) {94  MCInst BSICInst;95  BSICInst.setOpcode(VE::BSICrii);96  BSICInst.addOperand(R1);97  BSICInst.addOperand(R2);98  MCOperand czero = MCOperand::createImm(0);99  BSICInst.addOperand(czero);100  BSICInst.addOperand(czero);101  OutStreamer.emitInstruction(BSICInst, STI);102}103 104static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,105                       const MCSubtargetInfo &STI) {106  MCInst LEAInst;107  LEAInst.setOpcode(VE::LEAzii);108  LEAInst.addOperand(RD);109  MCOperand CZero = MCOperand::createImm(0);110  LEAInst.addOperand(CZero);111  LEAInst.addOperand(CZero);112  LEAInst.addOperand(Imm);113  OutStreamer.emitInstruction(LEAInst, STI);114}115 116static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,117                         const MCSubtargetInfo &STI) {118  MCInst LEASLInst;119  LEASLInst.setOpcode(VE::LEASLzii);120  LEASLInst.addOperand(RD);121  MCOperand CZero = MCOperand::createImm(0);122  LEASLInst.addOperand(CZero);123  LEASLInst.addOperand(CZero);124  LEASLInst.addOperand(Imm);125  OutStreamer.emitInstruction(LEASLInst, STI);126}127 128static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,129                       MCOperand &RD, const MCSubtargetInfo &STI) {130  MCInst LEAInst;131  LEAInst.setOpcode(VE::LEAzii);132  LEAInst.addOperand(RD);133  MCOperand CZero = MCOperand::createImm(0);134  LEAInst.addOperand(CZero);135  LEAInst.addOperand(RS1);136  LEAInst.addOperand(Imm);137  OutStreamer.emitInstruction(LEAInst, STI);138}139 140static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,141                         MCOperand &RS2, MCOperand &Imm, MCOperand &RD,142                         const MCSubtargetInfo &STI) {143  MCInst LEASLInst;144  LEASLInst.setOpcode(VE::LEASLrri);145  LEASLInst.addOperand(RD);146  LEASLInst.addOperand(RS1);147  LEASLInst.addOperand(RS2);148  LEASLInst.addOperand(Imm);149  OutStreamer.emitInstruction(LEASLInst, STI);150}151 152static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,153                       MCOperand &Src2, MCOperand &RD,154                       const MCSubtargetInfo &STI) {155  MCInst Inst;156  Inst.setOpcode(Opcode);157  Inst.addOperand(RD);158  Inst.addOperand(RS1);159  Inst.addOperand(Src2);160  OutStreamer.emitInstruction(Inst, STI);161}162 163static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,164                      MCOperand &RD, const MCSubtargetInfo &STI) {165  emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);166}167 168static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,169                     VE::Specifier HiKind, VE::Specifier LoKind, MCOperand &RD,170                     MCContext &OutContext, const MCSubtargetInfo &STI) {171 172  MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);173  MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);174  emitLEAzzi(OutStreamer, lo, RD, STI);175  MCOperand M032 = MCOperand::createImm(M0(32));176  emitANDrm(OutStreamer, RD, M032, RD, STI);177  emitLEASLzzi(OutStreamer, hi, RD, STI);178}179 180void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,181                                             const MCSubtargetInfo &STI) {182  MCSymbol *GOTLabel =183      OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));184 185  const MachineOperand &MO = MI->getOperand(0);186  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());187 188  if (!isPositionIndependent()) {189    // Just load the address of GOT to MCRegOP.190    switch (TM.getCodeModel()) {191    default:192      llvm_unreachable("Unsupported absolute code model");193    case CodeModel::Small:194    case CodeModel::Medium:195    case CodeModel::Large:196      emitHiLo(*OutStreamer, GOTLabel, VE::S_HI32, VE::S_LO32, MCRegOP,197               OutContext, STI);198      break;199    }200    return;201  }202 203  MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT204  MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT205 206  // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)207  // and %got, %got, (32)0208  // sic %plt209  // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)210  MCOperand cim24 = MCOperand::createImm(-24);211  MCOperand loImm = createGOTRelExprOp(VE::S_PC_LO32, GOTLabel, OutContext);212  emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);213  MCOperand M032 = MCOperand::createImm(M0(32));214  emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);215  emitSIC(*OutStreamer, RegPLT, STI);216  MCOperand hiImm = createGOTRelExprOp(VE::S_PC_HI32, GOTLabel, OutContext);217  emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);218}219 220void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,221                                                const MCSubtargetInfo &STI) {222  const MachineOperand &MO = MI->getOperand(0);223  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());224  const MachineOperand &Addr = MI->getOperand(1);225  MCSymbol *AddrSym = nullptr;226 227  switch (Addr.getType()) {228  default:229    llvm_unreachable("<unknown operand type>");230    return;231  case MachineOperand::MO_MachineBasicBlock:232    report_fatal_error("MBB is not supported yet");233    return;234  case MachineOperand::MO_ConstantPoolIndex:235    report_fatal_error("ConstantPool is not supported yet");236    return;237  case MachineOperand::MO_ExternalSymbol:238    AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());239    break;240  case MachineOperand::MO_GlobalAddress:241    AddrSym = getSymbol(Addr.getGlobal());242    break;243  }244 245  if (!isPositionIndependent()) {246    llvm_unreachable("Unsupported uses of %plt in not PIC code");247    return;248  }249 250  MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT251 252  // lea %dst, func@plt_lo(-24)253  // and %dst, %dst, (32)0254  // sic %plt                            ; FIXME: is it safe to use %plt here?255  // lea.sl %dst, func@plt_hi(%plt, %dst)256  MCOperand cim24 = MCOperand::createImm(-24);257  MCOperand loImm = createGOTRelExprOp(VE::S_PLT_LO32, AddrSym, OutContext);258  emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);259  MCOperand M032 = MCOperand::createImm(M0(32));260  emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);261  emitSIC(*OutStreamer, RegPLT, STI);262  MCOperand hiImm = createGOTRelExprOp(VE::S_PLT_HI32, AddrSym, OutContext);263  emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);264}265 266void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,267                                                 const MCSubtargetInfo &STI) {268  const MachineOperand &Addr = MI->getOperand(0);269  MCSymbol *AddrSym = nullptr;270 271  switch (Addr.getType()) {272  default:273    llvm_unreachable("<unknown operand type>");274    return;275  case MachineOperand::MO_MachineBasicBlock:276    report_fatal_error("MBB is not supported yet");277    return;278  case MachineOperand::MO_ConstantPoolIndex:279    report_fatal_error("ConstantPool is not supported yet");280    return;281  case MachineOperand::MO_ExternalSymbol:282    AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());283    break;284  case MachineOperand::MO_GlobalAddress:285    AddrSym = getSymbol(Addr.getGlobal());286    break;287  }288 289  MCOperand RegLR = MCOperand::createReg(VE::SX10);  // LR290  MCOperand RegS0 = MCOperand::createReg(VE::SX0);   // S0291  MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12292  MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));293 294  // lea %s0, sym@tls_gd_lo(-24)295  // and %s0, %s0, (32)0296  // sic %lr297  // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)298  // lea %s12, __tls_get_addr@plt_lo(8)299  // and %s12, %s12, (32)0300  // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)301  // bsic %lr, (, %s12)302  MCOperand cim24 = MCOperand::createImm(-24);303  MCOperand loImm = createGOTRelExprOp(VE::S_TLS_GD_LO32, AddrSym, OutContext);304  emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);305  MCOperand M032 = MCOperand::createImm(M0(32));306  emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);307  emitSIC(*OutStreamer, RegLR, STI);308  MCOperand hiImm = createGOTRelExprOp(VE::S_TLS_GD_HI32, AddrSym, OutContext);309  emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);310  MCOperand ci8 = MCOperand::createImm(8);311  MCOperand loImm2 =312      createGOTRelExprOp(VE::S_PLT_LO32, GetTLSLabel, OutContext);313  emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);314  emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);315  MCOperand hiImm2 =316      createGOTRelExprOp(VE::S_PLT_HI32, GetTLSLabel, OutContext);317  emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);318  emitBSIC(*OutStreamer, RegLR, RegS12, STI);319}320 321void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {322  VE_MC::verifyInstructionPredicates(MI->getOpcode(),323                                     getSubtargetInfo().getFeatureBits());324 325  switch (MI->getOpcode()) {326  default:327    break;328  case TargetOpcode::DBG_VALUE:329    // FIXME: Debug Value.330    return;331  case VE::GETGOT:332    lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());333    return;334  case VE::GETFUNPLT:335    lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());336    return;337  case VE::GETTLSADDR:338    lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());339    return;340  }341 342  MachineBasicBlock::const_instr_iterator I = MI->getIterator();343  MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();344  do {345    MCInst TmpInst;346    LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);347    EmitToStreamer(*OutStreamer, TmpInst);348  } while ((++I != E) && I->isInsideBundle()); // Delay slot check.349}350 351void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,352                                raw_ostream &O) {353  const MachineOperand &MO = MI->getOperand(OpNum);354 355  switch (MO.getType()) {356  case MachineOperand::MO_Register:357    O << "%" << StringRef(getRegisterName(MO.getReg())).lower();358    break;359  case MachineOperand::MO_Immediate:360    O << (int)MO.getImm();361    break;362  default:363    llvm_unreachable("<unknown operand type>");364  }365}366 367// PrintAsmOperand - Print out an operand for an inline asm expression.368bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,369                                   const char *ExtraCode, raw_ostream &O) {370  if (ExtraCode && ExtraCode[0]) {371    if (ExtraCode[1] != 0)372      return true; // Unknown modifier.373 374    switch (ExtraCode[0]) {375    default:376      // See if this is a generic print operand377      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);378    case 'r':379    case 'v':380      break;381    }382  }383 384  printOperand(MI, OpNo, O);385 386  return false;387}388 389bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,390                                         const char *ExtraCode,391                                         raw_ostream &O) {392  if (ExtraCode && ExtraCode[0])393    return true;  // Unknown modifier394 395  if (MI->getOperand(OpNo+1).isImm() &&396      MI->getOperand(OpNo+1).getImm() == 0) {397    // don't print "+0"398  } else {399    printOperand(MI, OpNo+1, O);400  }401  if (MI->getOperand(OpNo).isImm() &&402      MI->getOperand(OpNo).getImm() == 0) {403    if (MI->getOperand(OpNo+1).isImm() &&404        MI->getOperand(OpNo+1).getImm() == 0) {405      O << "0";406    } else {407      // don't print "(0)"408    }409  } else {410    O << "(";411    printOperand(MI, OpNo, O);412    O << ")";413  }414  return false;415}416 417char VEAsmPrinter::ID = 0;418 419INITIALIZE_PASS(VEAsmPrinter, "ve-asm-printer", "VE Assembly Printer", false,420                false)421 422// Force static initialization.423extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {424  RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());425}426