MipsAsmPrinter.cpp revision aa08ea0530a2baa7d1d74c492b1bd5af3518ad60
1//===-- MipsAsmPrinter.cpp - Mips 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 MIPS assembly language. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "mips-asm-printer" 16#include "MipsAsmPrinter.h" 17#include "Mips.h" 18#include "MipsInstrInfo.h" 19#include "MipsMachineFunction.h" 20#include "llvm/BasicBlock.h" 21#include "llvm/Instructions.h" 22#include "llvm/CodeGen/MachineFunctionPass.h" 23#include "llvm/CodeGen/MachineConstantPool.h" 24#include "llvm/CodeGen/MachineFrameInfo.h" 25#include "llvm/CodeGen/MachineInstr.h" 26#include "llvm/MC/MCStreamer.h" 27#include "llvm/MC/MCAsmInfo.h" 28#include "llvm/MC/MCSymbol.h" 29#include "llvm/Target/Mangler.h" 30#include "llvm/Target/TargetData.h" 31#include "llvm/Target/TargetLoweringObjectFile.h" 32#include "llvm/Target/TargetOptions.h" 33#include "llvm/Target/TargetRegistry.h" 34#include "llvm/ADT/SmallString.h" 35#include "llvm/ADT/StringExtras.h" 36#include "llvm/ADT/Twine.h" 37#include "llvm/Support/raw_ostream.h" 38#include "llvm/Analysis/DebugInfo.h" 39 40using namespace llvm; 41 42#include "MipsGenAsmWriter.inc" 43 44void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { 45 SmallString<128> Str; 46 raw_svector_ostream OS(Str); 47 48 if (MI->isDebugValue()) { 49 PrintDebugValueComment(MI, OS); 50 return; 51 } 52 53 printInstruction(MI, OS); 54 OutStreamer.EmitRawText(OS.str()); 55} 56 57//===----------------------------------------------------------------------===// 58// 59// Mips Asm Directives 60// 61// -- Frame directive "frame Stackpointer, Stacksize, RARegister" 62// Describe the stack frame. 63// 64// -- Mask directives "(f)mask bitmask, offset" 65// Tells the assembler which registers are saved and where. 66// bitmask - contain a little endian bitset indicating which registers are 67// saved on function prologue (e.g. with a 0x80000000 mask, the 68// assembler knows the register 31 (RA) is saved at prologue. 69// offset - the position before stack pointer subtraction indicating where 70// the first saved register on prologue is located. (e.g. with a 71// 72// Consider the following function prologue: 73// 74// .frame $fp,48,$ra 75// .mask 0xc0000000,-8 76// addiu $sp, $sp, -48 77// sw $ra, 40($sp) 78// sw $fp, 36($sp) 79// 80// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and 81// 30 (FP) are saved at prologue. As the save order on prologue is from 82// left to right, RA is saved first. A -8 offset means that after the 83// stack pointer subtration, the first register in the mask (RA) will be 84// saved at address 48-8=40. 85// 86//===----------------------------------------------------------------------===// 87 88//===----------------------------------------------------------------------===// 89// Mask directives 90//===----------------------------------------------------------------------===// 91 92// Create a bitmask with all callee saved registers for CPU or Floating Point 93// registers. For CPU registers consider RA, GP and FP for saving if necessary. 94void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { 95 // CPU and FPU Saved Registers Bitmasks 96 unsigned CPUBitmask = 0, FPUBitmask = 0; 97 int CPUTopSavedRegOff, FPUTopSavedRegOff; 98 99 // Set the CPU and FPU Bitmasks 100 const MachineFrameInfo *MFI = MF->getFrameInfo(); 101 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 102 // size of stack area to which FP callee-saved regs are saved. 103 unsigned CPURegSize = Mips::CPURegsRegisterClass->getSize(); 104 unsigned FGR32RegSize = Mips::FGR32RegisterClass->getSize(); 105 unsigned AFGR64RegSize = Mips::AFGR64RegisterClass->getSize(); 106 bool HasAFGR64Reg = false; 107 unsigned CSFPRegsSize = 0; 108 unsigned i, e = CSI.size(); 109 110 // Set FPU Bitmask. 111 for (i = 0; i != e; ++i) { 112 unsigned Reg = CSI[i].getReg(); 113 if (Mips::CPURegsRegisterClass->contains(Reg)) 114 break; 115 116 unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); 117 if (Mips::AFGR64RegisterClass->contains(Reg)) { 118 FPUBitmask |= (3 << RegNum); 119 CSFPRegsSize += AFGR64RegSize; 120 HasAFGR64Reg = true; 121 continue; 122 } 123 124 FPUBitmask |= (1 << RegNum); 125 CSFPRegsSize += FGR32RegSize; 126 } 127 128 // Set CPU Bitmask. 129 for (; i != e; ++i) { 130 unsigned Reg = CSI[i].getReg(); 131 unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); 132 CPUBitmask |= (1 << RegNum); 133 } 134 135 // FP Regs are saved right below where the virtual frame pointer points to. 136 FPUTopSavedRegOff = FPUBitmask ? 137 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; 138 139 // CPU Regs are saved below FP Regs. 140 CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; 141 142 // Print CPUBitmask 143 O << "\t.mask \t"; printHex32(CPUBitmask, O); 144 O << ',' << CPUTopSavedRegOff << '\n'; 145 146 // Print FPUBitmask 147 O << "\t.fmask\t"; printHex32(FPUBitmask, O); 148 O << "," << FPUTopSavedRegOff << '\n'; 149} 150 151// Print a 32 bit hex number with all numbers. 152void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { 153 O << "0x"; 154 for (int i = 7; i >= 0; i--) 155 O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); 156} 157 158//===----------------------------------------------------------------------===// 159// Frame and Set directives 160//===----------------------------------------------------------------------===// 161 162/// Frame Directive 163void MipsAsmPrinter::emitFrameDirective() { 164 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 165 166 unsigned stackReg = RI.getFrameRegister(*MF); 167 unsigned returnReg = RI.getRARegister(); 168 unsigned stackSize = MF->getFrameInfo()->getStackSize(); 169 170 OutStreamer.EmitRawText("\t.frame\t$" + 171 Twine(LowercaseString(getRegisterName(stackReg))) + 172 "," + Twine(stackSize) + ",$" + 173 Twine(LowercaseString(getRegisterName(returnReg)))); 174} 175 176/// Emit Set directives. 177const char *MipsAsmPrinter::getCurrentABIString() const { 178 switch (Subtarget->getTargetABI()) { 179 case MipsSubtarget::O32: return "abi32"; 180 case MipsSubtarget::O64: return "abiO64"; 181 case MipsSubtarget::N32: return "abiN32"; 182 case MipsSubtarget::N64: return "abi64"; 183 case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 184 default: break; 185 } 186 187 llvm_unreachable("Unknown Mips ABI"); 188 return NULL; 189} 190 191void MipsAsmPrinter::EmitFunctionEntryLabel() { 192 OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); 193 OutStreamer.EmitLabel(CurrentFnSym); 194} 195 196/// EmitFunctionBodyStart - Targets can override this to emit stuff before 197/// the first basic block in the function. 198void MipsAsmPrinter::EmitFunctionBodyStart() { 199 emitFrameDirective(); 200 201 SmallString<128> Str; 202 raw_svector_ostream OS(Str); 203 printSavedRegsBitmask(OS); 204 OutStreamer.EmitRawText(OS.str()); 205} 206 207/// EmitFunctionBodyEnd - Targets can override this to emit stuff after 208/// the last basic block in the function. 209void MipsAsmPrinter::EmitFunctionBodyEnd() { 210 // There are instruction for this macros, but they must 211 // always be at the function end, and we can't emit and 212 // break with BB logic. 213 OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); 214 OutStreamer.EmitRawText(StringRef("\t.set\treorder")); 215 OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); 216} 217 218 219/// isBlockOnlyReachableByFallthough - Return true if the basic block has 220/// exactly one predecessor and the control transfer mechanism between 221/// the predecessor and this block is a fall-through. 222bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* 223 MBB) const { 224 // The predecessor has to be immediately before this block. 225 const MachineBasicBlock *Pred = *MBB->pred_begin(); 226 227 // If the predecessor is a switch statement, assume a jump table 228 // implementation, so it is not a fall through. 229 if (const BasicBlock *bb = Pred->getBasicBlock()) 230 if (isa<SwitchInst>(bb->getTerminator())) 231 return false; 232 233 // If this is a landing pad, it isn't a fall through. If it has no preds, 234 // then nothing falls through to it. 235 if (MBB->isLandingPad() || MBB->pred_empty()) 236 return false; 237 238 // If there isn't exactly one predecessor, it can't be a fall through. 239 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 240 ++PI2; 241 242 if (PI2 != MBB->pred_end()) 243 return false; 244 245 // The predecessor has to be immediately before this block. 246 if (!Pred->isLayoutSuccessor(MBB)) 247 return false; 248 249 // If the block is completely empty, then it definitely does fall through. 250 if (Pred->empty()) 251 return true; 252 253 // Otherwise, check the last instruction. 254 // Check if the last terminator is an unconditional branch. 255 MachineBasicBlock::const_iterator I = Pred->end(); 256 while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) ; 257 258 return !I->getDesc().isBarrier(); 259} 260 261// Print out an operand for an inline asm expression. 262bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 263 unsigned AsmVariant,const char *ExtraCode, 264 raw_ostream &O) { 265 // Does this asm operand have a single letter operand modifier? 266 if (ExtraCode && ExtraCode[0]) 267 return true; // Unknown modifier. 268 269 printOperand(MI, OpNo, O); 270 return false; 271} 272 273bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 274 unsigned OpNum, unsigned AsmVariant, 275 const char *ExtraCode, 276 raw_ostream &O) { 277 if (ExtraCode && ExtraCode[0]) 278 return true; // Unknown modifier. 279 280 const MachineOperand &MO = MI->getOperand(OpNum); 281 assert(MO.isReg() && "unexpected inline asm memory operand"); 282 O << "0($" << MipsAsmPrinter::getRegisterName(MO.getReg()) << ")"; 283 return false; 284} 285 286void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 287 raw_ostream &O) { 288 const MachineOperand &MO = MI->getOperand(opNum); 289 bool closeP = false; 290 291 if (MO.getTargetFlags()) 292 closeP = true; 293 294 switch(MO.getTargetFlags()) { 295 case MipsII::MO_GPREL: O << "%gp_rel("; break; 296 case MipsII::MO_GOT_CALL: O << "%call16("; break; 297 case MipsII::MO_GOT: O << "%got("; break; 298 case MipsII::MO_ABS_HI: O << "%hi("; break; 299 case MipsII::MO_ABS_LO: O << "%lo("; break; 300 case MipsII::MO_TLSGD: O << "%tlsgd("; break; 301 case MipsII::MO_GOTTPREL: O << "%gottprel("; break; 302 case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; 303 case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; 304 } 305 306 switch (MO.getType()) { 307 case MachineOperand::MO_Register: 308 O << '$' << LowercaseString(getRegisterName(MO.getReg())); 309 break; 310 311 case MachineOperand::MO_Immediate: 312 O << MO.getImm(); 313 break; 314 315 case MachineOperand::MO_MachineBasicBlock: 316 O << *MO.getMBB()->getSymbol(); 317 return; 318 319 case MachineOperand::MO_GlobalAddress: 320 O << *Mang->getSymbol(MO.getGlobal()); 321 break; 322 323 case MachineOperand::MO_BlockAddress: { 324 MCSymbol* BA = GetBlockAddressSymbol(MO.getBlockAddress()); 325 O << BA->getName(); 326 break; 327 } 328 329 case MachineOperand::MO_ExternalSymbol: 330 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 331 break; 332 333 case MachineOperand::MO_JumpTableIndex: 334 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 335 << '_' << MO.getIndex(); 336 break; 337 338 case MachineOperand::MO_ConstantPoolIndex: 339 O << MAI->getPrivateGlobalPrefix() << "CPI" 340 << getFunctionNumber() << "_" << MO.getIndex(); 341 if (MO.getOffset()) 342 O << "+" << MO.getOffset(); 343 break; 344 345 default: 346 llvm_unreachable("<unknown operand type>"); 347 } 348 349 if (closeP) O << ")"; 350} 351 352void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, 353 raw_ostream &O) { 354 const MachineOperand &MO = MI->getOperand(opNum); 355 if (MO.isImm()) 356 O << (unsigned short int)MO.getImm(); 357 else 358 printOperand(MI, opNum, O); 359} 360 361void MipsAsmPrinter:: 362printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 363 const char *Modifier) { 364 // when using stack locations for not load/store instructions 365 // print the same way as all normal 3 operand instructions. 366 if (Modifier && !strcmp(Modifier, "stackloc")) { 367 printOperand(MI, opNum, O); 368 O << ", "; 369 printOperand(MI, opNum+1, O); 370 return; 371 } 372 373 // Load/Store memory operands -- imm($reg) 374 // If PIC target the target is loaded as the 375 // pattern lw $25,%call16($28) 376 printOperand(MI, opNum+1, O); 377 O << "("; 378 printOperand(MI, opNum, O); 379 O << ")"; 380} 381 382void MipsAsmPrinter:: 383printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 384 const char *Modifier) { 385 const MachineOperand& MO = MI->getOperand(opNum); 386 O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); 387} 388 389void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { 390 // FIXME: Use SwitchSection. 391 392 // Tell the assembler which ABI we are using 393 OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); 394 395 // TODO: handle O64 ABI 396 if (Subtarget->isABI_EABI()) { 397 if (Subtarget->isGP32bit()) 398 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); 399 else 400 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); 401 } 402 403 // return to previous section 404 OutStreamer.EmitRawText(StringRef("\t.previous")); 405} 406 407MachineLocation 408MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { 409 // Handles frame addresses emitted in MipsInstrInfo::emitFrameIndexDebugValue. 410 assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 411 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && 412 "Unexpected MachineOperand types"); 413 return MachineLocation(MI->getOperand(0).getReg(), 414 MI->getOperand(1).getImm()); 415} 416 417void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 418 raw_ostream &OS) { 419 // TODO: implement 420} 421 422// Force static initialization. 423extern "C" void LLVMInitializeMipsAsmPrinter() { 424 RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); 425 RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget); 426} 427