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