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