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