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