b37e62533919d9b9c228eac4ab4d561bc69aadff
[oota-llvm.git] / lib / Target / Blackfin / AsmPrinter / BlackfinAsmPrinter.cpp
1 //===-- BlackfinAsmPrinter.cpp - Blackfin 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 BLACKFIN assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "Blackfin.h"
17 #include "BlackfinInstrInfo.h"
18 #include "llvm/Constants.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Module.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/DwarfWriter.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineConstantPool.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/Target/TargetData.h"
29 #include "llvm/Target/TargetLoweringObjectFile.h"
30 #include "llvm/Target/TargetRegistry.h"
31 #include "llvm/Support/Mangler.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/Support/FormattedStream.h"
34
35 using namespace llvm;
36
37 STATISTIC(EmittedInsts, "Number of machine instrs printed");
38
39 namespace {
40   class VISIBILITY_HIDDEN BlackfinAsmPrinter : public AsmPrinter {
41   public:
42     BlackfinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
43                        const MCAsmInfo *MAI, bool V)
44       : AsmPrinter(O, TM, MAI, V) {}
45
46     virtual const char *getPassName() const {
47       return "Blackfin Assembly Printer";
48     }
49
50     void printOperand(const MachineInstr *MI, int opNum);
51     void printMemoryOperand(const MachineInstr *MI, int opNum);
52     void printInstruction(const MachineInstr *MI);  // autogenerated.
53     void emitLinkage(const std::string &n, GlobalValue::LinkageTypes l);
54     bool runOnMachineFunction(MachineFunction &F);
55     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
56                          unsigned AsmVariant, const char *ExtraCode);
57     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
58                                unsigned AsmVariant, const char *ExtraCode);
59     void PrintGlobalVariable(const GlobalVariable* GVar);
60   };
61 } // end of anonymous namespace
62
63 #include "BlackfinGenAsmWriter.inc"
64
65 extern "C" void LLVMInitializeBlackfinAsmPrinter() {
66   RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget);
67 }
68
69 void BlackfinAsmPrinter::emitLinkage(const std::string &name,
70                                      GlobalValue::LinkageTypes l) {
71   switch (l) {
72   default: llvm_unreachable("Unknown linkage type!");
73   case GlobalValue::InternalLinkage:  // Symbols default to internal.
74   case GlobalValue::PrivateLinkage:
75   case GlobalValue::LinkerPrivateLinkage:
76     break;
77   case GlobalValue::ExternalLinkage:
78     O << MAI->getGlobalDirective() << name << "\n";
79     break;
80   case GlobalValue::LinkOnceAnyLinkage:
81   case GlobalValue::LinkOnceODRLinkage:
82   case GlobalValue::WeakAnyLinkage:
83   case GlobalValue::WeakODRLinkage:
84     O << MAI->getGlobalDirective() << name << "\n";
85     O << MAI->getWeakDefDirective() << name << "\n";
86     break;
87   }
88 }
89
90 void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) {
91   const TargetData *TD = TM.getTargetData();
92
93   if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV))
94     return;
95
96   std::string name = Mang->getMangledName(GV);
97   Constant *C = GV->getInitializer();
98
99   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,
100                                                                   TM));
101   emitLinkage(name, GV->getLinkage());
102   EmitAlignment(TD->getPreferredAlignmentLog(GV), GV);
103   printVisibility(name, GV->getVisibility());
104
105   O << "\t.type " << name << ", STT_OBJECT\n";
106   O << "\t.size " << name << ',' << TD->getTypeAllocSize(C->getType()) << '\n';
107   O << name << ":\n";
108   EmitGlobalConstant(C);
109 }
110
111 /// runOnMachineFunction - This uses the printInstruction()
112 /// method to print assembly for each instruction.
113 ///
114 bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
115   SetupMachineFunction(MF);
116   EmitConstantPool(MF.getConstantPool());
117   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
118
119   const Function *F = MF.getFunction();
120   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
121   EmitAlignment(2, F);
122   emitLinkage(CurrentFnName, F->getLinkage());
123   printVisibility(CurrentFnName, F->getVisibility());
124
125   O << "\t.type\t" << CurrentFnName << ", STT_FUNC\n"
126     << CurrentFnName << ":\n";
127
128   if (DW)
129     DW->BeginFunction(&MF);
130
131   // Print out code for the function.
132   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
133        I != E; ++I) {
134     // Print a label for the basic block.
135     if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
136       // This is an entry block or a block that's only reachable via a
137       // fallthrough edge. In non-VerboseAsm mode, don't print the label.
138     } else {
139       printBasicBlockLabel(I, true, true, VerboseAsm);
140       O << '\n';
141     }
142
143     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
144          II != E; ++II) {
145       // Print the assembly for the instruction.
146       processDebugLoc(II->getDebugLoc());
147
148       printInstruction(II);
149       if (VerboseAsm && !II->getDebugLoc().isUnknown())
150         EmitComments(*II);
151       O << '\n';
152       
153       ++EmittedInsts;
154     }
155   }
156
157   O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
158
159   if (DW)
160     DW->EndFunction(&MF);
161
162   return false;
163 }
164
165 void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
166   const MachineOperand &MO = MI->getOperand (opNum);
167   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
168   switch (MO.getType()) {
169   case MachineOperand::MO_Register:
170     assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
171            "Virtual registers should be already mapped!");
172     O << RI.get(MO.getReg()).AsmName;
173     break;
174
175   case MachineOperand::MO_Immediate:
176     O << MO.getImm();
177     break;
178   case MachineOperand::MO_MachineBasicBlock:
179     printBasicBlockLabel(MO.getMBB(), false, false, false);
180     return;
181   case MachineOperand::MO_GlobalAddress:
182     O << Mang->getMangledName(MO.getGlobal());
183     printOffset(MO.getOffset());
184     break;
185   case MachineOperand::MO_ExternalSymbol:
186     O << Mang->makeNameProper(MO.getSymbolName());
187     break;
188   case MachineOperand::MO_ConstantPoolIndex:
189     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
190       << MO.getIndex();
191     break;
192   case MachineOperand::MO_JumpTableIndex:
193     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
194       << '_' << MO.getIndex();
195     break;
196   default:
197     llvm_unreachable("<unknown operand type>");
198     break;
199   }
200 }
201
202 void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum) {
203   printOperand(MI, opNum);
204
205   if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0)
206     return;
207
208   O << " + ";
209   printOperand(MI, opNum+1);
210 }
211
212 /// PrintAsmOperand - Print out an operand for an inline asm expression.
213 ///
214 bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
215                                          unsigned OpNo,
216                                          unsigned AsmVariant,
217                                          const char *ExtraCode) {
218   if (ExtraCode && ExtraCode[0]) {
219     if (ExtraCode[1] != 0) return true; // Unknown modifier.
220
221     switch (ExtraCode[0]) {
222     default: return true;  // Unknown modifier.
223     case 'r':
224       break;
225     }
226   }
227
228   printOperand(MI, OpNo);
229
230   return false;
231 }
232
233 bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
234                                                unsigned OpNo,
235                                                unsigned AsmVariant,
236                                                const char *ExtraCode) {
237   if (ExtraCode && ExtraCode[0])
238     return true;  // Unknown modifier
239
240   O << '[';
241   printOperand(MI, OpNo);
242   O << ']';
243
244   return false;
245 }