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