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