| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 1 | //===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 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 |  | 
|  | 17 | #include "Mips.h" | 
|  | 18 | #include "MipsInstrInfo.h" | 
|  | 19 | #include "MipsTargetMachine.h" | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 20 | #include "MipsMachineFunction.h" | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 21 | #include "llvm/Constants.h" | 
|  | 22 | #include "llvm/DerivedTypes.h" | 
|  | 23 | #include "llvm/Module.h" | 
|  | 24 | #include "llvm/CodeGen/AsmPrinter.h" | 
|  | 25 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | 26 | #include "llvm/CodeGen/MachineConstantPool.h" | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 27 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 28 | #include "llvm/CodeGen/MachineInstr.h" | 
|  | 29 | #include "llvm/Target/TargetAsmInfo.h" | 
|  | 30 | #include "llvm/Target/TargetData.h" | 
|  | 31 | #include "llvm/Target/TargetMachine.h" | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 32 | #include "llvm/Target/TargetOptions.h" | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 33 | #include "llvm/Support/Mangler.h" | 
|  | 34 | #include "llvm/ADT/Statistic.h" | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 35 | #include "llvm/ADT/SetVector.h" | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 36 | #include "llvm/ADT/StringExtras.h" | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 37 | #include "llvm/Support/Debug.h" | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 38 | #include "llvm/Support/CommandLine.h" | 
|  | 39 | #include "llvm/Support/MathExtras.h" | 
|  | 40 | #include <cctype> | 
|  | 41 |  | 
|  | 42 | using namespace llvm; | 
|  | 43 |  | 
|  | 44 | STATISTIC(EmittedInsts, "Number of machine instrs printed"); | 
|  | 45 |  | 
|  | 46 | namespace { | 
|  | 47 | struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter { | 
|  | 48 | MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM, | 
|  | 49 | const TargetAsmInfo *T): | 
|  | 50 | AsmPrinter(O, TM, T) {} | 
|  | 51 |  | 
|  | 52 | virtual const char *getPassName() const { | 
|  | 53 | return "Mips Assembly Printer"; | 
|  | 54 | } | 
|  | 55 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 56 | enum SetDirectiveFlags { | 
|  | 57 | REORDER,      // enables instruction reordering. | 
|  | 58 | NOREORDER,    // disables instruction reordering. | 
|  | 59 | MACRO,        // enables GAS macros. | 
|  | 60 | NOMACRO       // disables GAS macros. | 
|  | 61 | }; | 
|  | 62 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 63 | void printOperand(const MachineInstr *MI, int opNum); | 
|  | 64 | void printMemOperand(const MachineInstr *MI, int opNum, | 
|  | 65 | const char *Modifier = 0); | 
|  | 66 |  | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 67 | unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF); | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 68 | void printHex32(unsigned int Value); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 69 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 70 | void emitFunctionStart(MachineFunction &MF); | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 71 | void emitFunctionEnd(MachineFunction &MF); | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 72 | void emitFrameDirective(MachineFunction &MF); | 
|  | 73 | void emitMaskDirective(MachineFunction &MF); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 74 | void emitFMaskDirective(MachineFunction &MF); | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 75 | void emitSetDirective(SetDirectiveFlags Flag); | 
|  | 76 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 77 | bool printInstruction(const MachineInstr *MI);  // autogenerated. | 
|  | 78 | bool runOnMachineFunction(MachineFunction &F); | 
|  | 79 | bool doInitialization(Module &M); | 
|  | 80 | bool doFinalization(Module &M); | 
|  | 81 | }; | 
|  | 82 | } // end of anonymous namespace | 
|  | 83 |  | 
|  | 84 | #include "MipsGenAsmWriter.inc" | 
|  | 85 |  | 
|  | 86 | /// createMipsCodePrinterPass - Returns a pass that prints the MIPS | 
|  | 87 | /// assembly code for a MachineFunction to the given output stream, | 
|  | 88 | /// using the given target machine description.  This should work | 
|  | 89 | /// regardless of whether the function is in SSA form. | 
|  | 90 | FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o, | 
|  | 91 | MipsTargetMachine &tm) | 
|  | 92 | { | 
|  | 93 | return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo()); | 
|  | 94 | } | 
|  | 95 |  | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 96 | //===----------------------------------------------------------------------===// | 
|  | 97 | // | 
|  | 98 | //  Mips Asm Directives | 
|  | 99 | // | 
|  | 100 | //  -- Frame directive "frame Stackpointer, Stacksize, RARegister" | 
|  | 101 | //  Describe the stack frame. | 
|  | 102 | // | 
|  | 103 | //  -- Mask directives "(f)mask  bitmask, offset" | 
|  | 104 | //  Tells the assembler which registers are saved and where. | 
|  | 105 | //  bitmask - contain a little endian bitset indicating which registers are | 
|  | 106 | //            saved on function prologue (e.g. with a 0x80000000 mask, the | 
|  | 107 | //            assembler knows the register 31 (RA) is saved at prologue. | 
|  | 108 | //  offset  - the position before stack pointer subtraction indicating where | 
|  | 109 | //            the first saved register on prologue is located. (e.g. with a | 
|  | 110 | // | 
|  | 111 | //  Consider the following function prologue: | 
|  | 112 | // | 
| Bill Wendling | 97925ec | 2008-02-27 06:33:05 +0000 | [diff] [blame] | 113 | //    .frame  $fp,48,$ra | 
|  | 114 | //    .mask   0xc0000000,-8 | 
|  | 115 | //       addiu $sp, $sp, -48 | 
|  | 116 | //       sw $ra, 40($sp) | 
|  | 117 | //       sw $fp, 36($sp) | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 118 | // | 
|  | 119 | //    With a 0xc0000000 mask, the assembler knows the register 31 (RA) and | 
|  | 120 | //    30 (FP) are saved at prologue. As the save order on prologue is from | 
|  | 121 | //    left to right, RA is saved first. A -8 offset means that after the | 
|  | 122 | //    stack pointer subtration, the first register in the mask (RA) will be | 
|  | 123 | //    saved at address 48-8=40. | 
|  | 124 | // | 
|  | 125 | //===----------------------------------------------------------------------===// | 
|  | 126 |  | 
|  | 127 | /// Mask directive for GPR | 
|  | 128 | void MipsAsmPrinter:: | 
|  | 129 | emitMaskDirective(MachineFunction &MF) | 
|  | 130 | { | 
|  | 131 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); | 
|  | 132 |  | 
|  | 133 | int StackSize = MF.getFrameInfo()->getStackSize(); | 
|  | 134 | int Offset    = (!MipsFI->getTopSavedRegOffset()) ? 0 : | 
|  | 135 | (-(StackSize-MipsFI->getTopSavedRegOffset())); | 
|  | 136 |  | 
|  | 137 | #ifndef NDEBUG | 
|  | 138 | DOUT << "--> emitMaskDirective" << "\n"; | 
|  | 139 | DOUT << "StackSize :  " << StackSize << "\n"; | 
|  | 140 | DOUT << "getTopSavedReg : " << MipsFI->getTopSavedRegOffset() << "\n"; | 
|  | 141 | DOUT << "Offset : " << Offset << "\n\n"; | 
|  | 142 | #endif | 
|  | 143 |  | 
|  | 144 | unsigned int Bitmask = getSavedRegsBitmask(false, MF); | 
| Bruno Cardoso Lopes | 6d5ada2 | 2007-09-24 20:15:11 +0000 | [diff] [blame] | 145 | O << "\t.mask \t"; | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 146 | printHex32(Bitmask); | 
|  | 147 | O << "," << Offset << "\n"; | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | /// TODO: Mask Directive for Float Point | 
|  | 151 | void MipsAsmPrinter:: | 
|  | 152 | emitFMaskDirective(MachineFunction &MF) | 
|  | 153 | { | 
|  | 154 | unsigned int Bitmask = getSavedRegsBitmask(true, MF); | 
|  | 155 |  | 
|  | 156 | O << "\t.fmask\t"; | 
|  | 157 | printHex32(Bitmask); | 
|  | 158 | O << ",0" << "\n"; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | /// Frame Directive | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 162 | void MipsAsmPrinter:: | 
|  | 163 | emitFrameDirective(MachineFunction &MF) | 
|  | 164 | { | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 165 | const TargetRegisterInfo &RI = *TM.getRegisterInfo(); | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 166 |  | 
|  | 167 | unsigned stackReg  = RI.getFrameRegister(MF); | 
|  | 168 | unsigned returnReg = RI.getRARegister(); | 
|  | 169 | unsigned stackSize = MF.getFrameInfo()->getStackSize(); | 
|  | 170 |  | 
|  | 171 |  | 
| Bill Wendling | c24ea4f | 2008-02-26 21:11:01 +0000 | [diff] [blame] | 172 | O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName) | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 173 | << "," << stackSize << "," | 
| Bill Wendling | c24ea4f | 2008-02-26 21:11:01 +0000 | [diff] [blame] | 174 | << "$" << LowercaseString(RI.get(returnReg).AsmName) | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 175 | << "\n"; | 
|  | 176 | } | 
|  | 177 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 178 | /// Emit Set directives. | 
|  | 179 | void MipsAsmPrinter:: | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 180 | emitSetDirective(SetDirectiveFlags Flag) | 
|  | 181 | { | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 182 | O << "\t.set\t"; | 
|  | 183 | switch(Flag) { | 
|  | 184 | case REORDER:   O << "reorder" << "\n"; break; | 
|  | 185 | case NOREORDER: O << "noreorder" << "\n"; break; | 
|  | 186 | case MACRO:     O << "macro" << "\n"; break; | 
|  | 187 | case NOMACRO:   O << "nomacro" << "\n"; break; | 
|  | 188 | default: break; | 
|  | 189 | } | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
|  | 192 | // Create a bitmask with all callee saved registers for CPU | 
|  | 193 | // or Float Point registers. For CPU registers consider RA, | 
|  | 194 | // GP and FP for saving if necessary. | 
|  | 195 | unsigned int MipsAsmPrinter:: | 
|  | 196 | getSavedRegsBitmask(bool isFloat, MachineFunction &MF) | 
|  | 197 | { | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 198 | const TargetRegisterInfo &RI = *TM.getRegisterInfo(); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 199 |  | 
|  | 200 | // Float Point Registers, TODO | 
|  | 201 | if (isFloat) | 
|  | 202 | return 0; | 
|  | 203 |  | 
|  | 204 | // CPU Registers | 
|  | 205 | unsigned int Bitmask = 0; | 
|  | 206 |  | 
|  | 207 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | 208 | const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); | 
|  | 209 | for (unsigned i = 0, e = CSI.size(); i != e; ++i) | 
|  | 210 | Bitmask |= (1 << MipsRegisterInfo::getRegisterNumbering(CSI[i].getReg())); | 
|  | 211 |  | 
|  | 212 | if (RI.hasFP(MF)) | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 213 | Bitmask |= (1 << MipsRegisterInfo:: | 
|  | 214 | getRegisterNumbering(RI.getFrameRegister(MF))); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 215 |  | 
|  | 216 | if (MF.getFrameInfo()->hasCalls()) | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 217 | Bitmask |= (1 << MipsRegisterInfo:: | 
|  | 218 | getRegisterNumbering(RI.getRARegister())); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 219 |  | 
|  | 220 | return Bitmask; | 
|  | 221 | } | 
|  | 222 |  | 
|  | 223 | // Print a 32 bit hex number with all numbers. | 
|  | 224 | void MipsAsmPrinter:: | 
|  | 225 | printHex32(unsigned int Value) | 
|  | 226 | { | 
|  | 227 | O << "0x" << std::hex; | 
|  | 228 | for (int i = 7; i >= 0; i--) | 
|  | 229 | O << std::hex << ( (Value & (0xF << (i*4))) >> (i*4) ); | 
|  | 230 | O << std::dec; | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 231 | } | 
|  | 232 |  | 
|  | 233 | /// Emit the directives used by GAS on the start of functions | 
|  | 234 | void MipsAsmPrinter:: | 
|  | 235 | emitFunctionStart(MachineFunction &MF) | 
|  | 236 | { | 
|  | 237 | // Print out the label for the function. | 
|  | 238 | const Function *F = MF.getFunction(); | 
|  | 239 | SwitchToTextSection(getSectionForFunction(*F).c_str(), F); | 
|  | 240 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 241 | // 2 bits aligned | 
|  | 242 | EmitAlignment(2, F); | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 243 |  | 
|  | 244 | O << "\t.globl\t"  << CurrentFnName << "\n"; | 
|  | 245 | O << "\t.ent\t"    << CurrentFnName << "\n"; | 
|  | 246 | O << "\t.type\t"   << CurrentFnName << ", @function\n"; | 
|  | 247 | O << CurrentFnName << ":\n"; | 
|  | 248 |  | 
|  | 249 | emitFrameDirective(MF); | 
|  | 250 | emitMaskDirective(MF); | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 251 | emitFMaskDirective(MF); | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 252 |  | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 253 | if (TM.getRelocationModel() == Reloc::Static) { | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 254 | emitSetDirective(NOREORDER); | 
|  | 255 | emitSetDirective(NOMACRO); | 
|  | 256 | } | 
|  | 257 |  | 
| Bruno Cardoso Lopes | 833a1f9 | 2007-08-18 02:05:24 +0000 | [diff] [blame] | 258 | O << "\n"; | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 259 | } | 
|  | 260 |  | 
|  | 261 | /// Emit the directives used by GAS on the end of functions | 
|  | 262 | void MipsAsmPrinter:: | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 263 | emitFunctionEnd(MachineFunction &MF) | 
|  | 264 | { | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 265 | if (TM.getRelocationModel() == Reloc::Static) { | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 266 | emitSetDirective(MACRO); | 
|  | 267 | emitSetDirective(REORDER); | 
|  | 268 | } | 
|  | 269 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 270 | O << "\t.end\t" << CurrentFnName << "\n"; | 
|  | 271 | } | 
|  | 272 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 273 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 274 | /// method to print assembly for each instruction. | 
|  | 275 | bool MipsAsmPrinter:: | 
|  | 276 | runOnMachineFunction(MachineFunction &MF) | 
|  | 277 | { | 
|  | 278 | SetupMachineFunction(MF); | 
|  | 279 |  | 
|  | 280 | // Print out constants referenced by the function | 
|  | 281 | EmitConstantPool(MF.getConstantPool()); | 
|  | 282 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 283 | // Print out jump tables referenced by the function | 
|  | 284 | EmitJumpTableInfo(MF.getJumpTableInfo(), MF); | 
|  | 285 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 286 | O << "\n\n"; | 
|  | 287 |  | 
|  | 288 | // What's my mangled name? | 
|  | 289 | CurrentFnName = Mang->getValueName(MF.getFunction()); | 
|  | 290 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 291 | // Emit the function start directives | 
|  | 292 | emitFunctionStart(MF); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 293 |  | 
|  | 294 | // Print out code for the function. | 
|  | 295 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 296 | I != E; ++I) { | 
|  | 297 |  | 
|  | 298 | // Print a label for the basic block. | 
|  | 299 | if (I != MF.begin()) { | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 300 | printBasicBlockLabel(I, true, true); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 301 | O << '\n'; | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
|  | 305 | II != E; ++II) { | 
|  | 306 | // Print the assembly for the instruction. | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 307 | printInstruction(II); | 
|  | 308 | ++EmittedInsts; | 
|  | 309 | } | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 310 |  | 
|  | 311 | // Each Basic Block is separated by a newline | 
|  | 312 | O << '\n'; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 313 | } | 
|  | 314 |  | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 315 | // Emit function end directives | 
| Bruno Cardoso Lopes | 35d86e6 | 2007-10-09 03:01:19 +0000 | [diff] [blame] | 316 | emitFunctionEnd(MF); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 317 |  | 
|  | 318 | // We didn't modify anything. | 
|  | 319 | return false; | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | void MipsAsmPrinter:: | 
|  | 323 | printOperand(const MachineInstr *MI, int opNum) | 
|  | 324 | { | 
|  | 325 | const MachineOperand &MO = MI->getOperand(opNum); | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 326 | const TargetRegisterInfo  &RI = *TM.getRegisterInfo(); | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 327 | bool closeP = false; | 
|  | 328 | bool isPIC = (TM.getRelocationModel() == Reloc::PIC_); | 
|  | 329 | bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 330 |  | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 331 | // %hi and %lo used on mips gas to load global addresses on | 
|  | 332 | // static code. %got is used to load global addresses when | 
|  | 333 | // using PIC_. %call16 is used to load direct call targets | 
|  | 334 | // on PIC_ and small code size. %call_lo and %call_hi load | 
|  | 335 | // direct call targets on PIC_ and large code size. | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 336 | if (MI->getOpcode() == Mips::LUi && !MO.isRegister() | 
|  | 337 | && !MO.isImmediate()) { | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 338 | if ((isPIC) && (isCodeLarge)) | 
|  | 339 | O << "%call_hi("; | 
|  | 340 | else | 
|  | 341 | O << "%hi("; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 342 | closeP = true; | 
|  | 343 | } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() | 
|  | 344 | && !MO.isImmediate()) { | 
|  | 345 | O << "%lo("; | 
|  | 346 | closeP = true; | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 347 | } else if ((isPIC) && (MI->getOpcode() == Mips::LW) | 
|  | 348 | && (!MO.isRegister()) && (!MO.isImmediate())) { | 
|  | 349 | const MachineOperand &firstMO = MI->getOperand(opNum-1); | 
|  | 350 | const MachineOperand &lastMO  = MI->getOperand(opNum+1); | 
|  | 351 | if ((firstMO.isRegister()) && (lastMO.isRegister())) { | 
|  | 352 | if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP) | 
|  | 353 | && (!isCodeLarge)) | 
|  | 354 | O << "%call16("; | 
|  | 355 | else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP)) | 
|  | 356 | O << "%got("; | 
|  | 357 | else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP) | 
|  | 358 | && (isCodeLarge)) | 
|  | 359 | O << "%call_lo("; | 
|  | 360 | closeP = true; | 
|  | 361 | } | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 362 | } | 
|  | 363 |  | 
|  | 364 | switch (MO.getType()) | 
|  | 365 | { | 
|  | 366 | case MachineOperand::MO_Register: | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 367 | if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) | 
| Bill Wendling | c24ea4f | 2008-02-26 21:11:01 +0000 | [diff] [blame] | 368 | O << "$" << LowercaseString (RI.get(MO.getReg()).AsmName); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 369 | else | 
|  | 370 | O << "$" << MO.getReg(); | 
|  | 371 | break; | 
|  | 372 |  | 
|  | 373 | case MachineOperand::MO_Immediate: | 
|  | 374 | if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || | 
| Bruno Cardoso Lopes | bcda5e2 | 2007-07-11 23:24:41 +0000 | [diff] [blame] | 375 | (MI->getOpcode() == Mips::LUi)   || (MI->getOpcode() == Mips::ANDi)) | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 376 | O << (unsigned short int)MO.getImm(); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 377 | else | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 378 | O << (short int)MO.getImm(); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 379 | break; | 
|  | 380 |  | 
|  | 381 | case MachineOperand::MO_MachineBasicBlock: | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 382 | printBasicBlockLabel(MO.getMBB()); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 383 | return; | 
|  | 384 |  | 
|  | 385 | case MachineOperand::MO_GlobalAddress: | 
|  | 386 | O << Mang->getValueName(MO.getGlobal()); | 
|  | 387 | break; | 
|  | 388 |  | 
|  | 389 | case MachineOperand::MO_ExternalSymbol: | 
|  | 390 | O << MO.getSymbolName(); | 
|  | 391 | break; | 
|  | 392 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 393 | case MachineOperand::MO_JumpTableIndex: | 
|  | 394 | O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 395 | << '_' << MO.getIndex(); | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 396 | break; | 
|  | 397 |  | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 398 | // FIXME: Verify correct | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 399 | case MachineOperand::MO_ConstantPoolIndex: | 
|  | 400 | O << TAI->getPrivateGlobalPrefix() << "CPI" | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 401 | << getFunctionNumber() << "_" << MO.getIndex(); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 402 | break; | 
|  | 403 |  | 
|  | 404 | default: | 
|  | 405 | O << "<unknown operand type>"; abort (); break; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | if (closeP) O << ")"; | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | void MipsAsmPrinter:: | 
|  | 412 | printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) | 
|  | 413 | { | 
| Bruno Cardoso Lopes | 6d5ada2 | 2007-09-24 20:15:11 +0000 | [diff] [blame] | 414 | // when using stack locations for not load/store instructions | 
|  | 415 | // print the same way as all normal 3 operand instructions. | 
|  | 416 | if (Modifier && !strcmp(Modifier, "stackloc")) { | 
|  | 417 | printOperand(MI, opNum+1); | 
|  | 418 | O << ", "; | 
|  | 419 | printOperand(MI, opNum); | 
|  | 420 | return; | 
|  | 421 | } | 
|  | 422 |  | 
| Bruno Cardoso Lopes | 3e0d030 | 2007-11-05 03:02:32 +0000 | [diff] [blame] | 423 | // Load/Store memory operands -- imm($reg) | 
|  | 424 | // If PIC target the target is loaded as the | 
|  | 425 | // pattern lw $25,%call16($28) | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 426 | printOperand(MI, opNum); | 
|  | 427 | O << "("; | 
|  | 428 | printOperand(MI, opNum+1); | 
|  | 429 | O << ")"; | 
|  | 430 | } | 
|  | 431 |  | 
|  | 432 | bool MipsAsmPrinter:: | 
|  | 433 | doInitialization(Module &M) | 
|  | 434 | { | 
|  | 435 | Mang = new Mangler(M); | 
|  | 436 | return false; // success | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 | bool MipsAsmPrinter:: | 
|  | 440 | doFinalization(Module &M) | 
|  | 441 | { | 
|  | 442 | const TargetData *TD = TM.getTargetData(); | 
|  | 443 |  | 
|  | 444 | // Print out module-level global variables here. | 
|  | 445 | for (Module::const_global_iterator I = M.global_begin(), | 
|  | 446 | E = M.global_end(); I != E; ++I) | 
|  | 447 |  | 
|  | 448 | // External global require no code | 
|  | 449 | if (I->hasInitializer()) { | 
|  | 450 |  | 
|  | 451 | // Check to see if this is a special global | 
|  | 452 | // used by LLVM, if so, emit it. | 
|  | 453 | if (EmitSpecialLLVMGlobal(I)) | 
|  | 454 | continue; | 
|  | 455 |  | 
|  | 456 | O << "\n\n"; | 
|  | 457 | std::string name = Mang->getValueName(I); | 
|  | 458 | Constant *C      = I->getInitializer(); | 
| Duncan Sands | 283207a | 2007-11-05 00:04:43 +0000 | [diff] [blame] | 459 | unsigned Size    = TD->getABITypeSize(C->getType()); | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 460 | unsigned Align   = TD->getPreferredAlignmentLog(I); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 461 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 462 | // Is this correct ? | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 463 | if (C->isNullValue() && (I->hasLinkOnceLinkage() || | 
| Dale Johannesen | ce4396b | 2008-05-14 20:12:51 +0000 | [diff] [blame] | 464 | I->hasInternalLinkage() || I->hasWeakLinkage() || | 
|  | 465 | I->hasCommonLinkage())) | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 466 | { | 
|  | 467 | if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it. | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 468 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 469 | if (!NoZerosInBSS && TAI->getBSSSection()) | 
|  | 470 | SwitchToDataSection(TAI->getBSSSection(), I); | 
|  | 471 | else | 
|  | 472 | SwitchToDataSection(TAI->getDataSection(), I); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 473 |  | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 474 | if (I->hasInternalLinkage()) { | 
|  | 475 | if (TAI->getLCOMMDirective()) | 
|  | 476 | O << TAI->getLCOMMDirective() << name << "," << Size; | 
|  | 477 | else | 
|  | 478 | O << "\t.local\t" << name << "\n"; | 
|  | 479 | } else { | 
|  | 480 | O << TAI->getCOMMDirective() << name << "," << Size; | 
|  | 481 | // The .comm alignment in bytes. | 
|  | 482 | if (TAI->getCOMMDirectiveTakesAlignment()) | 
|  | 483 | O << "," << (1 << Align); | 
|  | 484 | } | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 485 |  | 
|  | 486 | } else { | 
|  | 487 |  | 
|  | 488 | switch (I->getLinkage()) | 
|  | 489 | { | 
|  | 490 | case GlobalValue::LinkOnceLinkage: | 
| Dale Johannesen | ce4396b | 2008-05-14 20:12:51 +0000 | [diff] [blame] | 491 | case GlobalValue::CommonLinkage: | 
|  | 492 | case GlobalValue::WeakLinkage: | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 493 | // FIXME: Verify correct for weak. | 
|  | 494 | // Nonnull linkonce -> weak | 
|  | 495 | O << "\t.weak " << name << "\n"; | 
|  | 496 | SwitchToDataSection("", I); | 
|  | 497 | O << "\t.section\t\".llvm.linkonce.d." << name | 
|  | 498 | << "\",\"aw\",@progbits\n"; | 
|  | 499 | break; | 
|  | 500 | case GlobalValue::AppendingLinkage: | 
|  | 501 | // FIXME: appending linkage variables | 
|  | 502 | // should go into a section of  their name or | 
|  | 503 | // something.  For now, just emit them as external. | 
|  | 504 | case GlobalValue::ExternalLinkage: | 
|  | 505 | // If external or appending, declare as a global symbol | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 506 | O << TAI->getGlobalDirective() << name << "\n"; | 
|  | 507 | // Fall Through | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 508 | case GlobalValue::InternalLinkage: | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 509 | // FIXME: special handling for ".ctors" & ".dtors" sections | 
|  | 510 | if (I->hasSection() && (I->getSection() == ".ctors" || | 
|  | 511 | I->getSection() == ".dtors")) { | 
|  | 512 | std::string SectionName = ".section " + I->getSection(); | 
|  | 513 | SectionName += ",\"aw\",%progbits"; | 
|  | 514 | SwitchToDataSection(SectionName.c_str()); | 
|  | 515 | } else { | 
|  | 516 | if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection()) | 
|  | 517 | SwitchToDataSection(TAI->getBSSSection(), I); | 
|  | 518 | else if (!I->isConstant()) | 
|  | 519 | SwitchToDataSection(TAI->getDataSection(), I); | 
|  | 520 | else { | 
|  | 521 | // Read-only data. | 
|  | 522 | if (TAI->getReadOnlySection()) | 
|  | 523 | SwitchToDataSection(TAI->getReadOnlySection(), I); | 
|  | 524 | else | 
|  | 525 | SwitchToDataSection(TAI->getDataSection(), I); | 
|  | 526 | } | 
|  | 527 | } | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 528 | break; | 
|  | 529 | case GlobalValue::GhostLinkage: | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 530 | cerr << "Should not have any unmaterialized functions!\n"; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 531 | abort(); | 
|  | 532 | case GlobalValue::DLLImportLinkage: | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 533 | cerr << "DLLImport linkage is not supported by this target!\n"; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 534 | abort(); | 
|  | 535 | case GlobalValue::DLLExportLinkage: | 
| Bruno Cardoso Lopes | b439132 | 2007-11-12 19:49:57 +0000 | [diff] [blame] | 536 | cerr << "DLLExport linkage is not supported by this target!\n"; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 537 | abort(); | 
|  | 538 | default: | 
|  | 539 | assert(0 && "Unknown linkage type!"); | 
|  | 540 | } | 
| Bruno Cardoso Lopes | cfd1638 | 2007-08-28 05:06:17 +0000 | [diff] [blame] | 541 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 542 | O << "\t.align " << Align << "\n"; | 
|  | 543 | O << "\t.type " << name << ",@object\n"; | 
|  | 544 | O << "\t.size " << name << "," << Size << "\n"; | 
|  | 545 | O << name << ":\n"; | 
|  | 546 | EmitGlobalConstant(C); | 
|  | 547 | } | 
|  | 548 | } | 
|  | 549 |  | 
| Bruno Cardoso Lopes | 326a037 | 2008-06-04 01:45:25 +0000 | [diff] [blame] | 550 | O << "\n"; | 
|  | 551 |  | 
| Dan Gohman | cf0a534 | 2007-07-25 19:33:14 +0000 | [diff] [blame] | 552 | return AsmPrinter::doFinalization(M); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 553 | } |