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