Home | History | Annotate | Download | only in Sparc
      1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains a printer that converts from our internal representation
     11 // of machine-dependent LLVM code to GAS-format SPARC assembly language.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "Sparc.h"
     16 #include "InstPrinter/SparcInstPrinter.h"
     17 #include "MCTargetDesc/SparcMCExpr.h"
     18 #include "SparcInstrInfo.h"
     19 #include "SparcTargetMachine.h"
     20 #include "SparcTargetStreamer.h"
     21 #include "llvm/ADT/SmallString.h"
     22 #include "llvm/CodeGen/AsmPrinter.h"
     23 #include "llvm/CodeGen/MachineInstr.h"
     24 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
     25 #include "llvm/CodeGen/MachineRegisterInfo.h"
     26 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
     27 #include "llvm/IR/Mangler.h"
     28 #include "llvm/MC/MCAsmInfo.h"
     29 #include "llvm/MC/MCContext.h"
     30 #include "llvm/MC/MCInst.h"
     31 #include "llvm/MC/MCStreamer.h"
     32 #include "llvm/MC/MCSymbol.h"
     33 #include "llvm/Support/TargetRegistry.h"
     34 #include "llvm/Support/raw_ostream.h"
     35 using namespace llvm;
     36 
     37 #define DEBUG_TYPE "asm-printer"
     38 
     39 namespace {
     40   class SparcAsmPrinter : public AsmPrinter {
     41     SparcTargetStreamer &getTargetStreamer() {
     42       return static_cast<SparcTargetStreamer &>(
     43           *OutStreamer->getTargetStreamer());
     44     }
     45   public:
     46     explicit SparcAsmPrinter(TargetMachine &TM,
     47                              std::unique_ptr<MCStreamer> Streamer)
     48         : AsmPrinter(TM, std::move(Streamer)) {}
     49 
     50     const char *getPassName() const override {
     51       return "Sparc Assembly Printer";
     52     }
     53 
     54     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
     55     void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
     56                          const char *Modifier = nullptr);
     57     void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
     58 
     59     void EmitFunctionBodyStart() override;
     60     void EmitInstruction(const MachineInstr *MI) override;
     61 
     62     static const char *getRegisterName(unsigned RegNo) {
     63       return SparcInstPrinter::getRegisterName(RegNo);
     64     }
     65 
     66     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     67                          unsigned AsmVariant, const char *ExtraCode,
     68                          raw_ostream &O) override;
     69     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
     70                                unsigned AsmVariant, const char *ExtraCode,
     71                                raw_ostream &O) override;
     72 
     73     void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
     74                                    const MCSubtargetInfo &STI);
     75 
     76   };
     77 } // end of anonymous namespace
     78 
     79 static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
     80                                       MCSymbol *Sym, MCContext &OutContext) {
     81   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym,
     82                                                          OutContext);
     83   const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext);
     84   return MCOperand::createExpr(expr);
     85 
     86 }
     87 static MCOperand createPCXCallOP(MCSymbol *Label,
     88                                  MCContext &OutContext) {
     89   return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
     90 }
     91 
     92 static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
     93                                     MCSymbol *GOTLabel, MCSymbol *StartLabel,
     94                                     MCSymbol *CurLabel,
     95                                     MCContext &OutContext)
     96 {
     97   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
     98   const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel,
     99                                                          OutContext);
    100   const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel,
    101                                                        OutContext);
    102 
    103   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext);
    104   const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext);
    105   const SparcMCExpr *expr = SparcMCExpr::create(Kind,
    106                                                 Add, OutContext);
    107   return MCOperand::createExpr(expr);
    108 }
    109 
    110 static void EmitCall(MCStreamer &OutStreamer,
    111                      MCOperand &Callee,
    112                      const MCSubtargetInfo &STI)
    113 {
    114   MCInst CallInst;
    115   CallInst.setOpcode(SP::CALL);
    116   CallInst.addOperand(Callee);
    117   OutStreamer.EmitInstruction(CallInst, STI);
    118 }
    119 
    120 static void EmitSETHI(MCStreamer &OutStreamer,
    121                       MCOperand &Imm, MCOperand &RD,
    122                       const MCSubtargetInfo &STI)
    123 {
    124   MCInst SETHIInst;
    125   SETHIInst.setOpcode(SP::SETHIi);
    126   SETHIInst.addOperand(RD);
    127   SETHIInst.addOperand(Imm);
    128   OutStreamer.EmitInstruction(SETHIInst, STI);
    129 }
    130 
    131 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
    132                        MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
    133                        const MCSubtargetInfo &STI)
    134 {
    135   MCInst Inst;
    136   Inst.setOpcode(Opcode);
    137   Inst.addOperand(RD);
    138   Inst.addOperand(RS1);
    139   Inst.addOperand(Src2);
    140   OutStreamer.EmitInstruction(Inst, STI);
    141 }
    142 
    143 static void EmitOR(MCStreamer &OutStreamer,
    144                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
    145                    const MCSubtargetInfo &STI) {
    146   EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
    147 }
    148 
    149 static void EmitADD(MCStreamer &OutStreamer,
    150                     MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
    151                     const MCSubtargetInfo &STI) {
    152   EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
    153 }
    154 
    155 static void EmitSHL(MCStreamer &OutStreamer,
    156                     MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
    157                     const MCSubtargetInfo &STI) {
    158   EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
    159 }
    160 
    161 
    162 static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
    163                      SparcMCExpr::VariantKind HiKind,
    164                      SparcMCExpr::VariantKind LoKind,
    165                      MCOperand &RD,
    166                      MCContext &OutContext,
    167                      const MCSubtargetInfo &STI) {
    168 
    169   MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
    170   MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
    171   EmitSETHI(OutStreamer, hi, RD, STI);
    172   EmitOR(OutStreamer, RD, lo, RD, STI);
    173 }
    174 
    175 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
    176                                                 const MCSubtargetInfo &STI)
    177 {
    178   MCSymbol *GOTLabel   =
    179     OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
    180 
    181   const MachineOperand &MO = MI->getOperand(0);
    182   assert(MO.getReg() != SP::O7 &&
    183          "%o7 is assigned as destination for getpcx!");
    184 
    185   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
    186 
    187 
    188   if (TM.getRelocationModel() != Reloc::PIC_) {
    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       EmitHiLo(*OutStreamer, GOTLabel,
    195                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
    196                MCRegOP, OutContext, STI);
    197       break;
    198     case CodeModel::Medium: {
    199       EmitHiLo(*OutStreamer, GOTLabel,
    200                SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
    201                MCRegOP, OutContext, STI);
    202       MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(12,
    203                                                                    OutContext));
    204       EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
    205       MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
    206                                           GOTLabel, OutContext);
    207       EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
    208       break;
    209     }
    210     case CodeModel::Large: {
    211       EmitHiLo(*OutStreamer, GOTLabel,
    212                SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
    213                MCRegOP, OutContext, STI);
    214       MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(32,
    215                                                                    OutContext));
    216       EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
    217       // Use register %o7 to load the lower 32 bits.
    218       MCOperand RegO7 = MCOperand::createReg(SP::O7);
    219       EmitHiLo(*OutStreamer, GOTLabel,
    220                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
    221                RegO7, OutContext, STI);
    222       EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
    223     }
    224     }
    225     return;
    226   }
    227 
    228   MCSymbol *StartLabel = OutContext.createTempSymbol();
    229   MCSymbol *EndLabel   = OutContext.createTempSymbol();
    230   MCSymbol *SethiLabel = OutContext.createTempSymbol();
    231 
    232   MCOperand RegO7   = MCOperand::createReg(SP::O7);
    233 
    234   // <StartLabel>:
    235   //   call <EndLabel>
    236   // <SethiLabel>:
    237   //     sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
    238   // <EndLabel>:
    239   //   or  <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
    240   //   add <MO>, %o7, <MO>
    241 
    242   OutStreamer->EmitLabel(StartLabel);
    243   MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
    244   EmitCall(*OutStreamer, Callee, STI);
    245   OutStreamer->EmitLabel(SethiLabel);
    246   MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
    247                                        GOTLabel, StartLabel, SethiLabel,
    248                                        OutContext);
    249   EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
    250   OutStreamer->EmitLabel(EndLabel);
    251   MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
    252                                        GOTLabel, StartLabel, EndLabel,
    253                                        OutContext);
    254   EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
    255   EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
    256 }
    257 
    258 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
    259 {
    260 
    261   switch (MI->getOpcode()) {
    262   default: break;
    263   case TargetOpcode::DBG_VALUE:
    264     // FIXME: Debug Value.
    265     return;
    266   case SP::GETPCX:
    267     LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
    268     return;
    269   }
    270   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
    271   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
    272   do {
    273     MCInst TmpInst;
    274     LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this);
    275     EmitToStreamer(*OutStreamer, TmpInst);
    276   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
    277 }
    278 
    279 void SparcAsmPrinter::EmitFunctionBodyStart() {
    280   if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
    281     return;
    282 
    283   const MachineRegisterInfo &MRI = MF->getRegInfo();
    284   const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
    285   for (unsigned i = 0; globalRegs[i] != 0; ++i) {
    286     unsigned reg = globalRegs[i];
    287     if (MRI.use_empty(reg))
    288       continue;
    289 
    290     if  (reg == SP::G6 || reg == SP::G7)
    291       getTargetStreamer().emitSparcRegisterIgnore(reg);
    292     else
    293       getTargetStreamer().emitSparcRegisterScratch(reg);
    294   }
    295 }
    296 
    297 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
    298                                    raw_ostream &O) {
    299   const DataLayout &DL = getDataLayout();
    300   const MachineOperand &MO = MI->getOperand (opNum);
    301   SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags();
    302 
    303 #ifndef NDEBUG
    304   // Verify the target flags.
    305   if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
    306     if (MI->getOpcode() == SP::CALL)
    307       assert(TF == SparcMCExpr::VK_Sparc_None &&
    308              "Cannot handle target flags on call address");
    309     else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
    310       assert((TF == SparcMCExpr::VK_Sparc_HI
    311               || TF == SparcMCExpr::VK_Sparc_H44
    312               || TF == SparcMCExpr::VK_Sparc_HH
    313               || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22
    314               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22
    315               || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22
    316               || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22
    317               || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) &&
    318              "Invalid target flags for address operand on sethi");
    319     else if (MI->getOpcode() == SP::TLS_CALL)
    320       assert((TF == SparcMCExpr::VK_Sparc_None
    321               || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL
    322               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) &&
    323              "Cannot handle target flags on tls call address");
    324     else if (MI->getOpcode() == SP::TLS_ADDrr)
    325       assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD
    326               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD
    327               || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD
    328               || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) &&
    329              "Cannot handle target flags on add for TLS");
    330     else if (MI->getOpcode() == SP::TLS_LDrr)
    331       assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
    332              "Cannot handle target flags on ld for TLS");
    333     else if (MI->getOpcode() == SP::TLS_LDXrr)
    334       assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
    335              "Cannot handle target flags on ldx for TLS");
    336     else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
    337       assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10
    338               || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) &&
    339              "Cannot handle target flags on xor for TLS");
    340     else
    341       assert((TF == SparcMCExpr::VK_Sparc_LO
    342               || TF == SparcMCExpr::VK_Sparc_M44
    343               || TF == SparcMCExpr::VK_Sparc_L44
    344               || TF == SparcMCExpr::VK_Sparc_HM
    345               || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10
    346               || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10
    347               || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) &&
    348              "Invalid target flags for small address operand");
    349   }
    350 #endif
    351 
    352 
    353   bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
    354 
    355   switch (MO.getType()) {
    356   case MachineOperand::MO_Register:
    357     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
    358     break;
    359 
    360   case MachineOperand::MO_Immediate:
    361     O << (int)MO.getImm();
    362     break;
    363   case MachineOperand::MO_MachineBasicBlock:
    364     MO.getMBB()->getSymbol()->print(O, MAI);
    365     return;
    366   case MachineOperand::MO_GlobalAddress:
    367     getSymbol(MO.getGlobal())->print(O, MAI);
    368     break;
    369   case MachineOperand::MO_BlockAddress:
    370     O <<  GetBlockAddressSymbol(MO.getBlockAddress())->getName();
    371     break;
    372   case MachineOperand::MO_ExternalSymbol:
    373     O << MO.getSymbolName();
    374     break;
    375   case MachineOperand::MO_ConstantPoolIndex:
    376     O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
    377       << MO.getIndex();
    378     break;
    379   default:
    380     llvm_unreachable("<unknown operand type>");
    381   }
    382   if (CloseParen) O << ")";
    383 }
    384 
    385 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
    386                                       raw_ostream &O, const char *Modifier) {
    387   printOperand(MI, opNum, O);
    388 
    389   // If this is an ADD operand, emit it like normal operands.
    390   if (Modifier && !strcmp(Modifier, "arith")) {
    391     O << ", ";
    392     printOperand(MI, opNum+1, O);
    393     return;
    394   }
    395 
    396   if (MI->getOperand(opNum+1).isReg() &&
    397       MI->getOperand(opNum+1).getReg() == SP::G0)
    398     return;   // don't print "+%g0"
    399   if (MI->getOperand(opNum+1).isImm() &&
    400       MI->getOperand(opNum+1).getImm() == 0)
    401     return;   // don't print "+0"
    402 
    403   O << "+";
    404   printOperand(MI, opNum+1, O);
    405 }
    406 
    407 /// PrintAsmOperand - Print out an operand for an inline asm expression.
    408 ///
    409 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
    410                                       unsigned AsmVariant,
    411                                       const char *ExtraCode,
    412                                       raw_ostream &O) {
    413   if (ExtraCode && ExtraCode[0]) {
    414     if (ExtraCode[1] != 0) return true; // Unknown modifier.
    415 
    416     switch (ExtraCode[0]) {
    417     default:
    418       // See if this is a generic print operand
    419       return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
    420     case 'r':
    421      break;
    422     }
    423   }
    424 
    425   printOperand(MI, OpNo, O);
    426 
    427   return false;
    428 }
    429 
    430 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
    431                                             unsigned OpNo, unsigned AsmVariant,
    432                                             const char *ExtraCode,
    433                                             raw_ostream &O) {
    434   if (ExtraCode && ExtraCode[0])
    435     return true;  // Unknown modifier
    436 
    437   O << '[';
    438   printMemOperand(MI, OpNo, O);
    439   O << ']';
    440 
    441   return false;
    442 }
    443 
    444 // Force static initialization.
    445 extern "C" void LLVMInitializeSparcAsmPrinter() {
    446   RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
    447   RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target);
    448   RegisterAsmPrinter<SparcAsmPrinter> Z(TheSparcelTarget);
    449 }
    450