SparcAsmPrinter.cpp revision 0518fca843ff87d069ecb07fc00d306c1f587d58
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains a printer that converts from our internal representation 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of machine-dependent LLVM code to GAS-format SPARC assembly language. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 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 virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; 67 }; 68} // end of anonymous namespace 69 70#include "SparcGenAsmWriter.inc" 71 72void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 73 raw_ostream &O) { 74 const MachineOperand &MO = MI->getOperand (opNum); 75 bool CloseParen = false; 76 if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) { 77 O << "%hi("; 78 CloseParen = true; 79 } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) && 80 !MO.isReg() && !MO.isImm()) { 81 O << "%lo("; 82 CloseParen = true; 83 } 84 switch (MO.getType()) { 85 case MachineOperand::MO_Register: 86 O << "%" << StringRef(getRegisterName(MO.getReg())).lower(); 87 break; 88 89 case MachineOperand::MO_Immediate: 90 O << (int)MO.getImm(); 91 break; 92 case MachineOperand::MO_MachineBasicBlock: 93 O << *MO.getMBB()->getSymbol(); 94 return; 95 case MachineOperand::MO_GlobalAddress: 96 O << *Mang->getSymbol(MO.getGlobal()); 97 break; 98 case MachineOperand::MO_ExternalSymbol: 99 O << MO.getSymbolName(); 100 break; 101 case MachineOperand::MO_ConstantPoolIndex: 102 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" 103 << MO.getIndex(); 104 break; 105 default: 106 llvm_unreachable("<unknown operand type>"); 107 } 108 if (CloseParen) O << ")"; 109} 110 111void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, 112 raw_ostream &O, const char *Modifier) { 113 printOperand(MI, opNum, O); 114 115 // If this is an ADD operand, emit it like normal operands. 116 if (Modifier && !strcmp(Modifier, "arith")) { 117 O << ", "; 118 printOperand(MI, opNum+1, O); 119 return; 120 } 121 122 if (MI->getOperand(opNum+1).isReg() && 123 MI->getOperand(opNum+1).getReg() == SP::G0) 124 return; // don't print "+%g0" 125 if (MI->getOperand(opNum+1).isImm() && 126 MI->getOperand(opNum+1).getImm() == 0) 127 return; // don't print "+0" 128 129 O << "+"; 130 if (MI->getOperand(opNum+1).isGlobal() || 131 MI->getOperand(opNum+1).isCPI()) { 132 O << "%lo("; 133 printOperand(MI, opNum+1, O); 134 O << ")"; 135 } else { 136 printOperand(MI, opNum+1, O); 137 } 138} 139 140bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, 141 raw_ostream &O) { 142 std::string operand = ""; 143 const MachineOperand &MO = MI->getOperand(opNum); 144 switch (MO.getType()) { 145 default: llvm_unreachable("Operand is not a register"); 146 case MachineOperand::MO_Register: 147 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 148 "Operand is not a physical register "); 149 assert(MO.getReg() != SP::O7 && 150 "%o7 is assigned as destination for getpcx!"); 151 operand = "%" + StringRef(getRegisterName(MO.getReg())).lower(); 152 break; 153 } 154 155 unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); 156 unsigned bbNum = MI->getParent()->getNumber(); 157 158 O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; 159 O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; 160 161 O << "\t sethi\t" 162 << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum 163 << ")), " << operand << '\n' ; 164 165 O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; 166 O << "\tor\t" << operand 167 << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum 168 << ")), " << operand << '\n'; 169 O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; 170 171 return true; 172} 173 174void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, 175 raw_ostream &O) { 176 int CC = (int)MI->getOperand(opNum).getImm(); 177 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 178} 179 180/// PrintAsmOperand - Print out an operand for an inline asm expression. 181/// 182bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 183 unsigned AsmVariant, 184 const char *ExtraCode, 185 raw_ostream &O) { 186 if (ExtraCode && ExtraCode[0]) { 187 if (ExtraCode[1] != 0) return true; // Unknown modifier. 188 189 switch (ExtraCode[0]) { 190 default: 191 // See if this is a generic print operand 192 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 193 case 'r': 194 break; 195 } 196 } 197 198 printOperand(MI, OpNo, O); 199 200 return false; 201} 202 203bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 204 unsigned OpNo, unsigned AsmVariant, 205 const char *ExtraCode, 206 raw_ostream &O) { 207 if (ExtraCode && ExtraCode[0]) 208 return true; // Unknown modifier 209 210 O << '['; 211 printMemOperand(MI, OpNo, O); 212 O << ']'; 213 214 return false; 215} 216 217/// isBlockOnlyReachableByFallthough - Return true if the basic block has 218/// exactly one predecessor and the control transfer mechanism between 219/// the predecessor and this block is a fall-through. 220/// 221/// This overrides AsmPrinter's implementation to handle delay slots. 222bool SparcAsmPrinter:: 223isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 224 // If this is a landing pad, it isn't a fall through. If it has no preds, 225 // then nothing falls through to it. 226 if (MBB->isLandingPad() || MBB->pred_empty()) 227 return false; 228 229 // If there isn't exactly one predecessor, it can't be a fall through. 230 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 231 ++PI2; 232 if (PI2 != MBB->pred_end()) 233 return false; 234 235 // The predecessor has to be immediately before this block. 236 const MachineBasicBlock *Pred = *PI; 237 238 if (!Pred->isLayoutSuccessor(MBB)) 239 return false; 240 241 // Check if the last terminator is an unconditional branch. 242 MachineBasicBlock::const_iterator I = Pred->end(); 243 while (I != Pred->begin() && !(--I)->isTerminator()) 244 ; // Noop 245 return I == Pred->end() || !I->isBarrier(); 246} 247 248MachineLocation SparcAsmPrinter:: 249getDebugValueLocation(const MachineInstr *MI) const { 250 assert(MI->getNumOperands() == 4 && "Invalid number of operands!"); 251 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && 252 "Unexpected MachineOperand types"); 253 return MachineLocation(MI->getOperand(0).getReg(), 254 MI->getOperand(1).getImm()); 255} 256 257// Force static initialization. 258extern "C" void LLVMInitializeSparcAsmPrinter() { 259 RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget); 260 RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target); 261} 262