Switch MSP430, CellSPU, SystemZ, Darwin/PPC, Alpha, and Sparc to
[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     bool runOnMachineFunction(MachineFunction &F);
82
83     void getAnalysisUsage(AnalysisUsage &AU) const {
84       AsmPrinter::getAnalysisUsage(AU);
85       AU.setPreservesAll();
86     }
87   };
88 } // end of anonymous namespace
89
90
91 bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
92   SetupMachineFunction(MF);
93   O << "\n\n";
94   
95   EmitFunctionHeader();
96
97   // Print out code for the function.
98   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
99        I != E; ++I) {
100     // Print a label for the basic block.
101     EmitBasicBlockStart(I);
102
103     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
104          II != E; ++II)
105       // Print the assembly for the instruction.
106       printMachineInstruction(II);
107   }
108
109   if (MAI->hasDotTypeDotSizeDirective())
110     O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
111
112   // Print out constants referenced by the function
113   EmitConstantPool(MF.getConstantPool());
114   EmitJumpTableInfo(MF);
115   
116   // We didn't modify anything
117   return false;
118 }
119
120 void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
121   ++EmittedInsts;
122
123   processDebugLoc(MI, true);
124
125   printInstructionThroughMCStreamer(MI);
126
127   if (VerboseAsm)
128     EmitComments(*MI);
129   O << '\n';
130
131   processDebugLoc(MI, false);
132 }
133
134 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
135                                     const char* Modifier) {
136   const MachineOperand &MO = MI->getOperand(OpNum);
137   switch (MO.getType()) {
138   case MachineOperand::MO_Register:
139     O << MSP430InstPrinter::getRegisterName(MO.getReg());
140     return;
141   case MachineOperand::MO_Immediate:
142     if (!Modifier || strcmp(Modifier, "nohash"))
143       O << '#';
144     O << MO.getImm();
145     return;
146   case MachineOperand::MO_MachineBasicBlock:
147     O << *MO.getMBB()->getSymbol(OutContext);
148     return;
149   case MachineOperand::MO_GlobalAddress: {
150     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
151     uint64_t Offset = MO.getOffset();
152
153     O << (isMemOp ? '&' : '#');
154     if (Offset)
155       O << '(' << Offset << '+';
156
157     O << *GetGlobalValueSymbol(MO.getGlobal());
158     
159     if (Offset)
160       O << ')';
161
162     return;
163   }
164   case MachineOperand::MO_ExternalSymbol: {
165     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
166     O << (isMemOp ? '&' : '#');
167     O << MAI->getGlobalPrefix() << MO.getSymbolName();
168     return;
169   }
170   default:
171     llvm_unreachable("Not implemented yet!");
172   }
173 }
174
175 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
176                                           const char* Modifier) {
177   const MachineOperand &Base = MI->getOperand(OpNum);
178   const MachineOperand &Disp = MI->getOperand(OpNum+1);
179
180   // Print displacement first
181   if (!Disp.isImm()) {
182     printOperand(MI, OpNum+1, "mem");
183   } else {
184     if (!Base.getReg())
185       O << '&';
186
187     printOperand(MI, OpNum+1, "nohash");
188   }
189
190
191   // Print register base field
192   if (Base.getReg()) {
193     O << '(';
194     printOperand(MI, OpNum);
195     O << ')';
196   }
197 }
198
199 void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
200   unsigned CC = MI->getOperand(OpNum).getImm();
201
202   switch (CC) {
203   default:
204    llvm_unreachable("Unsupported CC code");
205    break;
206   case MSP430CC::COND_E:
207    O << "eq";
208    break;
209   case MSP430CC::COND_NE:
210    O << "ne";
211    break;
212   case MSP430CC::COND_HS:
213    O << "hs";
214    break;
215   case MSP430CC::COND_LO:
216    O << "lo";
217    break;
218   case MSP430CC::COND_GE:
219    O << "ge";
220    break;
221   case MSP430CC::COND_L:
222    O << 'l';
223    break;
224   }
225 }
226
227 /// PrintAsmOperand - Print out an operand for an inline asm expression.
228 ///
229 bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
230                                        unsigned AsmVariant,
231                                        const char *ExtraCode) {
232   // Does this asm operand have a single letter operand modifier?
233   if (ExtraCode && ExtraCode[0])
234     return true; // Unknown modifier.
235
236   printOperand(MI, OpNo);
237   return false;
238 }
239
240 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
241                                              unsigned OpNo, unsigned AsmVariant,
242                                              const char *ExtraCode) {
243   if (ExtraCode && ExtraCode[0]) {
244     return true; // Unknown modifier.
245   }
246   printSrcMemOperand(MI, OpNo);
247   return false;
248 }
249
250 //===----------------------------------------------------------------------===//
251 void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI){
252
253   MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);
254
255   switch (MI->getOpcode()) {
256   case TargetInstrInfo::DBG_LABEL:
257   case TargetInstrInfo::EH_LABEL:
258   case TargetInstrInfo::GC_LABEL:
259     printLabel(MI);
260     return;
261   case TargetInstrInfo::KILL:
262     printKill(MI);
263     return;
264   case TargetInstrInfo::INLINEASM:
265     printInlineAsm(MI);
266     return;
267   case TargetInstrInfo::IMPLICIT_DEF:
268     printImplicitDef(MI);
269     return;
270   default: break;
271   }
272
273   MCInst TmpInst;
274   MCInstLowering.Lower(MI, TmpInst);
275
276   printMCInst(&TmpInst);
277 }
278
279 static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
280                                                 unsigned SyntaxVariant,
281                                                 const MCAsmInfo &MAI,
282                                                 raw_ostream &O) {
283   if (SyntaxVariant == 0)
284     return new MSP430InstPrinter(O, MAI);
285   return 0;
286 }
287
288 // Force static initialization.
289 extern "C" void LLVMInitializeMSP430AsmPrinter() {
290   RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
291   TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
292                                         createMSP430MCInstPrinter);
293 }