1218885Sdim//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file contains a printer that converts from our internal representation 11218885Sdim// of machine-dependent LLVM code to GAS-format SPARC assembly language. 12218885Sdim// 13218885Sdim//===----------------------------------------------------------------------===// 14218885Sdim 15218885Sdim#define DEBUG_TYPE "asm-printer" 16218885Sdim#include "Sparc.h" 17218885Sdim#include "SparcInstrInfo.h" 18218885Sdim#include "SparcTargetMachine.h" 19263764Sdim#include "SparcTargetStreamer.h" 20263764Sdim#include "InstPrinter/SparcInstPrinter.h" 21263764Sdim#include "MCTargetDesc/SparcMCExpr.h" 22252723Sdim#include "llvm/ADT/SmallString.h" 23218885Sdim#include "llvm/CodeGen/AsmPrinter.h" 24218885Sdim#include "llvm/CodeGen/MachineInstr.h" 25263764Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 26263509Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 27263764Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 28218885Sdim#include "llvm/MC/MCAsmInfo.h" 29263764Sdim#include "llvm/MC/MCContext.h" 30263764Sdim#include "llvm/MC/MCInst.h" 31218885Sdim#include "llvm/MC/MCStreamer.h" 32218885Sdim#include "llvm/MC/MCSymbol.h" 33226890Sdim#include "llvm/Support/TargetRegistry.h" 34218885Sdim#include "llvm/Support/raw_ostream.h" 35252723Sdim#include "llvm/Target/Mangler.h" 36218885Sdimusing namespace llvm; 37218885Sdim 38218885Sdimnamespace { 39218885Sdim class SparcAsmPrinter : public AsmPrinter { 40263764Sdim SparcTargetStreamer &getTargetStreamer() { 41263764Sdim return static_cast<SparcTargetStreamer&>(OutStreamer.getTargetStreamer()); 42263764Sdim } 43218885Sdim public: 44218885Sdim explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 45218885Sdim : AsmPrinter(TM, Streamer) {} 46218885Sdim 47218885Sdim virtual const char *getPassName() const { 48218885Sdim return "Sparc Assembly Printer"; 49218885Sdim } 50218885Sdim 51218885Sdim void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); 52218885Sdim void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, 53218885Sdim const char *Modifier = 0); 54218885Sdim void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); 55218885Sdim 56263509Sdim virtual void EmitFunctionBodyStart(); 57263764Sdim virtual void EmitInstruction(const MachineInstr *MI); 58263764Sdim virtual void EmitEndOfAsmFile(Module &M); 59263764Sdim 60263764Sdim static const char *getRegisterName(unsigned RegNo) { 61263764Sdim return SparcInstPrinter::getRegisterName(RegNo); 62218885Sdim } 63218885Sdim 64218885Sdim bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 65218885Sdim unsigned AsmVariant, const char *ExtraCode, 66218885Sdim raw_ostream &O); 67218885Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 68218885Sdim unsigned AsmVariant, const char *ExtraCode, 69218885Sdim raw_ostream &O); 70218885Sdim 71263764Sdim void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI); 72263509Sdim 73218885Sdim }; 74218885Sdim} // end of anonymous namespace 75218885Sdim 76263764Sdimstatic MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, 77263764Sdim MCSymbol *Sym, MCContext &OutContext) { 78263764Sdim const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym, 79263764Sdim OutContext); 80263764Sdim const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext); 81263764Sdim return MCOperand::CreateExpr(expr); 82218885Sdim 83263764Sdim} 84263764Sdimstatic MCOperand createPCXCallOP(MCSymbol *Label, 85263764Sdim MCContext &OutContext) { 86263764Sdim return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext); 87263764Sdim} 88263764Sdim 89263764Sdimstatic MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, 90263764Sdim MCSymbol *GOTLabel, MCSymbol *StartLabel, 91263764Sdim MCSymbol *CurLabel, 92263764Sdim MCContext &OutContext) 93263764Sdim{ 94263764Sdim const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext); 95263764Sdim const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel, 96263764Sdim OutContext); 97263764Sdim const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel, 98263764Sdim OutContext); 99263764Sdim 100263764Sdim const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext); 101263764Sdim const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext); 102263764Sdim const SparcMCExpr *expr = SparcMCExpr::Create(Kind, 103263764Sdim Add, OutContext); 104263764Sdim return MCOperand::CreateExpr(expr); 105263764Sdim} 106263764Sdim 107263764Sdimstatic void EmitCall(MCStreamer &OutStreamer, 108263764Sdim MCOperand &Callee) 109263764Sdim{ 110263764Sdim MCInst CallInst; 111263764Sdim CallInst.setOpcode(SP::CALL); 112263764Sdim CallInst.addOperand(Callee); 113263764Sdim OutStreamer.EmitInstruction(CallInst); 114263764Sdim} 115263764Sdim 116263764Sdimstatic void EmitSETHI(MCStreamer &OutStreamer, 117263764Sdim MCOperand &Imm, MCOperand &RD) 118263764Sdim{ 119263764Sdim MCInst SETHIInst; 120263764Sdim SETHIInst.setOpcode(SP::SETHIi); 121263764Sdim SETHIInst.addOperand(RD); 122263764Sdim SETHIInst.addOperand(Imm); 123263764Sdim OutStreamer.EmitInstruction(SETHIInst); 124263764Sdim} 125263764Sdim 126263764Sdimstatic void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, 127263764Sdim MCOperand &RS1, MCOperand &Src2, MCOperand &RD) 128263764Sdim{ 129263764Sdim MCInst Inst; 130263764Sdim Inst.setOpcode(Opcode); 131263764Sdim Inst.addOperand(RD); 132263764Sdim Inst.addOperand(RS1); 133263764Sdim Inst.addOperand(Src2); 134263764Sdim OutStreamer.EmitInstruction(Inst); 135263764Sdim} 136263764Sdim 137263764Sdimstatic void EmitOR(MCStreamer &OutStreamer, 138263764Sdim MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { 139263764Sdim EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD); 140263764Sdim} 141263764Sdim 142263764Sdimstatic void EmitADD(MCStreamer &OutStreamer, 143263764Sdim MCOperand &RS1, MCOperand &RS2, MCOperand &RD) { 144263764Sdim EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD); 145263764Sdim} 146263764Sdim 147263764Sdimstatic void EmitSHL(MCStreamer &OutStreamer, 148263764Sdim MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { 149263764Sdim EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD); 150263764Sdim} 151263764Sdim 152263764Sdim 153263764Sdimstatic void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, 154263764Sdim SparcMCExpr::VariantKind HiKind, 155263764Sdim SparcMCExpr::VariantKind LoKind, 156263764Sdim MCOperand &RD, 157263764Sdim MCContext &OutContext) { 158263764Sdim 159263764Sdim MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext); 160263764Sdim MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext); 161263764Sdim EmitSETHI(OutStreamer, hi, RD); 162263764Sdim EmitOR(OutStreamer, RD, lo, RD); 163263764Sdim} 164263764Sdim 165263764Sdimvoid SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI) 166263764Sdim{ 167263764Sdim MCSymbol *GOTLabel = 168263764Sdim OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); 169263764Sdim 170263764Sdim const MachineOperand &MO = MI->getOperand(0); 171263764Sdim assert(MO.getReg() != SP::O7 && 172263764Sdim "%o7 is assigned as destination for getpcx!"); 173263764Sdim 174263764Sdim MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); 175263764Sdim 176263764Sdim 177263764Sdim if (TM.getRelocationModel() != Reloc::PIC_) { 178263764Sdim // Just load the address of GOT to MCRegOP. 179263764Sdim switch(TM.getCodeModel()) { 180263764Sdim default: 181263764Sdim llvm_unreachable("Unsupported absolute code model"); 182263764Sdim case CodeModel::Small: 183263764Sdim EmitHiLo(OutStreamer, GOTLabel, 184263764Sdim SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, 185263764Sdim MCRegOP, OutContext); 186263764Sdim break; 187263764Sdim case CodeModel::Medium: { 188263764Sdim EmitHiLo(OutStreamer, GOTLabel, 189263764Sdim SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44, 190263764Sdim MCRegOP, OutContext); 191263764Sdim MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12, 192263764Sdim OutContext)); 193263764Sdim EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); 194263764Sdim MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44, 195263764Sdim GOTLabel, OutContext); 196263764Sdim EmitOR(OutStreamer, MCRegOP, lo, MCRegOP); 197263764Sdim break; 198263764Sdim } 199263764Sdim case CodeModel::Large: { 200263764Sdim EmitHiLo(OutStreamer, GOTLabel, 201263764Sdim SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM, 202263764Sdim MCRegOP, OutContext); 203263764Sdim MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32, 204263764Sdim OutContext)); 205263764Sdim EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); 206263764Sdim // Use register %o7 to load the lower 32 bits. 207263764Sdim MCOperand RegO7 = MCOperand::CreateReg(SP::O7); 208263764Sdim EmitHiLo(OutStreamer, GOTLabel, 209263764Sdim SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, 210263764Sdim RegO7, OutContext); 211263764Sdim EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); 212263764Sdim } 213263764Sdim } 214263764Sdim return; 215263764Sdim } 216263764Sdim 217263764Sdim MCSymbol *StartLabel = OutContext.CreateTempSymbol(); 218263764Sdim MCSymbol *EndLabel = OutContext.CreateTempSymbol(); 219263764Sdim MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); 220263764Sdim 221263764Sdim MCOperand RegO7 = MCOperand::CreateReg(SP::O7); 222263764Sdim 223263764Sdim // <StartLabel>: 224263764Sdim // call <EndLabel> 225263764Sdim // <SethiLabel>: 226263764Sdim // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO> 227263764Sdim // <EndLabel>: 228263764Sdim // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO> 229263764Sdim // add <MO>, %o7, <MO> 230263764Sdim 231263764Sdim OutStreamer.EmitLabel(StartLabel); 232263764Sdim MCOperand Callee = createPCXCallOP(EndLabel, OutContext); 233263764Sdim EmitCall(OutStreamer, Callee); 234263764Sdim OutStreamer.EmitLabel(SethiLabel); 235263764Sdim MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22, 236263764Sdim GOTLabel, StartLabel, SethiLabel, 237263764Sdim OutContext); 238263764Sdim EmitSETHI(OutStreamer, hiImm, MCRegOP); 239263764Sdim OutStreamer.EmitLabel(EndLabel); 240263764Sdim MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10, 241263764Sdim GOTLabel, StartLabel, EndLabel, 242263764Sdim OutContext); 243263764Sdim EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP); 244263764Sdim EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); 245263764Sdim} 246263764Sdim 247263764Sdimvoid SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) 248263764Sdim{ 249263764Sdim 250263764Sdim switch (MI->getOpcode()) { 251263764Sdim default: break; 252263764Sdim case TargetOpcode::DBG_VALUE: 253263764Sdim // FIXME: Debug Value. 254263764Sdim return; 255263764Sdim case SP::GETPCX: 256263764Sdim LowerGETPCXAndEmitMCInsts(MI); 257263764Sdim return; 258263764Sdim } 259263764Sdim MachineBasicBlock::const_instr_iterator I = MI; 260263764Sdim MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 261263764Sdim do { 262263764Sdim MCInst TmpInst; 263263764Sdim LowerSparcMachineInstrToMCInst(I, TmpInst, *this); 264263764Sdim OutStreamer.EmitInstruction(TmpInst); 265263764Sdim } while ((++I != E) && I->isInsideBundle()); // Delay slot check. 266263764Sdim} 267263764Sdim 268263509Sdimvoid SparcAsmPrinter::EmitFunctionBodyStart() { 269263509Sdim if (!TM.getSubtarget<SparcSubtarget>().is64Bit()) 270263509Sdim return; 271263509Sdim 272263509Sdim const MachineRegisterInfo &MRI = MF->getRegInfo(); 273263509Sdim const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 }; 274263509Sdim for (unsigned i = 0; globalRegs[i] != 0; ++i) { 275263509Sdim unsigned reg = globalRegs[i]; 276263509Sdim if (MRI.use_empty(reg)) 277263509Sdim continue; 278263764Sdim 279263764Sdim if (reg == SP::G6 || reg == SP::G7) 280263764Sdim getTargetStreamer().emitSparcRegisterIgnore(reg); 281263764Sdim else 282263764Sdim getTargetStreamer().emitSparcRegisterScratch(reg); 283263509Sdim } 284263509Sdim} 285263509Sdim 286218885Sdimvoid SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 287218885Sdim raw_ostream &O) { 288218885Sdim const MachineOperand &MO = MI->getOperand (opNum); 289263764Sdim SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags(); 290263764Sdim 291252723Sdim#ifndef NDEBUG 292252723Sdim // Verify the target flags. 293252723Sdim if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) { 294252723Sdim if (MI->getOpcode() == SP::CALL) 295263764Sdim assert(TF == SparcMCExpr::VK_Sparc_None && 296252723Sdim "Cannot handle target flags on call address"); 297263764Sdim else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi) 298263764Sdim assert((TF == SparcMCExpr::VK_Sparc_HI 299263764Sdim || TF == SparcMCExpr::VK_Sparc_H44 300263764Sdim || TF == SparcMCExpr::VK_Sparc_HH 301263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22 302263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22 303263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22 304263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22 305263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) && 306252723Sdim "Invalid target flags for address operand on sethi"); 307263509Sdim else if (MI->getOpcode() == SP::TLS_CALL) 308263764Sdim assert((TF == SparcMCExpr::VK_Sparc_None 309263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL 310263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) && 311263509Sdim "Cannot handle target flags on tls call address"); 312263509Sdim else if (MI->getOpcode() == SP::TLS_ADDrr) 313263764Sdim assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD 314263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD 315263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD 316263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) && 317263509Sdim "Cannot handle target flags on add for TLS"); 318263509Sdim else if (MI->getOpcode() == SP::TLS_LDrr) 319263764Sdim assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD && 320263509Sdim "Cannot handle target flags on ld for TLS"); 321263509Sdim else if (MI->getOpcode() == SP::TLS_LDXrr) 322263764Sdim assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX && 323263509Sdim "Cannot handle target flags on ldx for TLS"); 324263764Sdim else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri) 325263764Sdim assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10 326263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) && 327263509Sdim "Cannot handle target flags on xor for TLS"); 328252723Sdim else 329263764Sdim assert((TF == SparcMCExpr::VK_Sparc_LO 330263764Sdim || TF == SparcMCExpr::VK_Sparc_M44 331263764Sdim || TF == SparcMCExpr::VK_Sparc_L44 332263764Sdim || TF == SparcMCExpr::VK_Sparc_HM 333263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10 334263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10 335263764Sdim || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) && 336252723Sdim "Invalid target flags for small address operand"); 337218885Sdim } 338252723Sdim#endif 339252723Sdim 340252723Sdim 341263764Sdim bool CloseParen = SparcMCExpr::printVariantKind(O, TF); 342263764Sdim 343218885Sdim switch (MO.getType()) { 344218885Sdim case MachineOperand::MO_Register: 345235633Sdim O << "%" << StringRef(getRegisterName(MO.getReg())).lower(); 346218885Sdim break; 347218885Sdim 348218885Sdim case MachineOperand::MO_Immediate: 349218885Sdim O << (int)MO.getImm(); 350218885Sdim break; 351218885Sdim case MachineOperand::MO_MachineBasicBlock: 352218885Sdim O << *MO.getMBB()->getSymbol(); 353218885Sdim return; 354218885Sdim case MachineOperand::MO_GlobalAddress: 355263509Sdim O << *getSymbol(MO.getGlobal()); 356218885Sdim break; 357263509Sdim case MachineOperand::MO_BlockAddress: 358263509Sdim O << GetBlockAddressSymbol(MO.getBlockAddress())->getName(); 359263509Sdim break; 360218885Sdim case MachineOperand::MO_ExternalSymbol: 361218885Sdim O << MO.getSymbolName(); 362218885Sdim break; 363218885Sdim case MachineOperand::MO_ConstantPoolIndex: 364218885Sdim O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" 365218885Sdim << MO.getIndex(); 366218885Sdim break; 367218885Sdim default: 368218885Sdim llvm_unreachable("<unknown operand type>"); 369218885Sdim } 370218885Sdim if (CloseParen) O << ")"; 371218885Sdim} 372218885Sdim 373218885Sdimvoid SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, 374218885Sdim raw_ostream &O, const char *Modifier) { 375218885Sdim printOperand(MI, opNum, O); 376218885Sdim 377218885Sdim // If this is an ADD operand, emit it like normal operands. 378218885Sdim if (Modifier && !strcmp(Modifier, "arith")) { 379218885Sdim O << ", "; 380218885Sdim printOperand(MI, opNum+1, O); 381218885Sdim return; 382218885Sdim } 383218885Sdim 384218885Sdim if (MI->getOperand(opNum+1).isReg() && 385218885Sdim MI->getOperand(opNum+1).getReg() == SP::G0) 386218885Sdim return; // don't print "+%g0" 387218885Sdim if (MI->getOperand(opNum+1).isImm() && 388218885Sdim MI->getOperand(opNum+1).getImm() == 0) 389218885Sdim return; // don't print "+0" 390218885Sdim 391218885Sdim O << "+"; 392252723Sdim printOperand(MI, opNum+1, O); 393218885Sdim} 394218885Sdim 395218885Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression. 396218885Sdim/// 397218885Sdimbool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 398218885Sdim unsigned AsmVariant, 399218885Sdim const char *ExtraCode, 400218885Sdim raw_ostream &O) { 401218885Sdim if (ExtraCode && ExtraCode[0]) { 402218885Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 403218885Sdim 404218885Sdim switch (ExtraCode[0]) { 405245431Sdim default: 406245431Sdim // See if this is a generic print operand 407245431Sdim return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 408218885Sdim case 'r': 409218885Sdim break; 410218885Sdim } 411218885Sdim } 412218885Sdim 413218885Sdim printOperand(MI, OpNo, O); 414218885Sdim 415218885Sdim return false; 416218885Sdim} 417218885Sdim 418218885Sdimbool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 419218885Sdim unsigned OpNo, unsigned AsmVariant, 420218885Sdim const char *ExtraCode, 421218885Sdim raw_ostream &O) { 422218885Sdim if (ExtraCode && ExtraCode[0]) 423218885Sdim return true; // Unknown modifier 424218885Sdim 425218885Sdim O << '['; 426218885Sdim printMemOperand(MI, OpNo, O); 427218885Sdim O << ']'; 428218885Sdim 429218885Sdim return false; 430218885Sdim} 431218885Sdim 432263764Sdimvoid SparcAsmPrinter::EmitEndOfAsmFile(Module &M) { 433263764Sdim const TargetLoweringObjectFileELF &TLOFELF = 434263764Sdim static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 435263764Sdim MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 436263509Sdim 437263764Sdim // Generate stubs for global variables. 438263764Sdim MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 439263764Sdim if (!Stubs.empty()) { 440263764Sdim OutStreamer.SwitchSection(TLOFELF.getDataSection()); 441263764Sdim unsigned PtrSize = TM.getDataLayout()->getPointerSize(0); 442263764Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 443263764Sdim OutStreamer.EmitLabel(Stubs[i].first); 444263764Sdim OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize); 445263764Sdim } 446263764Sdim } 447218885Sdim} 448218885Sdim 449218885Sdim// Force static initialization. 450263509Sdimextern "C" void LLVMInitializeSparcAsmPrinter() { 451218885Sdim RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget); 452218885Sdim RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target); 453218885Sdim} 454