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