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 SparcAsmPrinter(raw_ostream
&O
, TargetMachine
&TM
,
52 const TargetAsmInfo
*T
, bool F
, bool V
)
53 : AsmPrinter(O
, TM
, T
, F
, V
) {}
55 virtual const char *getPassName() const {
56 return "Sparc Assembly Printer";
59 void printModuleLevelGV(const GlobalVariable
* GVar
);
60 void printOperand(const MachineInstr
*MI
, int opNum
);
61 void printMemOperand(const MachineInstr
*MI
, int opNum
,
62 const char *Modifier
= 0);
63 void printCCOperand(const MachineInstr
*MI
, int opNum
);
65 bool printInstruction(const MachineInstr
*MI
); // autogenerated.
66 bool runOnMachineFunction(MachineFunction
&F
);
67 bool doInitialization(Module
&M
);
68 bool doFinalization(Module
&M
);
69 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
70 unsigned AsmVariant
, const char *ExtraCode
);
71 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
72 unsigned AsmVariant
, const char *ExtraCode
);
74 } // end of anonymous namespace
76 #include "SparcGenAsmWriter.inc"
78 /// createSparcCodePrinterPass - Returns a pass that prints the SPARC
79 /// assembly code for a MachineFunction to the given output stream,
80 /// using the given target machine description. This should work
81 /// regardless of whether the function is in SSA form.
83 FunctionPass
*llvm::createSparcCodePrinterPass(raw_ostream
&o
,
85 bool fast
, bool verbose
) {
86 return new SparcAsmPrinter(o
, tm
, tm
.getTargetAsmInfo(), fast
, verbose
);
89 /// runOnMachineFunction - This uses the printInstruction()
90 /// method to print assembly for each instruction.
92 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
95 SetupMachineFunction(MF
);
97 // Print out constants referenced by the function
98 EmitConstantPool(MF
.getConstantPool());
100 // BBNumber is used here so that a given Printer will never give two
101 // BBs the same name. (If you have a better way, please let me know!)
102 static unsigned BBNumber
= 0;
106 // Print out the label for the function.
107 const Function
*F
= MF
.getFunction();
108 SwitchToSection(TAI
->SectionForGlobal(F
));
110 O
<< "\t.globl\t" << CurrentFnName
<< '\n';
112 printVisibility(CurrentFnName
, F
->getVisibility());
114 O
<< "\t.type\t" << CurrentFnName
<< ", #function\n";
115 O
<< CurrentFnName
<< ":\n";
117 // Number each basic block so that we can consistently refer to them
118 // in PC-relative references.
119 // FIXME: Why not use the MBB numbers?
121 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
123 NumberForBB
[I
->getBasicBlock()] = BBNumber
++;
126 // Print out code for the function.
127 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
129 // Print a label for the basic block.
130 if (I
!= MF
.begin()) {
131 printBasicBlockLabel(I
, true, true);
134 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
136 // Print the assembly for the instruction.
137 printInstruction(II
);
142 // We didn't modify anything.
146 void SparcAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
) {
147 const MachineOperand
&MO
= MI
->getOperand (opNum
);
148 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
149 bool CloseParen
= false;
150 if (MI
->getOpcode() == SP::SETHIi
&& !MO
.isReg() && !MO
.isImm()) {
153 } else if ((MI
->getOpcode() == SP::ORri
|| MI
->getOpcode() == SP::ADDri
) &&
154 !MO
.isReg() && !MO
.isImm()) {
158 switch (MO
.getType()) {
159 case MachineOperand::MO_Register
:
160 if (TargetRegisterInfo::isPhysicalRegister(MO
.getReg()))
161 O
<< "%" << LowercaseString (RI
.get(MO
.getReg()).AsmName
);
163 O
<< "%reg" << MO
.getReg();
166 case MachineOperand::MO_Immediate
:
167 O
<< (int)MO
.getImm();
169 case MachineOperand::MO_MachineBasicBlock
:
170 printBasicBlockLabel(MO
.getMBB());
172 case MachineOperand::MO_GlobalAddress
:
174 const GlobalValue
*GV
= MO
.getGlobal();
175 O
<< Mang
->getValueName(GV
);
178 case MachineOperand::MO_ExternalSymbol
:
179 O
<< MO
.getSymbolName();
181 case MachineOperand::MO_ConstantPoolIndex
:
182 O
<< TAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
186 O
<< "<unknown operand type>"; abort (); break;
188 if (CloseParen
) O
<< ")";
191 void SparcAsmPrinter::printMemOperand(const MachineInstr
*MI
, int opNum
,
192 const char *Modifier
) {
193 printOperand(MI
, opNum
);
195 // If this is an ADD operand, emit it like normal operands.
196 if (Modifier
&& !strcmp(Modifier
, "arith")) {
198 printOperand(MI
, opNum
+1);
202 if (MI
->getOperand(opNum
+1).isReg() &&
203 MI
->getOperand(opNum
+1).getReg() == SP::G0
)
204 return; // don't print "+%g0"
205 if (MI
->getOperand(opNum
+1).isImm() &&
206 MI
->getOperand(opNum
+1).getImm() == 0)
207 return; // don't print "+0"
210 if (MI
->getOperand(opNum
+1).isGlobal() ||
211 MI
->getOperand(opNum
+1).isCPI()) {
213 printOperand(MI
, opNum
+1);
216 printOperand(MI
, opNum
+1);
220 void SparcAsmPrinter::printCCOperand(const MachineInstr
*MI
, int opNum
) {
221 int CC
= (int)MI
->getOperand(opNum
).getImm();
222 O
<< SPARCCondCodeToString((SPCC::CondCodes
)CC
);
225 bool SparcAsmPrinter::doInitialization(Module
&M
) {
226 Mang
= new Mangler(M
, "", TAI
->getPrivateGlobalPrefix());
227 return false; // success
230 bool SparcAsmPrinter::doFinalization(Module
&M
) {
231 // Print out module-level global variables here.
232 for (Module::const_global_iterator I
= M
.global_begin(), E
= M
.global_end();
234 printModuleLevelGV(I
);
238 return AsmPrinter::doFinalization(M
);
241 void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable
* GVar
) {
242 const TargetData
*TD
= TM
.getTargetData();
244 if (!GVar
->hasInitializer())
245 return; // External global require no code
247 // Check to see if this is a special global used by LLVM, if so, emit it.
248 if (EmitSpecialLLVMGlobal(GVar
))
252 std::string name
= Mang
->getValueName(GVar
);
253 Constant
*C
= GVar
->getInitializer();
254 unsigned Size
= TD
->getTypePaddedSize(C
->getType());
255 unsigned Align
= TD
->getPreferredAlignment(GVar
);
257 printVisibility(name
, GVar
->getVisibility());
259 SwitchToSection(TAI
->SectionForGlobal(GVar
));
261 if (C
->isNullValue() && !GVar
->hasSection()) {
262 if (!GVar
->isThreadLocal() &&
263 (GVar
->hasLocalLinkage() || GVar
->isWeakForLinker())) {
264 if (Size
== 0) Size
= 1; // .comm Foo, 0 is undefined, avoid it.
266 if (GVar
->hasLocalLinkage())
267 O
<< "\t.local " << name
<< '\n';
269 O
<< TAI
->getCOMMDirective() << name
<< ',' << Size
;
270 if (TAI
->getCOMMDirectiveTakesAlignment())
271 O
<< ',' << (1 << Align
);
278 switch (GVar
->getLinkage()) {
279 case GlobalValue::CommonLinkage
:
280 case GlobalValue::LinkOnceAnyLinkage
:
281 case GlobalValue::LinkOnceODRLinkage
:
282 case GlobalValue::WeakAnyLinkage
: // FIXME: Verify correct for weak.
283 case GlobalValue::WeakODRLinkage
: // FIXME: Verify correct for weak.
284 // Nonnull linkonce -> weak
285 O
<< "\t.weak " << name
<< '\n';
287 case GlobalValue::AppendingLinkage
:
288 // FIXME: appending linkage variables should go into a section of
289 // their name or something. For now, just emit them as external.
290 case GlobalValue::ExternalLinkage
:
291 // If external or appending, declare as a global symbol
292 O
<< TAI
->getGlobalDirective() << name
<< '\n';
294 case GlobalValue::PrivateLinkage
:
295 case GlobalValue::InternalLinkage
:
297 case GlobalValue::GhostLinkage
:
298 cerr
<< "Should not have any unmaterialized functions!\n";
300 case GlobalValue::DLLImportLinkage
:
301 cerr
<< "DLLImport linkage is not supported by this target!\n";
303 case GlobalValue::DLLExportLinkage
:
304 cerr
<< "DLLExport linkage is not supported by this target!\n";
307 assert(0 && "Unknown linkage type!");
310 EmitAlignment(Align
, GVar
);
312 if (TAI
->hasDotTypeDotSizeDirective()) {
313 O
<< "\t.type " << name
<< ",#object\n";
314 O
<< "\t.size " << name
<< ',' << Size
<< '\n';
318 EmitGlobalConstant(C
);
321 /// PrintAsmOperand - Print out an operand for an inline asm expression.
323 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
325 const char *ExtraCode
) {
326 if (ExtraCode
&& ExtraCode
[0]) {
327 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
329 switch (ExtraCode
[0]) {
330 default: return true; // Unknown modifier.
336 printOperand(MI
, OpNo
);
341 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
344 const char *ExtraCode
) {
345 if (ExtraCode
&& ExtraCode
[0])
346 return true; // Unknown modifier
349 printMemOperand(MI
, OpNo
);