1 //===-- SparcAsmPrinter.cpp - Sparc 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 SPARC assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
17 #include "SparcInstrInfo.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/Target/TargetAsmInfo.h"
27 #include "llvm/Target/TargetData.h"
28 #include "llvm/Target/TargetMachine.h"
29 #include "llvm/Support/Mangler.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include "llvm/ADT/Statistic.h"
32 #include "llvm/ADT/StringExtras.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/MathExtras.h"
40 STATISTIC(EmittedInsts
, "Number of machine instrs printed");
43 class VISIBILITY_HIDDEN SparcAsmPrinter
: public AsmPrinter
{
44 /// We name each basic block in a Function with a unique number, so
45 /// that we can consistently refer to them later. This is cleared
46 /// at the beginning of each call to runOnMachineFunction().
48 typedef std::map
<const Value
*, unsigned> ValueMapTy
;
49 ValueMapTy NumberForBB
;
51 explicit SparcAsmPrinter(raw_ostream
&O
, TargetMachine
&TM
,
52 const TargetAsmInfo
*T
, CodeGenOpt::Level OL
,
54 : AsmPrinter(O
, TM
, T
, OL
, V
) {}
56 virtual const char *getPassName() const {
57 return "Sparc Assembly Printer";
60 void printModuleLevelGV(const GlobalVariable
* GVar
);
61 void printOperand(const MachineInstr
*MI
, int opNum
);
62 void printMemOperand(const MachineInstr
*MI
, int opNum
,
63 const char *Modifier
= 0);
64 void printCCOperand(const MachineInstr
*MI
, int opNum
);
66 bool printInstruction(const MachineInstr
*MI
); // autogenerated.
67 bool runOnMachineFunction(MachineFunction
&F
);
68 bool doInitialization(Module
&M
);
69 bool doFinalization(Module
&M
);
70 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
71 unsigned AsmVariant
, const char *ExtraCode
);
72 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
73 unsigned AsmVariant
, const char *ExtraCode
);
75 } // end of anonymous namespace
77 #include "SparcGenAsmWriter.inc"
79 /// createSparcCodePrinterPass - Returns a pass that prints the SPARC
80 /// assembly code for a MachineFunction to the given output stream,
81 /// using the given target machine description. This should work
82 /// regardless of whether the function is in SSA form.
84 FunctionPass
*llvm::createSparcCodePrinterPass(raw_ostream
&o
,
86 CodeGenOpt::Level OptLevel
,
88 return new SparcAsmPrinter(o
, tm
, tm
.getTargetAsmInfo(), OptLevel
, verbose
);
91 /// runOnMachineFunction - This uses the printInstruction()
92 /// method to print assembly for each instruction.
94 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
97 SetupMachineFunction(MF
);
99 // Print out constants referenced by the function
100 EmitConstantPool(MF
.getConstantPool());
102 // BBNumber is used here so that a given Printer will never give two
103 // BBs the same name. (If you have a better way, please let me know!)
104 static unsigned BBNumber
= 0;
108 // Print out the label for the function.
109 const Function
*F
= MF
.getFunction();
110 SwitchToSection(TAI
->SectionForGlobal(F
));
112 O
<< "\t.globl\t" << CurrentFnName
<< '\n';
114 printVisibility(CurrentFnName
, F
->getVisibility());
116 O
<< "\t.type\t" << CurrentFnName
<< ", #function\n";
117 O
<< CurrentFnName
<< ":\n";
119 // Number each basic block so that we can consistently refer to them
120 // in PC-relative references.
121 // FIXME: Why not use the MBB numbers?
123 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
125 NumberForBB
[I
->getBasicBlock()] = BBNumber
++;
128 // Print out code for the function.
129 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
131 // Print a label for the basic block.
132 if (I
!= MF
.begin()) {
133 printBasicBlockLabel(I
, true, true);
136 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
138 // Print the assembly for the instruction.
139 printInstruction(II
);
144 // We didn't modify anything.
148 void SparcAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
) {
149 const MachineOperand
&MO
= MI
->getOperand (opNum
);
150 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
151 bool CloseParen
= false;
152 if (MI
->getOpcode() == SP::SETHIi
&& !MO
.isReg() && !MO
.isImm()) {
155 } else if ((MI
->getOpcode() == SP::ORri
|| MI
->getOpcode() == SP::ADDri
) &&
156 !MO
.isReg() && !MO
.isImm()) {
160 switch (MO
.getType()) {
161 case MachineOperand::MO_Register
:
162 if (TargetRegisterInfo::isPhysicalRegister(MO
.getReg()))
163 O
<< "%" << LowercaseString (RI
.get(MO
.getReg()).AsmName
);
165 O
<< "%reg" << MO
.getReg();
168 case MachineOperand::MO_Immediate
:
169 O
<< (int)MO
.getImm();
171 case MachineOperand::MO_MachineBasicBlock
:
172 printBasicBlockLabel(MO
.getMBB());
174 case MachineOperand::MO_GlobalAddress
:
176 const GlobalValue
*GV
= MO
.getGlobal();
177 O
<< Mang
->getValueName(GV
);
180 case MachineOperand::MO_ExternalSymbol
:
181 O
<< MO
.getSymbolName();
183 case MachineOperand::MO_ConstantPoolIndex
:
184 O
<< TAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
188 O
<< "<unknown operand type>"; abort (); break;
190 if (CloseParen
) O
<< ")";
193 void SparcAsmPrinter::printMemOperand(const MachineInstr
*MI
, int opNum
,
194 const char *Modifier
) {
195 printOperand(MI
, opNum
);
197 // If this is an ADD operand, emit it like normal operands.
198 if (Modifier
&& !strcmp(Modifier
, "arith")) {
200 printOperand(MI
, opNum
+1);
204 if (MI
->getOperand(opNum
+1).isReg() &&
205 MI
->getOperand(opNum
+1).getReg() == SP::G0
)
206 return; // don't print "+%g0"
207 if (MI
->getOperand(opNum
+1).isImm() &&
208 MI
->getOperand(opNum
+1).getImm() == 0)
209 return; // don't print "+0"
212 if (MI
->getOperand(opNum
+1).isGlobal() ||
213 MI
->getOperand(opNum
+1).isCPI()) {
215 printOperand(MI
, opNum
+1);
218 printOperand(MI
, opNum
+1);
222 void SparcAsmPrinter::printCCOperand(const MachineInstr
*MI
, int opNum
) {
223 int CC
= (int)MI
->getOperand(opNum
).getImm();
224 O
<< SPARCCondCodeToString((SPCC::CondCodes
)CC
);
227 bool SparcAsmPrinter::doInitialization(Module
&M
) {
228 Mang
= new Mangler(M
, "", TAI
->getPrivateGlobalPrefix());
229 return false; // success
232 bool SparcAsmPrinter::doFinalization(Module
&M
) {
233 // Print out module-level global variables here.
234 for (Module::const_global_iterator I
= M
.global_begin(), E
= M
.global_end();
236 printModuleLevelGV(I
);
240 return AsmPrinter::doFinalization(M
);
243 void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable
* GVar
) {
244 const TargetData
*TD
= TM
.getTargetData();
246 if (!GVar
->hasInitializer())
247 return; // External global require no code
249 // Check to see if this is a special global used by LLVM, if so, emit it.
250 if (EmitSpecialLLVMGlobal(GVar
))
254 std::string name
= Mang
->getValueName(GVar
);
255 Constant
*C
= GVar
->getInitializer();
256 unsigned Size
= TD
->getTypeAllocSize(C
->getType());
257 unsigned Align
= TD
->getPreferredAlignment(GVar
);
259 printVisibility(name
, GVar
->getVisibility());
261 SwitchToSection(TAI
->SectionForGlobal(GVar
));
263 if (C
->isNullValue() && !GVar
->hasSection()) {
264 if (!GVar
->isThreadLocal() &&
265 (GVar
->hasLocalLinkage() || GVar
->isWeakForLinker())) {
266 if (Size
== 0) Size
= 1; // .comm Foo, 0 is undefined, avoid it.
268 if (GVar
->hasLocalLinkage())
269 O
<< "\t.local " << name
<< '\n';
271 O
<< TAI
->getCOMMDirective() << name
<< ',' << Size
;
272 if (TAI
->getCOMMDirectiveTakesAlignment())
273 O
<< ',' << (1 << Align
);
280 switch (GVar
->getLinkage()) {
281 case GlobalValue::CommonLinkage
:
282 case GlobalValue::LinkOnceAnyLinkage
:
283 case GlobalValue::LinkOnceODRLinkage
:
284 case GlobalValue::WeakAnyLinkage
: // FIXME: Verify correct for weak.
285 case GlobalValue::WeakODRLinkage
: // FIXME: Verify correct for weak.
286 // Nonnull linkonce -> weak
287 O
<< "\t.weak " << name
<< '\n';
289 case GlobalValue::AppendingLinkage
:
290 // FIXME: appending linkage variables should go into a section of
291 // their name or something. For now, just emit them as external.
292 case GlobalValue::ExternalLinkage
:
293 // If external or appending, declare as a global symbol
294 O
<< TAI
->getGlobalDirective() << name
<< '\n';
296 case GlobalValue::PrivateLinkage
:
297 case GlobalValue::InternalLinkage
:
299 case GlobalValue::GhostLinkage
:
300 cerr
<< "Should not have any unmaterialized functions!\n";
302 case GlobalValue::DLLImportLinkage
:
303 cerr
<< "DLLImport linkage is not supported by this target!\n";
305 case GlobalValue::DLLExportLinkage
:
306 cerr
<< "DLLExport linkage is not supported by this target!\n";
309 assert(0 && "Unknown linkage type!");
312 EmitAlignment(Align
, GVar
);
314 if (TAI
->hasDotTypeDotSizeDirective()) {
315 O
<< "\t.type " << name
<< ",#object\n";
316 O
<< "\t.size " << name
<< ',' << Size
<< '\n';
320 EmitGlobalConstant(C
);
323 /// PrintAsmOperand - Print out an operand for an inline asm expression.
325 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
327 const char *ExtraCode
) {
328 if (ExtraCode
&& ExtraCode
[0]) {
329 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
331 switch (ExtraCode
[0]) {
332 default: return true; // Unknown modifier.
338 printOperand(MI
, OpNo
);
343 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
346 const char *ExtraCode
) {
347 if (ExtraCode
&& ExtraCode
[0])
348 return true; // Unknown modifier
351 printMemOperand(MI
, OpNo
);