1 //===-- AlphaAsmPrinter.cpp - Alpha 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 Alpha assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
17 #include "AlphaInstrInfo.h"
18 #include "AlphaTargetMachine.h"
19 #include "llvm/Module.h"
20 #include "llvm/Type.h"
21 #include "llvm/Assembly/Writer.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/Target/TargetAsmInfo.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/Mangler.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/ADT/Statistic.h"
32 STATISTIC(EmittedInsts
, "Number of machine instrs printed");
35 struct VISIBILITY_HIDDEN AlphaAsmPrinter
: public AsmPrinter
{
36 /// Unique incrementer for label values for referencing Global values.
39 AlphaAsmPrinter(raw_ostream
&o
, TargetMachine
&tm
,
40 const TargetAsmInfo
*T
, bool F
, bool V
)
41 : AsmPrinter(o
, tm
, T
, F
, V
) {}
43 virtual const char *getPassName() const {
44 return "Alpha Assembly Printer";
46 bool printInstruction(const MachineInstr
*MI
);
47 void printOp(const MachineOperand
&MO
, bool IsCallOp
= false);
48 void printOperand(const MachineInstr
*MI
, int opNum
);
49 void printBaseOffsetPair (const MachineInstr
*MI
, int i
, bool brackets
=true);
50 void printModuleLevelGV(const GlobalVariable
* GVar
);
51 bool runOnMachineFunction(MachineFunction
&F
);
52 bool doInitialization(Module
&M
);
53 bool doFinalization(Module
&M
);
55 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
56 unsigned AsmVariant
, const char *ExtraCode
);
57 bool PrintAsmMemoryOperand(const MachineInstr
*MI
,
60 const char *ExtraCode
);
62 } // end of anonymous namespace
64 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
65 /// assembly code for a MachineFunction to the given output stream,
66 /// using the given target machine description. This should work
67 /// regardless of whether the function is in SSA form.
69 FunctionPass
*llvm::createAlphaCodePrinterPass(raw_ostream
&o
,
71 bool fast
, bool verbose
) {
72 return new AlphaAsmPrinter(o
, tm
, tm
.getTargetAsmInfo(), fast
, verbose
);
75 #include "AlphaGenAsmWriter.inc"
77 void AlphaAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
)
79 const MachineOperand
&MO
= MI
->getOperand(opNum
);
80 if (MO
.getType() == MachineOperand::MO_Register
) {
81 assert(TargetRegisterInfo::isPhysicalRegister(MO
.getReg()) &&
83 O
<< TM
.getRegisterInfo()->get(MO
.getReg()).AsmName
;
84 } else if (MO
.isImm()) {
86 assert(MO
.getImm() < (1 << 30));
93 void AlphaAsmPrinter::printOp(const MachineOperand
&MO
, bool IsCallOp
) {
94 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
96 switch (MO
.getType()) {
97 case MachineOperand::MO_Register
:
98 O
<< RI
.get(MO
.getReg()).AsmName
;
101 case MachineOperand::MO_Immediate
:
102 cerr
<< "printOp() does not handle immediate values\n";
106 case MachineOperand::MO_MachineBasicBlock
:
107 printBasicBlockLabel(MO
.getMBB());
110 case MachineOperand::MO_ConstantPoolIndex
:
111 O
<< TAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
115 case MachineOperand::MO_ExternalSymbol
:
116 O
<< MO
.getSymbolName();
119 case MachineOperand::MO_GlobalAddress
: {
120 GlobalValue
*GV
= MO
.getGlobal();
121 O
<< Mang
->getValueName(GV
);
122 if (GV
->isDeclaration() && GV
->hasExternalWeakLinkage())
123 ExtWeakSymbols
.insert(GV
);
127 case MachineOperand::MO_JumpTableIndex
:
128 O
<< TAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
129 << '_' << MO
.getIndex();
133 O
<< "<unknown operand type: " << MO
.getType() << ">";
138 /// runOnMachineFunction - This uses the printMachineInstruction()
139 /// method to print assembly for each instruction.
141 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
144 SetupMachineFunction(MF
);
147 // Print out constants referenced by the function
148 EmitConstantPool(MF
.getConstantPool());
150 // Print out jump tables referenced by the function
151 EmitJumpTableInfo(MF
.getJumpTableInfo(), MF
);
153 // Print out labels for the function.
154 const Function
*F
= MF
.getFunction();
155 SwitchToSection(TAI
->SectionForGlobal(F
));
158 switch (F
->getLinkage()) {
159 default: assert(0 && "Unknown linkage type!");
160 case Function::InternalLinkage
: // Symbols default to internal.
161 case Function::PrivateLinkage
:
163 case Function::ExternalLinkage
:
164 O
<< "\t.globl " << CurrentFnName
<< "\n";
166 case Function::WeakAnyLinkage
:
167 case Function::WeakODRLinkage
:
168 case Function::LinkOnceAnyLinkage
:
169 case Function::LinkOnceODRLinkage
:
170 O
<< TAI
->getWeakRefDirective() << CurrentFnName
<< "\n";
174 printVisibility(CurrentFnName
, F
->getVisibility());
176 O
<< "\t.ent " << CurrentFnName
<< "\n";
178 O
<< CurrentFnName
<< ":\n";
180 // Print out code for the function.
181 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
183 if (I
!= MF
.begin()) {
184 printBasicBlockLabel(I
, true, true);
187 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
189 // Print the assembly for the instruction.
191 if (!printInstruction(II
)) {
192 assert(0 && "Unhandled instruction in asm writer!");
198 O
<< "\t.end " << CurrentFnName
<< "\n";
200 // We didn't modify anything.
204 bool AlphaAsmPrinter::doInitialization(Module
&M
)
206 if(TM
.getSubtarget
<AlphaSubtarget
>().hasCT())
207 O
<< "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
209 O
<< "\t.arch ev6\n";
210 O
<< "\t.set noat\n";
211 return AsmPrinter::doInitialization(M
);
214 void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable
* GVar
) {
215 const TargetData
*TD
= TM
.getTargetData();
217 if (!GVar
->hasInitializer()) return; // External global require no code
219 // Check to see if this is a special global used by LLVM, if so, emit it.
220 if (EmitSpecialLLVMGlobal(GVar
))
223 std::string name
= Mang
->getValueName(GVar
);
224 Constant
*C
= GVar
->getInitializer();
225 unsigned Size
= TD
->getTypePaddedSize(C
->getType());
226 unsigned Align
= TD
->getPreferredAlignmentLog(GVar
);
228 // 0: Switch to section
229 SwitchToSection(TAI
->SectionForGlobal(GVar
));
231 // 1: Check visibility
232 printVisibility(name
, GVar
->getVisibility());
235 switch (GVar
->getLinkage()) {
236 case GlobalValue::LinkOnceAnyLinkage
:
237 case GlobalValue::LinkOnceODRLinkage
:
238 case GlobalValue::WeakAnyLinkage
:
239 case GlobalValue::WeakODRLinkage
:
240 case GlobalValue::CommonLinkage
:
241 O
<< TAI
->getWeakRefDirective() << name
<< '\n';
243 case GlobalValue::AppendingLinkage
:
244 case GlobalValue::ExternalLinkage
:
245 O
<< TAI
->getGlobalDirective() << name
<< "\n";
247 case GlobalValue::InternalLinkage
:
248 case GlobalValue::PrivateLinkage
:
251 assert(0 && "Unknown linkage type!");
252 cerr
<< "Unknown linkage type!\n";
256 // 3: Type, Size, Align
257 if (TAI
->hasDotTypeDotSizeDirective()) {
258 O
<< "\t.type\t" << name
<< ", @object\n";
259 O
<< "\t.size\t" << name
<< ", " << Size
<< "\n";
262 EmitAlignment(Align
, GVar
);
266 // If the initializer is a extern weak symbol, remember to emit the weak
268 if (const GlobalValue
*GV
= dyn_cast
<GlobalValue
>(C
))
269 if (GV
->hasExternalWeakLinkage())
270 ExtWeakSymbols
.insert(GV
);
272 EmitGlobalConstant(C
);
276 bool AlphaAsmPrinter::doFinalization(Module
&M
) {
277 for (Module::const_global_iterator I
= M
.global_begin(), E
= M
.global_end();
279 printModuleLevelGV(I
);
281 return AsmPrinter::doFinalization(M
);
284 /// PrintAsmOperand - Print out an operand for an inline asm expression.
286 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
288 const char *ExtraCode
) {
289 printOperand(MI
, OpNo
);
293 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
296 const char *ExtraCode
) {
297 if (ExtraCode
&& ExtraCode
[0])
298 return true; // Unknown modifier.
300 printOperand(MI
, OpNo
);