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