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 explicit AlphaAsmPrinter(raw_ostream
&o
, TargetMachine
&tm
,
40 const TargetAsmInfo
*T
, CodeGenOpt::Level OL
,
42 : AsmPrinter(o
, tm
, T
, OL
, V
) {}
44 virtual const char *getPassName() const {
45 return "Alpha Assembly Printer";
47 bool printInstruction(const MachineInstr
*MI
);
48 void printOp(const MachineOperand
&MO
, bool IsCallOp
= false);
49 void printOperand(const MachineInstr
*MI
, int opNum
);
50 void printBaseOffsetPair (const MachineInstr
*MI
, int i
, bool brackets
=true);
51 void printModuleLevelGV(const GlobalVariable
* GVar
);
52 bool runOnMachineFunction(MachineFunction
&F
);
53 bool doInitialization(Module
&M
);
54 bool doFinalization(Module
&M
);
56 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
57 unsigned AsmVariant
, const char *ExtraCode
);
58 bool PrintAsmMemoryOperand(const MachineInstr
*MI
,
61 const char *ExtraCode
);
63 } // end of anonymous namespace
65 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
66 /// assembly code for a MachineFunction to the given output stream,
67 /// using the given target machine description. This should work
68 /// regardless of whether the function is in SSA form.
70 FunctionPass
*llvm::createAlphaCodePrinterPass(raw_ostream
&o
,
72 CodeGenOpt::Level OptLevel
,
74 return new AlphaAsmPrinter(o
, tm
, tm
.getTargetAsmInfo(), OptLevel
, verbose
);
77 #include "AlphaGenAsmWriter.inc"
79 void AlphaAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
)
81 const MachineOperand
&MO
= MI
->getOperand(opNum
);
82 if (MO
.getType() == MachineOperand::MO_Register
) {
83 assert(TargetRegisterInfo::isPhysicalRegister(MO
.getReg()) &&
85 O
<< TM
.getRegisterInfo()->get(MO
.getReg()).AsmName
;
86 } else if (MO
.isImm()) {
88 assert(MO
.getImm() < (1 << 30));
95 void AlphaAsmPrinter::printOp(const MachineOperand
&MO
, bool IsCallOp
) {
96 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
98 switch (MO
.getType()) {
99 case MachineOperand::MO_Register
:
100 O
<< RI
.get(MO
.getReg()).AsmName
;
103 case MachineOperand::MO_Immediate
:
104 cerr
<< "printOp() does not handle immediate values\n";
108 case MachineOperand::MO_MachineBasicBlock
:
109 printBasicBlockLabel(MO
.getMBB());
112 case MachineOperand::MO_ConstantPoolIndex
:
113 O
<< TAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
117 case MachineOperand::MO_ExternalSymbol
:
118 O
<< MO
.getSymbolName();
121 case MachineOperand::MO_GlobalAddress
: {
122 GlobalValue
*GV
= MO
.getGlobal();
123 O
<< Mang
->getValueName(GV
);
124 if (GV
->isDeclaration() && GV
->hasExternalWeakLinkage())
125 ExtWeakSymbols
.insert(GV
);
129 case MachineOperand::MO_JumpTableIndex
:
130 O
<< TAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
131 << '_' << MO
.getIndex();
135 O
<< "<unknown operand type: " << MO
.getType() << ">";
140 /// runOnMachineFunction - This uses the printMachineInstruction()
141 /// method to print assembly for each instruction.
143 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
146 SetupMachineFunction(MF
);
149 // Print out constants referenced by the function
150 EmitConstantPool(MF
.getConstantPool());
152 // Print out jump tables referenced by the function
153 EmitJumpTableInfo(MF
.getJumpTableInfo(), MF
);
155 // Print out labels for the function.
156 const Function
*F
= MF
.getFunction();
157 SwitchToSection(TAI
->SectionForGlobal(F
));
160 switch (F
->getLinkage()) {
161 default: assert(0 && "Unknown linkage type!");
162 case Function::InternalLinkage
: // Symbols default to internal.
163 case Function::PrivateLinkage
:
165 case Function::ExternalLinkage
:
166 O
<< "\t.globl " << CurrentFnName
<< "\n";
168 case Function::WeakAnyLinkage
:
169 case Function::WeakODRLinkage
:
170 case Function::LinkOnceAnyLinkage
:
171 case Function::LinkOnceODRLinkage
:
172 O
<< TAI
->getWeakRefDirective() << CurrentFnName
<< "\n";
176 printVisibility(CurrentFnName
, F
->getVisibility());
178 O
<< "\t.ent " << CurrentFnName
<< "\n";
180 O
<< CurrentFnName
<< ":\n";
182 // Print out code for the function.
183 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
185 if (I
!= MF
.begin()) {
186 printBasicBlockLabel(I
, true, true);
189 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
191 // Print the assembly for the instruction.
193 if (!printInstruction(II
)) {
194 assert(0 && "Unhandled instruction in asm writer!");
200 O
<< "\t.end " << CurrentFnName
<< "\n";
202 // We didn't modify anything.
206 bool AlphaAsmPrinter::doInitialization(Module
&M
)
208 if(TM
.getSubtarget
<AlphaSubtarget
>().hasCT())
209 O
<< "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
211 O
<< "\t.arch ev6\n";
212 O
<< "\t.set noat\n";
213 return AsmPrinter::doInitialization(M
);
216 void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable
* GVar
) {
217 const TargetData
*TD
= TM
.getTargetData();
219 if (!GVar
->hasInitializer()) return; // External global require no code
221 // Check to see if this is a special global used by LLVM, if so, emit it.
222 if (EmitSpecialLLVMGlobal(GVar
))
225 std::string name
= Mang
->getValueName(GVar
);
226 Constant
*C
= GVar
->getInitializer();
227 unsigned Size
= TD
->getTypeAllocSize(C
->getType());
228 unsigned Align
= TD
->getPreferredAlignmentLog(GVar
);
230 // 0: Switch to section
231 SwitchToSection(TAI
->SectionForGlobal(GVar
));
233 // 1: Check visibility
234 printVisibility(name
, GVar
->getVisibility());
237 switch (GVar
->getLinkage()) {
238 case GlobalValue::LinkOnceAnyLinkage
:
239 case GlobalValue::LinkOnceODRLinkage
:
240 case GlobalValue::WeakAnyLinkage
:
241 case GlobalValue::WeakODRLinkage
:
242 case GlobalValue::CommonLinkage
:
243 O
<< TAI
->getWeakRefDirective() << name
<< '\n';
245 case GlobalValue::AppendingLinkage
:
246 case GlobalValue::ExternalLinkage
:
247 O
<< TAI
->getGlobalDirective() << name
<< "\n";
249 case GlobalValue::InternalLinkage
:
250 case GlobalValue::PrivateLinkage
:
253 assert(0 && "Unknown linkage type!");
254 cerr
<< "Unknown linkage type!\n";
258 // 3: Type, Size, Align
259 if (TAI
->hasDotTypeDotSizeDirective()) {
260 O
<< "\t.type\t" << name
<< ", @object\n";
261 O
<< "\t.size\t" << name
<< ", " << Size
<< "\n";
264 EmitAlignment(Align
, GVar
);
268 // If the initializer is a extern weak symbol, remember to emit the weak
270 if (const GlobalValue
*GV
= dyn_cast
<GlobalValue
>(C
))
271 if (GV
->hasExternalWeakLinkage())
272 ExtWeakSymbols
.insert(GV
);
274 EmitGlobalConstant(C
);
278 bool AlphaAsmPrinter::doFinalization(Module
&M
) {
279 for (Module::const_global_iterator I
= M
.global_begin(), E
= M
.global_end();
281 printModuleLevelGV(I
);
283 return AsmPrinter::doFinalization(M
);
286 /// PrintAsmOperand - Print out an operand for an inline asm expression.
288 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
290 const char *ExtraCode
) {
291 printOperand(MI
, OpNo
);
295 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
298 const char *ExtraCode
) {
299 if (ExtraCode
&& ExtraCode
[0])
300 return true; // Unknown modifier.
302 printOperand(MI
, OpNo
);