1 //===-- BlackfinAsmPrinter.cpp - Blackfin LLVM assembly writer ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format BLACKFIN assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
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"
38 STATISTIC(EmittedInsts
, "Number of machine instrs printed");
41 class VISIBILITY_HIDDEN BlackfinAsmPrinter
: public AsmPrinter
{
43 BlackfinAsmPrinter(formatted_raw_ostream
&O
, TargetMachine
&TM
,
44 const MCAsmInfo
*MAI
, bool V
)
45 : AsmPrinter(O
, TM
, MAI
, V
) {}
47 virtual const char *getPassName() const {
48 return "Blackfin Assembly Printer";
51 void printOperand(const MachineInstr
*MI
, int opNum
);
52 void printMemoryOperand(const MachineInstr
*MI
, int opNum
);
53 void printInstruction(const MachineInstr
*MI
); // autogenerated.
54 static const char *getRegisterName(unsigned RegNo
);
56 void emitLinkage(const std::string
&n
, GlobalValue::LinkageTypes l
);
57 bool runOnMachineFunction(MachineFunction
&F
);
58 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
59 unsigned AsmVariant
, const char *ExtraCode
);
60 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
61 unsigned AsmVariant
, const char *ExtraCode
);
62 void PrintGlobalVariable(const GlobalVariable
* GVar
);
64 } // end of anonymous namespace
66 #include "BlackfinGenAsmWriter.inc"
68 extern "C" void LLVMInitializeBlackfinAsmPrinter() {
69 RegisterAsmPrinter
<BlackfinAsmPrinter
> X(TheBlackfinTarget
);
72 void BlackfinAsmPrinter::emitLinkage(const std::string
&name
,
73 GlobalValue::LinkageTypes l
) {
75 default: llvm_unreachable("Unknown linkage type!");
76 case GlobalValue::InternalLinkage
: // Symbols default to internal.
77 case GlobalValue::PrivateLinkage
:
78 case GlobalValue::LinkerPrivateLinkage
:
80 case GlobalValue::ExternalLinkage
:
81 O
<< MAI
->getGlobalDirective() << name
<< "\n";
83 case GlobalValue::LinkOnceAnyLinkage
:
84 case GlobalValue::LinkOnceODRLinkage
:
85 case GlobalValue::WeakAnyLinkage
:
86 case GlobalValue::WeakODRLinkage
:
87 O
<< MAI
->getGlobalDirective() << name
<< "\n";
88 O
<< MAI
->getWeakDefDirective() << name
<< "\n";
93 void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable
* GV
) {
94 const TargetData
*TD
= TM
.getTargetData();
96 if (!GV
->hasInitializer() || EmitSpecialLLVMGlobal(GV
))
99 std::string name
= Mang
->getMangledName(GV
);
100 Constant
*C
= GV
->getInitializer();
102 OutStreamer
.SwitchSection(getObjFileLowering().SectionForGlobal(GV
, Mang
,
104 emitLinkage(name
, GV
->getLinkage());
105 EmitAlignment(TD
->getPreferredAlignmentLog(GV
), GV
);
106 printVisibility(name
, GV
->getVisibility());
108 O
<< "\t.type " << name
<< ", STT_OBJECT\n";
109 O
<< "\t.size " << name
<< ',' << TD
->getTypeAllocSize(C
->getType()) << '\n';
111 EmitGlobalConstant(C
);
114 /// runOnMachineFunction - This uses the printInstruction()
115 /// method to print assembly for each instruction.
117 bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
118 SetupMachineFunction(MF
);
119 EmitConstantPool(MF
.getConstantPool());
120 EmitJumpTableInfo(MF
.getJumpTableInfo(), MF
);
122 const Function
*F
= MF
.getFunction();
123 OutStreamer
.SwitchSection(getObjFileLowering().SectionForGlobal(F
, Mang
, TM
));
125 emitLinkage(CurrentFnName
, F
->getLinkage());
126 printVisibility(CurrentFnName
, F
->getVisibility());
128 O
<< "\t.type\t" << CurrentFnName
<< ", STT_FUNC\n"
129 << CurrentFnName
<< ":\n";
132 DW
->BeginFunction(&MF
);
134 // Print out code for the function.
135 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
137 // Print a label for the basic block.
138 if (!VerboseAsm
&& (I
->pred_empty() || I
->isOnlyReachableByFallthrough())) {
139 // This is an entry block or a block that's only reachable via a
140 // fallthrough edge. In non-VerboseAsm mode, don't print the label.
142 EmitBasicBlockStart(I
);
146 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
148 // Print the assembly for the instruction.
149 processDebugLoc(II
->getDebugLoc());
151 printInstruction(II
);
152 if (VerboseAsm
&& !II
->getDebugLoc().isUnknown())
160 O
<< "\t.size " << CurrentFnName
<< ", .-" << CurrentFnName
<< "\n";
163 DW
->EndFunction(&MF
);
168 void BlackfinAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
) {
169 const MachineOperand
&MO
= MI
->getOperand (opNum
);
170 switch (MO
.getType()) {
171 case MachineOperand::MO_Register
:
172 assert(TargetRegisterInfo::isPhysicalRegister(MO
.getReg()) &&
173 "Virtual registers should be already mapped!");
174 O
<< getRegisterName(MO
.getReg());
177 case MachineOperand::MO_Immediate
:
180 case MachineOperand::MO_MachineBasicBlock
:
181 GetMBBSymbol(MO
.getMBB()->getNumber())->print(O
, MAI
);
183 case MachineOperand::MO_GlobalAddress
:
184 O
<< Mang
->getMangledName(MO
.getGlobal());
185 printOffset(MO
.getOffset());
187 case MachineOperand::MO_ExternalSymbol
:
188 O
<< Mang
->makeNameProper(MO
.getSymbolName());
190 case MachineOperand::MO_ConstantPoolIndex
:
191 O
<< MAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
194 case MachineOperand::MO_JumpTableIndex
:
195 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
196 << '_' << MO
.getIndex();
199 llvm_unreachable("<unknown operand type>");
204 void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr
*MI
, int opNum
) {
205 printOperand(MI
, opNum
);
207 if (MI
->getOperand(opNum
+1).isImm() && MI
->getOperand(opNum
+1).getImm() == 0)
211 printOperand(MI
, opNum
+1);
214 /// PrintAsmOperand - Print out an operand for an inline asm expression.
216 bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
,
219 const char *ExtraCode
) {
220 if (ExtraCode
&& ExtraCode
[0]) {
221 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
223 switch (ExtraCode
[0]) {
224 default: return true; // Unknown modifier.
230 printOperand(MI
, OpNo
);
235 bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
238 const char *ExtraCode
) {
239 if (ExtraCode
&& ExtraCode
[0])
240 return true; // Unknown modifier
243 printOperand(MI
, OpNo
);