1 //===-- MBlazeAsmPrinter.cpp - MBlaze 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 MBlaze assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #define DEBUG_TYPE "mblaze-asm-printer" 16 17 #include "MBlaze.h" 18 #include "MBlazeSubtarget.h" 19 #include "MBlazeInstrInfo.h" 20 #include "MBlazeTargetMachine.h" 21 #include "MBlazeMachineFunction.h" 22 #include "MBlazeMCInstLower.h" 23 #include "InstPrinter/MBlazeInstPrinter.h" 24 #include "llvm/Constants.h" 25 #include "llvm/DerivedTypes.h" 26 #include "llvm/Module.h" 27 #include "llvm/CodeGen/AsmPrinter.h" 28 #include "llvm/CodeGen/MachineFunctionPass.h" 29 #include "llvm/CodeGen/MachineConstantPool.h" 30 #include "llvm/CodeGen/MachineFrameInfo.h" 31 #include "llvm/CodeGen/MachineInstr.h" 32 #include "llvm/MC/MCInst.h" 33 #include "llvm/MC/MCStreamer.h" 34 #include "llvm/MC/MCAsmInfo.h" 35 #include "llvm/MC/MCSymbol.h" 36 #include "llvm/Target/Mangler.h" 37 #include "llvm/Target/TargetData.h" 38 #include "llvm/Target/TargetLoweringObjectFile.h" 39 #include "llvm/Target/TargetMachine.h" 40 #include "llvm/Target/TargetOptions.h" 41 #include "llvm/ADT/SmallString.h" 42 #include "llvm/ADT/StringExtras.h" 43 #include "llvm/Support/ErrorHandling.h" 44 #include "llvm/Support/TargetRegistry.h" 45 #include "llvm/Support/raw_ostream.h" 46 #include <cctype> 47 48 using namespace llvm; 49 50 namespace { 51 class MBlazeAsmPrinter : public AsmPrinter { 52 const MBlazeSubtarget *Subtarget; 53 public: 54 explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 55 : AsmPrinter(TM, Streamer) { 56 Subtarget = &TM.getSubtarget<MBlazeSubtarget>(); 57 } 58 59 virtual const char *getPassName() const { 60 return "MBlaze Assembly Printer"; 61 } 62 63 void printSavedRegsBitmask(); 64 void emitFrameDirective(); 65 virtual void EmitFunctionBodyStart(); 66 virtual void EmitFunctionBodyEnd(); 67 virtual void EmitFunctionEntryLabel(); 68 69 virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) 70 const; 71 72 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 73 unsigned AsmVariant, const char *ExtraCode, 74 raw_ostream &O); 75 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); 76 void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); 77 void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O); 78 void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 79 const char *Modifier = 0); 80 81 void EmitInstruction(const MachineInstr *MI); 82 }; 83 } // end of anonymous namespace 84 85 // #include "MBlazeGenAsmWriter.inc" 86 87 //===----------------------------------------------------------------------===// 88 // 89 // MBlaze Asm Directives 90 // 91 // -- Frame directive "frame Stackpointer, Stacksize, RARegister" 92 // Describe the stack frame. 93 // 94 // -- Mask directives "mask bitmask, offset" 95 // Tells the assembler which registers are saved and where. 96 // bitmask - contain a little endian bitset indicating which registers are 97 // saved on function prologue (e.g. with a 0x80000000 mask, the 98 // assembler knows the register 31 (RA) is saved at prologue. 99 // offset - the position before stack pointer subtraction indicating where 100 // the first saved register on prologue is located. (e.g. with a 101 // 102 // Consider the following function prologue: 103 // 104 // .frame R19,48,R15 105 // .mask 0xc0000000,-8 106 // addiu R1, R1, -48 107 // sw R15, 40(R1) 108 // sw R19, 36(R1) 109 // 110 // With a 0xc0000000 mask, the assembler knows the register 15 (R15) and 111 // 19 (R19) are saved at prologue. As the save order on prologue is from 112 // left to right, R15 is saved first. A -8 offset means that after the 113 // stack pointer subtration, the first register in the mask (R15) will be 114 // saved at address 48-8=40. 115 // 116 //===----------------------------------------------------------------------===// 117 118 // Print a 32 bit hex number with all numbers. 119 static void printHex32(unsigned int Value, raw_ostream &O) { 120 O << "0x"; 121 for (int i = 7; i >= 0; i--) 122 O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); 123 } 124 125 // Create a bitmask with all callee saved registers for CPU or Floating Point 126 // registers. For CPU registers consider RA, GP and FP for saving if necessary. 127 void MBlazeAsmPrinter::printSavedRegsBitmask() { 128 const TargetFrameLowering *TFI = TM.getFrameLowering(); 129 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 130 131 // CPU Saved Registers Bitmasks 132 unsigned int CPUBitmask = 0; 133 134 // Set the CPU Bitmasks 135 const MachineFrameInfo *MFI = MF->getFrameInfo(); 136 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 137 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 138 unsigned Reg = CSI[i].getReg(); 139 unsigned RegNum = getMBlazeRegisterNumbering(Reg); 140 if (MBlaze::GPRRegisterClass->contains(Reg)) 141 CPUBitmask |= (1 << RegNum); 142 } 143 144 // Return Address and Frame registers must also be set in CPUBitmask. 145 if (TFI->hasFP(*MF)) 146 CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getFrameRegister(*MF))); 147 148 if (MFI->adjustsStack()) 149 CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getRARegister())); 150 151 // Print CPUBitmask 152 OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask)); 153 } 154 155 /// Frame Directive 156 void MBlazeAsmPrinter::emitFrameDirective() { 157 if (!OutStreamer.hasRawTextSupport()) 158 return; 159 160 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 161 unsigned stkReg = RI.getFrameRegister(*MF); 162 unsigned retReg = RI.getRARegister(); 163 unsigned stkSze = MF->getFrameInfo()->getStackSize(); 164 165 OutStreamer.EmitRawText("\t.frame\t" + 166 Twine(MBlazeInstPrinter::getRegisterName(stkReg)) + 167 "," + Twine(stkSze) + "," + 168 Twine(MBlazeInstPrinter::getRegisterName(retReg))); 169 } 170 171 void MBlazeAsmPrinter::EmitFunctionEntryLabel() { 172 if (OutStreamer.hasRawTextSupport()) 173 OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); 174 AsmPrinter::EmitFunctionEntryLabel(); 175 } 176 177 void MBlazeAsmPrinter::EmitFunctionBodyStart() { 178 if (!OutStreamer.hasRawTextSupport()) 179 return; 180 181 emitFrameDirective(); 182 printSavedRegsBitmask(); 183 } 184 185 void MBlazeAsmPrinter::EmitFunctionBodyEnd() { 186 if (OutStreamer.hasRawTextSupport()) 187 OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); 188 } 189 190 //===----------------------------------------------------------------------===// 191 void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { 192 MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this); 193 194 MCInst TmpInst; 195 MCInstLowering.Lower(MI, TmpInst); 196 OutStreamer.EmitInstruction(TmpInst); 197 } 198 199 // Print out an operand for an inline asm expression. 200 bool MBlazeAsmPrinter:: 201 PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 202 unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { 203 // Does this asm operand have a single letter operand modifier? 204 if (ExtraCode && ExtraCode[0]) 205 return true; // Unknown modifier. 206 207 printOperand(MI, OpNo, O); 208 return false; 209 } 210 211 void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 212 raw_ostream &O) { 213 const MachineOperand &MO = MI->getOperand(opNum); 214 215 switch (MO.getType()) { 216 case MachineOperand::MO_Register: 217 O << MBlazeInstPrinter::getRegisterName(MO.getReg()); 218 break; 219 220 case MachineOperand::MO_Immediate: 221 O << (int32_t)MO.getImm(); 222 break; 223 224 case MachineOperand::MO_FPImmediate: { 225 const ConstantFP *fp = MO.getFPImm(); 226 printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O); 227 O << ";\t# immediate = " << *fp; 228 break; 229 } 230 231 case MachineOperand::MO_MachineBasicBlock: 232 O << *MO.getMBB()->getSymbol(); 233 return; 234 235 case MachineOperand::MO_GlobalAddress: 236 O << *Mang->getSymbol(MO.getGlobal()); 237 break; 238 239 case MachineOperand::MO_ExternalSymbol: 240 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 241 break; 242 243 case MachineOperand::MO_JumpTableIndex: 244 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 245 << '_' << MO.getIndex(); 246 break; 247 248 case MachineOperand::MO_ConstantPoolIndex: 249 O << MAI->getPrivateGlobalPrefix() << "CPI" 250 << getFunctionNumber() << "_" << MO.getIndex(); 251 if (MO.getOffset()) 252 O << "+" << MO.getOffset(); 253 break; 254 255 default: 256 llvm_unreachable("<unknown operand type>"); 257 } 258 } 259 260 void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, 261 raw_ostream &O) { 262 const MachineOperand &MO = MI->getOperand(opNum); 263 if (MO.isImm()) 264 O << (uint32_t)MO.getImm(); 265 else 266 printOperand(MI, opNum, O); 267 } 268 269 void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum, 270 raw_ostream &O) { 271 const MachineOperand &MO = MI->getOperand(opNum); 272 if (MO.isImm()) 273 O << "rfsl" << (unsigned int)MO.getImm(); 274 else 275 printOperand(MI, opNum, O); 276 } 277 278 void MBlazeAsmPrinter:: 279 printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 280 const char *Modifier) { 281 printOperand(MI, opNum, O); 282 O << ", "; 283 printOperand(MI, opNum+1, O); 284 } 285 286 /// isBlockOnlyReachableByFallthough - Return true if the basic block has 287 /// exactly one predecessor and the control transfer mechanism between 288 /// the predecessor and this block is a fall-through. 289 bool MBlazeAsmPrinter:: 290 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 291 // If this is a landing pad, it isn't a fall through. If it has no preds, 292 // then nothing falls through to it. 293 if (MBB->isLandingPad() || MBB->pred_empty()) 294 return false; 295 296 // If there isn't exactly one predecessor, it can't be a fall through. 297 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 298 ++PI2; 299 if (PI2 != MBB->pred_end()) 300 return false; 301 302 // The predecessor has to be immediately before this block. 303 const MachineBasicBlock *Pred = *PI; 304 305 if (!Pred->isLayoutSuccessor(MBB)) 306 return false; 307 308 // If the block is completely empty, then it definitely does fall through. 309 if (Pred->empty()) 310 return true; 311 312 // Check if the last terminator is an unconditional branch. 313 MachineBasicBlock::const_iterator I = Pred->end(); 314 while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) 315 ; // Noop 316 return I == Pred->end() || !I->getDesc().isBarrier(); 317 } 318 319 // Force static initialization. 320 extern "C" void LLVMInitializeMBlazeAsmPrinter() { 321 RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget); 322 } 323