SparcAsmPrinter.cpp revision 5a96b3dad2f634c9081c8b2b6c2575441dc5a2bd
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#define DEBUG_TYPE "asm-printer" 16#include "Sparc.h" 17#include "SparcInstrInfo.h" 18#include "SparcTargetMachine.h" 19#include "llvm/CodeGen/AsmPrinter.h" 20#include "llvm/CodeGen/MachineInstr.h" 21#include "llvm/MC/MCAsmInfo.h" 22#include "llvm/MC/MCStreamer.h" 23#include "llvm/MC/MCSymbol.h" 24#include "llvm/Target/Mangler.h" 25#include "llvm/ADT/SmallString.h" 26#include "llvm/Support/TargetRegistry.h" 27#include "llvm/Support/raw_ostream.h" 28using namespace llvm; 29 30namespace { 31 class SparcAsmPrinter : public AsmPrinter { 32 public: 33 explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 34 : AsmPrinter(TM, Streamer) {} 35 36 virtual const char *getPassName() const { 37 return "Sparc Assembly Printer"; 38 } 39 40 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); 41 void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, 42 const char *Modifier = 0); 43 void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); 44 45 virtual void EmitInstruction(const MachineInstr *MI) { 46 SmallString<128> Str; 47 raw_svector_ostream OS(Str); 48 printInstruction(MI, OS); 49 OutStreamer.EmitRawText(OS.str()); 50 } 51 void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd. 52 static const char *getRegisterName(unsigned RegNo); 53 54 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 55 unsigned AsmVariant, const char *ExtraCode, 56 raw_ostream &O); 57 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 58 unsigned AsmVariant, const char *ExtraCode, 59 raw_ostream &O); 60 61 bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS); 62 63 virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) 64 const; 65 }; 66} // end of anonymous namespace 67 68#include "SparcGenAsmWriter.inc" 69 70void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 71 raw_ostream &O) { 72 const MachineOperand &MO = MI->getOperand (opNum); 73 bool CloseParen = false; 74 if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) { 75 O << "%hi("; 76 CloseParen = true; 77 } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) && 78 !MO.isReg() && !MO.isImm()) { 79 O << "%lo("; 80 CloseParen = true; 81 } 82 switch (MO.getType()) { 83 case MachineOperand::MO_Register: 84 O << "%" << StringRef(getRegisterName(MO.getReg())).lower(); 85 break; 86 87 case MachineOperand::MO_Immediate: 88 O << (int)MO.getImm(); 89 break; 90 case MachineOperand::MO_MachineBasicBlock: 91 O << *MO.getMBB()->getSymbol(); 92 return; 93 case MachineOperand::MO_GlobalAddress: 94 O << *Mang->getSymbol(MO.getGlobal()); 95 break; 96 case MachineOperand::MO_ExternalSymbol: 97 O << MO.getSymbolName(); 98 break; 99 case MachineOperand::MO_ConstantPoolIndex: 100 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" 101 << MO.getIndex(); 102 break; 103 default: 104 llvm_unreachable("<unknown operand type>"); 105 } 106 if (CloseParen) O << ")"; 107} 108 109void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, 110 raw_ostream &O, const char *Modifier) { 111 printOperand(MI, opNum, O); 112 113 // If this is an ADD operand, emit it like normal operands. 114 if (Modifier && !strcmp(Modifier, "arith")) { 115 O << ", "; 116 printOperand(MI, opNum+1, O); 117 return; 118 } 119 120 if (MI->getOperand(opNum+1).isReg() && 121 MI->getOperand(opNum+1).getReg() == SP::G0) 122 return; // don't print "+%g0" 123 if (MI->getOperand(opNum+1).isImm() && 124 MI->getOperand(opNum+1).getImm() == 0) 125 return; // don't print "+0" 126 127 O << "+"; 128 if (MI->getOperand(opNum+1).isGlobal() || 129 MI->getOperand(opNum+1).isCPI()) { 130 O << "%lo("; 131 printOperand(MI, opNum+1, O); 132 O << ")"; 133 } else { 134 printOperand(MI, opNum+1, O); 135 } 136} 137 138bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, 139 raw_ostream &O) { 140 std::string operand = ""; 141 const MachineOperand &MO = MI->getOperand(opNum); 142 switch (MO.getType()) { 143 default: assert(0 && "Operand is not a register "); 144 case MachineOperand::MO_Register: 145 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 146 "Operand is not a physical register "); 147 assert(MO.getReg() != SP::O7 && 148 "%o7 is assigned as destination for getpcx!"); 149 operand = "%" + StringRef(getRegisterName(MO.getReg())).lower(); 150 break; 151 } 152 153 unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); 154 unsigned bbNum = MI->getParent()->getNumber(); 155 156 O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; 157 O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; 158 159 O << "\t sethi\t" 160 << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum 161 << ")), " << operand << '\n' ; 162 163 O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; 164 O << "\tor\t" << operand 165 << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum 166 << ")), " << operand << '\n'; 167 O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; 168 169 return true; 170} 171 172void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, 173 raw_ostream &O) { 174 int CC = (int)MI->getOperand(opNum).getImm(); 175 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 176} 177 178/// PrintAsmOperand - Print out an operand for an inline asm expression. 179/// 180bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 181 unsigned AsmVariant, 182 const char *ExtraCode, 183 raw_ostream &O) { 184 if (ExtraCode && ExtraCode[0]) { 185 if (ExtraCode[1] != 0) return true; // Unknown modifier. 186 187 switch (ExtraCode[0]) { 188 default: return true; // Unknown modifier. 189 case 'r': 190 break; 191 } 192 } 193 194 printOperand(MI, OpNo, O); 195 196 return false; 197} 198 199bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 200 unsigned OpNo, unsigned AsmVariant, 201 const char *ExtraCode, 202 raw_ostream &O) { 203 if (ExtraCode && ExtraCode[0]) 204 return true; // Unknown modifier 205 206 O << '['; 207 printMemOperand(MI, OpNo, O); 208 O << ']'; 209 210 return false; 211} 212 213/// isBlockOnlyReachableByFallthough - Return true if the basic block has 214/// exactly one predecessor and the control transfer mechanism between 215/// the predecessor and this block is a fall-through. 216/// 217/// This overrides AsmPrinter's implementation to handle delay slots. 218bool SparcAsmPrinter:: 219isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 220 // If this is a landing pad, it isn't a fall through. If it has no preds, 221 // then nothing falls through to it. 222 if (MBB->isLandingPad() || MBB->pred_empty()) 223 return false; 224 225 // If there isn't exactly one predecessor, it can't be a fall through. 226 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 227 ++PI2; 228 if (PI2 != MBB->pred_end()) 229 return false; 230 231 // The predecessor has to be immediately before this block. 232 const MachineBasicBlock *Pred = *PI; 233 234 if (!Pred->isLayoutSuccessor(MBB)) 235 return false; 236 237 // Check if the last terminator is an unconditional branch. 238 MachineBasicBlock::const_iterator I = Pred->end(); 239 while (I != Pred->begin() && !(--I)->isTerminator()) 240 ; // Noop 241 return I == Pred->end() || !I->isBarrier(); 242} 243 244 245 246// Force static initialization. 247extern "C" void LLVMInitializeSparcAsmPrinter() { 248 RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget); 249 RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target); 250} 251