Checkpoint MCInst printer. We (almostly) able to print global / JT / constpool entries
[oota-llvm.git] / lib / Target / MSP430 / AsmPrinter / MSP430AsmPrinter.cpp
1 //===-- MSP430AsmPrinter.cpp - MSP430 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 the MSP430 assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "MSP430.h"
17 #include "MSP430InstrInfo.h"
18 #include "MSP430InstPrinter.h"
19 #include "MSP430MCAsmInfo.h"
20 #include "MSP430MCInstLower.h"
21 #include "MSP430TargetMachine.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/DwarfWriter.h"
27 #include "llvm/CodeGen/MachineModuleInfo.h"
28 #include "llvm/CodeGen/MachineFunctionPass.h"
29 #include "llvm/CodeGen/MachineConstantPool.h"
30 #include "llvm/CodeGen/MachineInstr.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSymbol.h"
34 #include "llvm/Target/TargetData.h"
35 #include "llvm/Target/TargetLoweringObjectFile.h"
36 #include "llvm/Target/TargetRegistry.h"
37 #include "llvm/ADT/Statistic.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Compiler.h"
40 #include "llvm/Support/FormattedStream.h"
41 #include "llvm/Support/Mangler.h"
42 #include "llvm/Support/ErrorHandling.h"
43
44 using namespace llvm;
45
46 STATISTIC(EmittedInsts, "Number of machine instrs printed");
47
48 static cl::opt<bool>
49 EnableMCInst("enable-msp430-mcinst-printer", cl::Hidden,
50              cl::desc("enable experimental mcinst gunk in the msp430 backend"));
51
52 namespace {
53   class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
54   public:
55     MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56                      const MCAsmInfo *MAI, bool V)
57       : AsmPrinter(O, TM, MAI, V) {}
58
59     virtual const char *getPassName() const {
60       return "MSP430 Assembly Printer";
61     }
62
63     void printMCInst(const MCInst *MI) {
64       MSP430InstPrinter(O, *MAI).printInstruction(MI);
65     }
66     void printOperand(const MachineInstr *MI, int OpNum,
67                       const char* Modifier = 0);
68     void printSrcMemOperand(const MachineInstr *MI, int OpNum,
69                             const char* Modifier = 0);
70     void printCCOperand(const MachineInstr *MI, int OpNum);
71     void printInstruction(const MachineInstr *MI);  // autogenerated.
72     static const char *getRegisterName(unsigned RegNo);
73
74     void printMachineInstruction(const MachineInstr * MI);
75     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
76                          unsigned AsmVariant,
77                          const char *ExtraCode);
78     bool PrintAsmMemoryOperand(const MachineInstr *MI,
79                                unsigned OpNo, unsigned AsmVariant,
80                                const char *ExtraCode);
81     void printInstructionThroughMCStreamer(const MachineInstr *MI);
82
83     void emitFunctionHeader(const MachineFunction &MF);
84     bool runOnMachineFunction(MachineFunction &F);
85
86     virtual void PrintGlobalVariable(const GlobalVariable *GV) {
87       // FIXME: No support for global variables?
88     }
89
90     void getAnalysisUsage(AnalysisUsage &AU) const {
91       AsmPrinter::getAnalysisUsage(AU);
92       AU.setPreservesAll();
93     }
94   };
95 } // end of anonymous namespace
96
97 #include "MSP430GenAsmWriter.inc"
98
99
100 void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
101   const Function *F = MF.getFunction();
102
103   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
104
105   unsigned FnAlign = MF.getAlignment();
106   EmitAlignment(FnAlign, F);
107
108   switch (F->getLinkage()) {
109   default: llvm_unreachable("Unknown linkage type!");
110   case Function::InternalLinkage:  // Symbols default to internal.
111   case Function::PrivateLinkage:
112   case Function::LinkerPrivateLinkage:
113     break;
114   case Function::ExternalLinkage:
115     O << "\t.globl\t" << CurrentFnName << '\n';
116     break;
117   case Function::LinkOnceAnyLinkage:
118   case Function::LinkOnceODRLinkage:
119   case Function::WeakAnyLinkage:
120   case Function::WeakODRLinkage:
121     O << "\t.weak\t" << CurrentFnName << '\n';
122     break;
123   }
124
125   printVisibility(CurrentFnName, F->getVisibility());
126
127   O << "\t.type\t" << CurrentFnName << ",@function\n"
128     << CurrentFnName << ":\n";
129 }
130
131 bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
132   SetupMachineFunction(MF);
133   O << "\n\n";
134
135   // Print the 'header' of function
136   emitFunctionHeader(MF);
137
138   // Print out code for the function.
139   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
140        I != E; ++I) {
141     // Print a label for the basic block.
142     EmitBasicBlockStart(I);
143
144     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
145          II != E; ++II)
146       // Print the assembly for the instruction.
147       printMachineInstruction(II);
148   }
149
150   if (MAI->hasDotTypeDotSizeDirective())
151     O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
152
153   // We didn't modify anything
154   return false;
155 }
156
157 void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
158   ++EmittedInsts;
159
160   processDebugLoc(MI, true);
161
162   // Call the autogenerated instruction printer routines.
163   if (EnableMCInst) {
164     printInstructionThroughMCStreamer(MI);
165   } else {
166     printInstruction(MI);
167   }
168
169   if (VerboseAsm && !MI->getDebugLoc().isUnknown())
170     EmitComments(*MI);
171   O << '\n';
172
173   processDebugLoc(MI, false);
174 }
175
176 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
177                                     const char* Modifier) {
178   const MachineOperand &MO = MI->getOperand(OpNum);
179   switch (MO.getType()) {
180   case MachineOperand::MO_Register:
181     O << getRegisterName(MO.getReg());
182     return;
183   case MachineOperand::MO_Immediate:
184     if (!Modifier || strcmp(Modifier, "nohash"))
185       O << '#';
186     O << MO.getImm();
187     return;
188   case MachineOperand::MO_MachineBasicBlock:
189     GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
190     return;
191   case MachineOperand::MO_GlobalAddress: {
192     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
193     std::string Name = Mang->getMangledName(MO.getGlobal());
194     uint64_t Offset = MO.getOffset();
195
196     O << (isMemOp ? '&' : '#');
197     if (Offset)
198       O << '(' << Offset << '+';
199
200     O << Name;
201     if (Offset)
202       O << ')';
203
204     return;
205   }
206   case MachineOperand::MO_ExternalSymbol: {
207     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
208     std::string Name(MAI->getGlobalPrefix());
209     Name += MO.getSymbolName();
210
211     O << (isMemOp ? '&' : '#') << Name;
212
213     return;
214   }
215   default:
216     llvm_unreachable("Not implemented yet!");
217   }
218 }
219
220 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
221                                           const char* Modifier) {
222   const MachineOperand &Base = MI->getOperand(OpNum);
223   const MachineOperand &Disp = MI->getOperand(OpNum+1);
224
225   if (Base.isGlobal())
226     printOperand(MI, OpNum, "mem");
227   else if (Disp.isImm() && !Base.getReg())
228     printOperand(MI, OpNum);
229   else if (Base.getReg()) {
230     if (Disp.getImm()) {
231       printOperand(MI, OpNum + 1, "nohash");
232       O << '(';
233       printOperand(MI, OpNum);
234       O << ')';
235     } else {
236       O << '@';
237       printOperand(MI, OpNum);
238     }
239   } else
240     llvm_unreachable("Unsupported memory operand");
241 }
242
243 void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
244   unsigned CC = MI->getOperand(OpNum).getImm();
245
246   switch (CC) {
247   default:
248    llvm_unreachable("Unsupported CC code");
249    break;
250   case MSP430::COND_E:
251    O << "eq";
252    break;
253   case MSP430::COND_NE:
254    O << "ne";
255    break;
256   case MSP430::COND_HS:
257    O << "hs";
258    break;
259   case MSP430::COND_LO:
260    O << "lo";
261    break;
262   case MSP430::COND_GE:
263    O << "ge";
264    break;
265   case MSP430::COND_L:
266    O << 'l';
267    break;
268   }
269 }
270
271 /// PrintAsmOperand - Print out an operand for an inline asm expression.
272 ///
273 bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
274                                        unsigned AsmVariant,
275                                        const char *ExtraCode) {
276   // Does this asm operand have a single letter operand modifier?
277   if (ExtraCode && ExtraCode[0])
278     return true; // Unknown modifier.
279
280   printOperand(MI, OpNo);
281   return false;
282 }
283
284 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
285                                              unsigned OpNo, unsigned AsmVariant,
286                                              const char *ExtraCode) {
287   if (ExtraCode && ExtraCode[0]) {
288     return true; // Unknown modifier.
289   }
290   printSrcMemOperand(MI, OpNo);
291   return false;
292 }
293
294 //===----------------------------------------------------------------------===//
295 void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI)
296 {
297
298   MSP430MCInstLower MCInstLowering(OutContext, *Mang, getFunctionNumber(), *MAI);
299
300   switch (MI->getOpcode()) {
301   case TargetInstrInfo::DBG_LABEL:
302   case TargetInstrInfo::EH_LABEL:
303   case TargetInstrInfo::GC_LABEL:
304     printLabel(MI);
305     return;
306   case TargetInstrInfo::KILL:
307     return;
308   case TargetInstrInfo::INLINEASM:
309     O << '\t';
310     printInlineAsm(MI);
311     return;
312   case TargetInstrInfo::IMPLICIT_DEF:
313     printImplicitDef(MI);
314     return;
315   default: break;
316   }
317
318   MCInst TmpInst;
319   MCInstLowering.Lower(MI, TmpInst);
320
321   printMCInst(&TmpInst);
322 }
323
324 // Force static initialization.
325 extern "C" void LLVMInitializeMSP430AsmPrinter() {
326   RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
327 }