MipsAsmPrinter.cpp revision a4e8200366805c665bb1424d8af5550f5d3d6863
1//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Bruno Cardoso Lopes and is distributed under the
6// University of Illinois Open Source 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
17#include "Mips.h"
18#include "MipsInstrInfo.h"
19#include "MipsTargetMachine.h"
20#include "MipsMachineFunction.h"
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"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineInstr.h"
29#include "llvm/Target/TargetAsmInfo.h"
30#include "llvm/Target/TargetData.h"
31#include "llvm/Target/TargetMachine.h"
32#include "llvm/Support/Mangler.h"
33#include "llvm/ADT/Statistic.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/MathExtras.h"
38#include <cctype>
39
40using namespace llvm;
41
42STATISTIC(EmittedInsts, "Number of machine instrs printed");
43
44namespace {
45  struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
46    MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM,
47                   const TargetAsmInfo *T):
48                   AsmPrinter(O, TM, T) {}
49
50    virtual const char *getPassName() const {
51      return "Mips Assembly Printer";
52    }
53
54    enum SetDirectiveFlags {
55      REORDER,      // enables instruction reordering.
56      NOREORDER,    // disables instruction reordering.
57      MACRO,        // enables GAS macros.
58      NOMACRO       // disables GAS macros.
59    };
60
61    void printOperand(const MachineInstr *MI, int opNum);
62    void printMemOperand(const MachineInstr *MI, int opNum,
63                         const char *Modifier = 0);
64
65    void printHex32(unsigned int Value);
66    void emitFunctionStart(MachineFunction &MF);
67    void emitFunctionEnd();
68    void emitFrameDirective(MachineFunction &MF);
69    void emitMaskDirective(MachineFunction &MF);
70    void emitFMaskDirective();
71    void emitSetDirective(SetDirectiveFlags Flag);
72
73    bool printInstruction(const MachineInstr *MI);  // autogenerated.
74    bool runOnMachineFunction(MachineFunction &F);
75    bool doInitialization(Module &M);
76    bool doFinalization(Module &M);
77  };
78} // end of anonymous namespace
79
80#include "MipsGenAsmWriter.inc"
81
82/// createMipsCodePrinterPass - Returns a pass that prints the MIPS
83/// assembly code for a MachineFunction to the given output stream,
84/// using the given target machine description.  This should work
85/// regardless of whether the function is in SSA form.
86FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
87                                              MipsTargetMachine &tm)
88{
89  return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo());
90}
91
92/// This pattern will be emitted :
93///   .frame reg1, size, reg2
94/// It describes the stack frame.
95/// reg1 - stack pointer
96/// size - stack size allocated for the function
97/// reg2 - return address register
98void MipsAsmPrinter::
99emitFrameDirective(MachineFunction &MF)
100{
101  const MRegisterInfo &RI = *TM.getRegisterInfo();
102
103  unsigned stackReg  = RI.getFrameRegister(MF);
104  unsigned returnReg = RI.getRARegister();
105  unsigned stackSize = MF.getFrameInfo()->getStackSize();
106
107
108  O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).Name)
109                    << "," << stackSize << ","
110                    << "$" << LowercaseString(RI.get(returnReg).Name)
111                    << "\n";
112}
113
114/// This pattern will be emitted :
115///   .mask bitmask, offset
116/// Tells the assembler (and possibly linker) which registers are saved and where.
117/// bitmask - mask of all GPRs (little endian)
118/// offset  - negative value. offset+stackSize should give where on the stack
119///           the first GPR is saved.
120/// TODO: consider calle saved GPR regs here, not hardcode register numbers.
121void MipsAsmPrinter::
122emitMaskDirective(MachineFunction &MF)
123{
124  const MRegisterInfo &RI  = *TM.getRegisterInfo();
125  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
126
127  bool hasFP  = RI.hasFP(MF);
128  bool saveRA = MF.getFrameInfo()->hasCalls();
129
130  int offset;
131
132  if (!MipsFI->getTopSavedRegOffset())
133    offset = 0;
134  else
135    offset = -(MF.getFrameInfo()->getStackSize()
136               -MipsFI->getTopSavedRegOffset());
137
138  #ifndef NDEBUG
139  DOUT << "<--ASM PRINTER--emitMaskDirective-->" << "\n";
140  DOUT << "StackSize :  " << MF.getFrameInfo()->getStackSize() << "\n";
141  DOUT << "getTopSavedRegOffset() : " << MipsFI->getTopSavedRegOffset() << "\n";
142  DOUT << "offset : " << offset << "\n\n";
143  #endif
144
145  unsigned int bitmask = 0;
146
147  if (hasFP)
148    bitmask |= (1 << 30);
149
150  if (saveRA)
151    bitmask |= (1 << 31);
152
153  O << "\t.mask\t";
154  printHex32(bitmask);
155  O << "," << offset << "\n";
156}
157
158/// This pattern will be emitted :
159///   .fmask bitmask, offset
160/// Tells the assembler (and possibly linker) which float registers are saved.
161/// bitmask - mask of all Float Point registers (little endian)
162/// offset  - negative value. offset+stackSize should give where on the stack
163///           the first Float Point register is saved.
164/// TODO: implement this, dummy for now
165void MipsAsmPrinter::
166emitFMaskDirective()
167{
168  O << "\t.fmask\t0x00000000,0" << "\n";
169}
170
171/// Print a 32 bit hex number filling with 0's on the left.
172/// TODO: make this setfill and setw
173void MipsAsmPrinter::
174printHex32(unsigned int Value) {
175  O << "0x" << std::hex << Value << std::dec;
176}
177
178/// Emit Set directives.
179void MipsAsmPrinter::
180emitSetDirective(SetDirectiveFlags Flag) {
181
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  }
190}
191
192/// Emit the directives used by GAS on the start of functions
193void MipsAsmPrinter::
194emitFunctionStart(MachineFunction &MF)
195{
196  // Print out the label for the function.
197  const Function *F = MF.getFunction();
198  SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
199
200  // On Mips GAS, if .align #n is present, #n means the number of bits
201  // to be cleared. So, if we want 4 byte alignment, we must have .align 2
202  EmitAlignment(1, F);
203
204  O << "\t.globl\t"  << CurrentFnName << "\n";
205  O << "\t.ent\t"    << CurrentFnName << "\n";
206  O << "\t.type\t"   << CurrentFnName << ", @function\n";
207  O << CurrentFnName << ":\n";
208
209  emitFrameDirective(MF);
210  emitMaskDirective(MF);
211  emitFMaskDirective();
212
213  emitSetDirective(NOREORDER);
214  emitSetDirective(NOMACRO);
215}
216
217/// Emit the directives used by GAS on the end of functions
218void MipsAsmPrinter::
219emitFunctionEnd() {
220  emitSetDirective(MACRO);
221  emitSetDirective(REORDER);
222  O << "\t.end\t" << CurrentFnName << "\n";
223}
224
225/// runOnMachineFunction - This uses the printMachineInstruction()
226/// method to print assembly for each instruction.
227bool MipsAsmPrinter::
228runOnMachineFunction(MachineFunction &MF)
229{
230  SetupMachineFunction(MF);
231
232  // Print out constants referenced by the function
233  EmitConstantPool(MF.getConstantPool());
234
235  O << "\n\n";
236
237  // What's my mangled name?
238  CurrentFnName = Mang->getValueName(MF.getFunction());
239
240  // Emit the function start directives
241  emitFunctionStart(MF);
242
243  // Print out code for the function.
244  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
245       I != E; ++I) {
246
247    // Print a label for the basic block.
248    if (I != MF.begin()) {
249      printBasicBlockLabel(I, true);
250      O << '\n';
251    }
252
253    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
254         II != E; ++II) {
255      // Print the assembly for the instruction.
256      O << "\t";
257      printInstruction(II);
258      ++EmittedInsts;
259    }
260  }
261
262  // Emit function end directives
263  emitFunctionEnd();
264
265  // We didn't modify anything.
266  return false;
267}
268
269void MipsAsmPrinter::
270printOperand(const MachineInstr *MI, int opNum)
271{
272  const MachineOperand &MO = MI->getOperand(opNum);
273  const MRegisterInfo  &RI = *TM.getRegisterInfo();
274  bool  closeP=false;
275
276  // %hi and %lo used on mips gas to break large constants
277  if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
278      && !MO.isImmediate()) {
279    O << "%hi(";
280    closeP = true;
281  } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
282             && !MO.isImmediate()) {
283    O << "%lo(";
284    closeP = true;
285  }
286
287  switch (MO.getType())
288  {
289    case MachineOperand::MO_Register:
290      if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
291        O << "$" << LowercaseString (RI.get(MO.getReg()).Name);
292      else
293        O << "$" << MO.getReg();
294      break;
295
296    case MachineOperand::MO_Immediate:
297      if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) ||
298          (MI->getOpcode() == Mips::LUi)   || (MI->getOpcode() == Mips::ANDi))
299        O << (unsigned short int)MO.getImmedValue();
300      else
301        O << (short int)MO.getImmedValue();
302      break;
303
304    case MachineOperand::MO_MachineBasicBlock:
305      printBasicBlockLabel(MO.getMachineBasicBlock());
306      return;
307
308    case MachineOperand::MO_GlobalAddress:
309      O << Mang->getValueName(MO.getGlobal());
310      break;
311
312    case MachineOperand::MO_ExternalSymbol:
313      O << MO.getSymbolName();
314      break;
315
316    case MachineOperand::MO_ConstantPoolIndex:
317      O << TAI->getPrivateGlobalPrefix() << "CPI"
318        << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
319      break;
320
321    default:
322      O << "<unknown operand type>"; abort (); break;
323  }
324
325  if (closeP) O << ")";
326}
327
328void MipsAsmPrinter::
329printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
330{
331  // lw/sw $reg, MemOperand
332  // will turn into :
333  // lw/sw $reg, imm($reg)
334  printOperand(MI, opNum);
335  O << "(";
336  printOperand(MI, opNum+1);
337  O << ")";
338}
339
340bool MipsAsmPrinter::
341doInitialization(Module &M)
342{
343  Mang = new Mangler(M);
344  return false; // success
345}
346
347bool MipsAsmPrinter::
348doFinalization(Module &M)
349{
350  const TargetData *TD = TM.getTargetData();
351
352  // Print out module-level global variables here.
353  for (Module::const_global_iterator I = M.global_begin(),
354         E = M.global_end(); I != E; ++I)
355
356    // External global require no code
357    if (I->hasInitializer()) {
358
359      // Check to see if this is a special global
360      // used by LLVM, if so, emit it.
361      if (EmitSpecialLLVMGlobal(I))
362        continue;
363
364      O << "\n\n";
365      std::string name = Mang->getValueName(I);
366      Constant *C      = I->getInitializer();
367      unsigned Size    = TD->getTypeSize(C->getType());
368      unsigned Align   = TD->getPrefTypeAlignment(C->getType());
369
370      if (C->isNullValue() && (I->hasLinkOnceLinkage() ||
371        I->hasInternalLinkage() || I->hasWeakLinkage()
372        /* FIXME: Verify correct */)) {
373
374        SwitchToDataSection(".data", I);
375        if (I->hasInternalLinkage())
376          O << "\t.local " << name << "\n";
377
378        O << "\t.comm " << name << ","
379          << TD->getTypeSize(C->getType())
380          << "," << Align << "\n";
381
382      } else {
383
384        switch (I->getLinkage())
385        {
386          case GlobalValue::LinkOnceLinkage:
387          case GlobalValue::WeakLinkage:
388            // FIXME: Verify correct for weak.
389            // Nonnull linkonce -> weak
390            O << "\t.weak " << name << "\n";
391            SwitchToDataSection("", I);
392            O << "\t.section\t\".llvm.linkonce.d." << name
393                          << "\",\"aw\",@progbits\n";
394            break;
395          case GlobalValue::AppendingLinkage:
396            // FIXME: appending linkage variables
397            // should go into a section of  their name or
398            // something.  For now, just emit them as external.
399          case GlobalValue::ExternalLinkage:
400            // If external or appending, declare as a global symbol
401            O << "\t.globl " << name << "\n";
402          case GlobalValue::InternalLinkage:
403            if (C->isNullValue())
404              SwitchToDataSection(".bss", I);
405            else
406              SwitchToDataSection(".data", I);
407            break;
408          case GlobalValue::GhostLinkage:
409            cerr << "Should not have any"
410                 << "unmaterialized functions!\n";
411            abort();
412          case GlobalValue::DLLImportLinkage:
413            cerr << "DLLImport linkage is"
414                 << "not supported by this target!\n";
415            abort();
416          case GlobalValue::DLLExportLinkage:
417            cerr << "DLLExport linkage is"
418                 << "not supported by this target!\n";
419            abort();
420          default:
421            assert(0 && "Unknown linkage type!");
422        }
423        O << "\t.align " << Align << "\n";
424        O << "\t.type " << name << ",@object\n";
425        O << "\t.size " << name << "," << Size << "\n";
426        O << name << ":\n";
427        EmitGlobalConstant(C);
428    }
429  }
430
431  AsmPrinter::doFinalization(M);
432  return false; // success
433}
434