LLVM API Documentation

SparcAsmPrinter.cpp
Go to the documentation of this file.
00001 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains a printer that converts from our internal representation
00011 // of machine-dependent LLVM code to GAS-format SPARC assembly language.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "Sparc.h"
00016 #include "InstPrinter/SparcInstPrinter.h"
00017 #include "MCTargetDesc/SparcMCExpr.h"
00018 #include "SparcInstrInfo.h"
00019 #include "SparcTargetMachine.h"
00020 #include "SparcTargetStreamer.h"
00021 #include "llvm/ADT/SmallString.h"
00022 #include "llvm/CodeGen/AsmPrinter.h"
00023 #include "llvm/CodeGen/MachineInstr.h"
00024 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
00025 #include "llvm/CodeGen/MachineRegisterInfo.h"
00026 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
00027 #include "llvm/IR/Mangler.h"
00028 #include "llvm/MC/MCAsmInfo.h"
00029 #include "llvm/MC/MCContext.h"
00030 #include "llvm/MC/MCInst.h"
00031 #include "llvm/MC/MCStreamer.h"
00032 #include "llvm/MC/MCSymbol.h"
00033 #include "llvm/Support/TargetRegistry.h"
00034 #include "llvm/Support/raw_ostream.h"
00035 using namespace llvm;
00036 
00037 #define DEBUG_TYPE "asm-printer"
00038 
00039 namespace {
00040   class SparcAsmPrinter : public AsmPrinter {
00041     SparcTargetStreamer &getTargetStreamer() {
00042       return static_cast<SparcTargetStreamer &>(
00043           *OutStreamer.getTargetStreamer());
00044     }
00045   public:
00046     explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
00047       : AsmPrinter(TM, Streamer) {}
00048 
00049     const char *getPassName() const override {
00050       return "Sparc Assembly Printer";
00051     }
00052 
00053     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
00054     void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
00055                          const char *Modifier = nullptr);
00056     void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
00057 
00058     void EmitFunctionBodyStart() override;
00059     void EmitInstruction(const MachineInstr *MI) override;
00060     void EmitEndOfAsmFile(Module &M) override;
00061 
00062     static const char *getRegisterName(unsigned RegNo) {
00063       return SparcInstPrinter::getRegisterName(RegNo);
00064     }
00065 
00066     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00067                          unsigned AsmVariant, const char *ExtraCode,
00068                          raw_ostream &O) override;
00069     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
00070                                unsigned AsmVariant, const char *ExtraCode,
00071                                raw_ostream &O) override;
00072 
00073     void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
00074                                    const MCSubtargetInfo &STI);
00075 
00076   };
00077 } // end of anonymous namespace
00078 
00079 static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
00080                                       MCSymbol *Sym, MCContext &OutContext) {
00081   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
00082                                                          OutContext);
00083   const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
00084   return MCOperand::CreateExpr(expr);
00085 
00086 }
00087 static MCOperand createPCXCallOP(MCSymbol *Label,
00088                                  MCContext &OutContext) {
00089   return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
00090 }
00091 
00092 static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
00093                                     MCSymbol *GOTLabel, MCSymbol *StartLabel,
00094                                     MCSymbol *CurLabel,
00095                                     MCContext &OutContext)
00096 {
00097   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext);
00098   const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel,
00099                                                          OutContext);
00100   const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel,
00101                                                        OutContext);
00102 
00103   const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext);
00104   const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext);
00105   const SparcMCExpr *expr = SparcMCExpr::Create(Kind,
00106                                                 Add, OutContext);
00107   return MCOperand::CreateExpr(expr);
00108 }
00109 
00110 static void EmitCall(MCStreamer &OutStreamer,
00111                      MCOperand &Callee,
00112                      const MCSubtargetInfo &STI)
00113 {
00114   MCInst CallInst;
00115   CallInst.setOpcode(SP::CALL);
00116   CallInst.addOperand(Callee);
00117   OutStreamer.EmitInstruction(CallInst, STI);
00118 }
00119 
00120 static void EmitSETHI(MCStreamer &OutStreamer,
00121                       MCOperand &Imm, MCOperand &RD,
00122                       const MCSubtargetInfo &STI)
00123 {
00124   MCInst SETHIInst;
00125   SETHIInst.setOpcode(SP::SETHIi);
00126   SETHIInst.addOperand(RD);
00127   SETHIInst.addOperand(Imm);
00128   OutStreamer.EmitInstruction(SETHIInst, STI);
00129 }
00130 
00131 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
00132                        MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
00133                        const MCSubtargetInfo &STI)
00134 {
00135   MCInst Inst;
00136   Inst.setOpcode(Opcode);
00137   Inst.addOperand(RD);
00138   Inst.addOperand(RS1);
00139   Inst.addOperand(Src2);
00140   OutStreamer.EmitInstruction(Inst, STI);
00141 }
00142 
00143 static void EmitOR(MCStreamer &OutStreamer,
00144                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
00145                    const MCSubtargetInfo &STI) {
00146   EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
00147 }
00148 
00149 static void EmitADD(MCStreamer &OutStreamer,
00150                     MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
00151                     const MCSubtargetInfo &STI) {
00152   EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
00153 }
00154 
00155 static void EmitSHL(MCStreamer &OutStreamer,
00156                     MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
00157                     const MCSubtargetInfo &STI) {
00158   EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
00159 }
00160 
00161 
00162 static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
00163                      SparcMCExpr::VariantKind HiKind,
00164                      SparcMCExpr::VariantKind LoKind,
00165                      MCOperand &RD,
00166                      MCContext &OutContext,
00167                      const MCSubtargetInfo &STI) {
00168 
00169   MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
00170   MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
00171   EmitSETHI(OutStreamer, hi, RD, STI);
00172   EmitOR(OutStreamer, RD, lo, RD, STI);
00173 }
00174 
00175 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
00176                                                 const MCSubtargetInfo &STI)
00177 {
00178   MCSymbol *GOTLabel   =
00179     OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
00180 
00181   const MachineOperand &MO = MI->getOperand(0);
00182   assert(MO.getReg() != SP::O7 &&
00183          "%o7 is assigned as destination for getpcx!");
00184 
00185   MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
00186 
00187 
00188   if (TM.getRelocationModel() != Reloc::PIC_) {
00189     // Just load the address of GOT to MCRegOP.
00190     switch(TM.getCodeModel()) {
00191     default:
00192       llvm_unreachable("Unsupported absolute code model");
00193     case CodeModel::Small:
00194       EmitHiLo(OutStreamer, GOTLabel,
00195                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
00196                MCRegOP, OutContext, STI);
00197       break;
00198     case CodeModel::Medium: {
00199       EmitHiLo(OutStreamer, GOTLabel,
00200                SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
00201                MCRegOP, OutContext, STI);
00202       MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
00203                                                                    OutContext));
00204       EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI);
00205       MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
00206                                           GOTLabel, OutContext);
00207       EmitOR(OutStreamer, MCRegOP, lo, MCRegOP, STI);
00208       break;
00209     }
00210     case CodeModel::Large: {
00211       EmitHiLo(OutStreamer, GOTLabel,
00212                SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
00213                MCRegOP, OutContext, STI);
00214       MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
00215                                                                    OutContext));
00216       EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI);
00217       // Use register %o7 to load the lower 32 bits.
00218       MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
00219       EmitHiLo(OutStreamer, GOTLabel,
00220                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
00221                RegO7, OutContext, STI);
00222       EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
00223     }
00224     }
00225     return;
00226   }
00227 
00228   MCSymbol *StartLabel = OutContext.CreateTempSymbol();
00229   MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
00230   MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
00231 
00232   MCOperand RegO7   = MCOperand::CreateReg(SP::O7);
00233 
00234   // <StartLabel>:
00235   //   call <EndLabel>
00236   // <SethiLabel>:
00237   //     sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
00238   // <EndLabel>:
00239   //   or  <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
00240   //   add <MO>, %o7, <MO>
00241 
00242   OutStreamer.EmitLabel(StartLabel);
00243   MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
00244   EmitCall(OutStreamer, Callee, STI);
00245   OutStreamer.EmitLabel(SethiLabel);
00246   MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
00247                                        GOTLabel, StartLabel, SethiLabel,
00248                                        OutContext);
00249   EmitSETHI(OutStreamer, hiImm, MCRegOP, STI);
00250   OutStreamer.EmitLabel(EndLabel);
00251   MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
00252                                        GOTLabel, StartLabel, EndLabel,
00253                                        OutContext);
00254   EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP, STI);
00255   EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
00256 }
00257 
00258 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
00259 {
00260 
00261   switch (MI->getOpcode()) {
00262   default: break;
00263   case TargetOpcode::DBG_VALUE:
00264     // FIXME: Debug Value.
00265     return;
00266   case SP::GETPCX:
00267     LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
00268     return;
00269   }
00270   MachineBasicBlock::const_instr_iterator I = MI;
00271   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
00272   do {
00273     MCInst TmpInst;
00274     LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
00275     EmitToStreamer(OutStreamer, TmpInst);
00276   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
00277 }
00278 
00279 void SparcAsmPrinter::EmitFunctionBodyStart() {
00280   if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
00281     return;
00282 
00283   const MachineRegisterInfo &MRI = MF->getRegInfo();
00284   const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
00285   for (unsigned i = 0; globalRegs[i] != 0; ++i) {
00286     unsigned reg = globalRegs[i];
00287     if (MRI.use_empty(reg))
00288       continue;
00289 
00290     if  (reg == SP::G6 || reg == SP::G7)
00291       getTargetStreamer().emitSparcRegisterIgnore(reg);
00292     else
00293       getTargetStreamer().emitSparcRegisterScratch(reg);
00294   }
00295 }
00296 
00297 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
00298                                    raw_ostream &O) {
00299   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
00300   const MachineOperand &MO = MI->getOperand (opNum);
00301   SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags();
00302 
00303 #ifndef NDEBUG
00304   // Verify the target flags.
00305   if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
00306     if (MI->getOpcode() == SP::CALL)
00307       assert(TF == SparcMCExpr::VK_Sparc_None &&
00308              "Cannot handle target flags on call address");
00309     else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
00310       assert((TF == SparcMCExpr::VK_Sparc_HI
00311               || TF == SparcMCExpr::VK_Sparc_H44
00312               || TF == SparcMCExpr::VK_Sparc_HH
00313               || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22
00314               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22
00315               || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22
00316               || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22
00317               || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) &&
00318              "Invalid target flags for address operand on sethi");
00319     else if (MI->getOpcode() == SP::TLS_CALL)
00320       assert((TF == SparcMCExpr::VK_Sparc_None
00321               || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL
00322               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) &&
00323              "Cannot handle target flags on tls call address");
00324     else if (MI->getOpcode() == SP::TLS_ADDrr)
00325       assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD
00326               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD
00327               || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD
00328               || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) &&
00329              "Cannot handle target flags on add for TLS");
00330     else if (MI->getOpcode() == SP::TLS_LDrr)
00331       assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
00332              "Cannot handle target flags on ld for TLS");
00333     else if (MI->getOpcode() == SP::TLS_LDXrr)
00334       assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
00335              "Cannot handle target flags on ldx for TLS");
00336     else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
00337       assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10
00338               || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) &&
00339              "Cannot handle target flags on xor for TLS");
00340     else
00341       assert((TF == SparcMCExpr::VK_Sparc_LO
00342               || TF == SparcMCExpr::VK_Sparc_M44
00343               || TF == SparcMCExpr::VK_Sparc_L44
00344               || TF == SparcMCExpr::VK_Sparc_HM
00345               || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10
00346               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10
00347               || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) &&
00348              "Invalid target flags for small address operand");
00349   }
00350 #endif
00351 
00352 
00353   bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
00354 
00355   switch (MO.getType()) {
00356   case MachineOperand::MO_Register:
00357     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
00358     break;
00359 
00360   case MachineOperand::MO_Immediate:
00361     O << (int)MO.getImm();
00362     break;
00363   case MachineOperand::MO_MachineBasicBlock:
00364     O << *MO.getMBB()->getSymbol();
00365     return;
00366   case MachineOperand::MO_GlobalAddress:
00367     O << *getSymbol(MO.getGlobal());
00368     break;
00369   case MachineOperand::MO_BlockAddress:
00370     O <<  GetBlockAddressSymbol(MO.getBlockAddress())->getName();
00371     break;
00372   case MachineOperand::MO_ExternalSymbol:
00373     O << MO.getSymbolName();
00374     break;
00375   case MachineOperand::MO_ConstantPoolIndex:
00376     O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
00377       << MO.getIndex();
00378     break;
00379   default:
00380     llvm_unreachable("<unknown operand type>");
00381   }
00382   if (CloseParen) O << ")";
00383 }
00384 
00385 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
00386                                       raw_ostream &O, const char *Modifier) {
00387   printOperand(MI, opNum, O);
00388 
00389   // If this is an ADD operand, emit it like normal operands.
00390   if (Modifier && !strcmp(Modifier, "arith")) {
00391     O << ", ";
00392     printOperand(MI, opNum+1, O);
00393     return;
00394   }
00395 
00396   if (MI->getOperand(opNum+1).isReg() &&
00397       MI->getOperand(opNum+1).getReg() == SP::G0)
00398     return;   // don't print "+%g0"
00399   if (MI->getOperand(opNum+1).isImm() &&
00400       MI->getOperand(opNum+1).getImm() == 0)
00401     return;   // don't print "+0"
00402 
00403   O << "+";
00404   printOperand(MI, opNum+1, O);
00405 }
00406 
00407 /// PrintAsmOperand - Print out an operand for an inline asm expression.
00408 ///
00409 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00410                                       unsigned AsmVariant,
00411                                       const char *ExtraCode,
00412                                       raw_ostream &O) {
00413   if (ExtraCode && ExtraCode[0]) {
00414     if (ExtraCode[1] != 0) return true; // Unknown modifier.
00415 
00416     switch (ExtraCode[0]) {
00417     default:
00418       // See if this is a generic print operand
00419       return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
00420     case 'r':
00421      break;
00422     }
00423   }
00424 
00425   printOperand(MI, OpNo, O);
00426 
00427   return false;
00428 }
00429 
00430 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
00431                                             unsigned OpNo, unsigned AsmVariant,
00432                                             const char *ExtraCode,
00433                                             raw_ostream &O) {
00434   if (ExtraCode && ExtraCode[0])
00435     return true;  // Unknown modifier
00436 
00437   O << '[';
00438   printMemOperand(MI, OpNo, O);
00439   O << ']';
00440 
00441   return false;
00442 }
00443 
00444 void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) {
00445   const TargetLoweringObjectFileELF &TLOFELF =
00446     static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
00447   MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
00448 
00449   // Generate stubs for global variables.
00450   MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
00451   if (!Stubs.empty()) {
00452     OutStreamer.SwitchSection(TLOFELF.getDataSection());
00453     unsigned PtrSize =
00454         TM.getSubtargetImpl()->getDataLayout()->getPointerSize(0);
00455     for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
00456       OutStreamer.EmitLabel(Stubs[i].first);
00457       OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize);
00458     }
00459   }
00460 }
00461 
00462 // Force static initialization.
00463 extern "C" void LLVMInitializeSparcAsmPrinter() {
00464   RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
00465   RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target);
00466 }