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