LLVM API Documentation
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 }