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 "SparcTargetMachine.h"
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Module.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineConstantPool.h"
26 #include "llvm/CodeGen/MachineInstr.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/Target/TargetLoweringObjectFile.h"
31 #include "llvm/Target/TargetRegistry.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/FormattedStream.h"
37 #include "llvm/Support/Mangler.h"
38 #include "llvm/Support/MathExtras.h"
44 STATISTIC(EmittedInsts
, "Number of machine instrs printed");
47 class VISIBILITY_HIDDEN SparcAsmPrinter
: public AsmPrinter
{
48 /// We name each basic block in a Function with a unique number, so
49 /// that we can consistently refer to them later. This is cleared
50 /// at the beginning of each call to runOnMachineFunction().
52 typedef std::map
<const Value
*, unsigned> ValueMapTy
;
53 ValueMapTy NumberForBB
;
56 explicit SparcAsmPrinter(formatted_raw_ostream
&O
, TargetMachine
&TM
,
57 const MCAsmInfo
*T
, bool V
)
58 : AsmPrinter(O
, TM
, T
, V
), BBNumber(0) {}
60 virtual const char *getPassName() const {
61 return "Sparc Assembly Printer";
64 void PrintGlobalVariable(const GlobalVariable
*GVar
);
65 void printOperand(const MachineInstr
*MI
, int opNum
);
66 void printMemOperand(const MachineInstr
*MI
, int opNum
,
67 const char *Modifier
= 0);
68 void printCCOperand(const MachineInstr
*MI
, int opNum
);
70 void printInstruction(const MachineInstr
*MI
); // autogenerated.
71 static const char *getRegisterName(unsigned RegNo
);
73 bool runOnMachineFunction(MachineFunction
&F
);
74 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
75 unsigned AsmVariant
, const char *ExtraCode
);
76 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
77 unsigned AsmVariant
, const char *ExtraCode
);
79 } // end of anonymous namespace
81 #include "SparcGenAsmWriter.inc"
84 /// runOnMachineFunction - This uses the printInstruction()
85 /// method to print assembly for each instruction.
87 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
90 SetupMachineFunction(MF
);
92 // Print out constants referenced by the function
93 EmitConstantPool(MF
.getConstantPool());
95 // BBNumber is used here so that a given Printer will never give two
96 // BBs the same name. (If you have a better way, please let me know!)
100 // Print out the label for the function.
101 const Function
*F
= MF
.getFunction();
102 OutStreamer
.SwitchSection(getObjFileLowering().SectionForGlobal(F
, Mang
, TM
));
103 EmitAlignment(MF
.getAlignment(), F
);
104 O
<< "\t.globl\t" << CurrentFnName
<< '\n';
106 printVisibility(CurrentFnName
, F
->getVisibility());
108 O
<< "\t.type\t" << CurrentFnName
<< ", #function\n";
109 O
<< CurrentFnName
<< ":\n";
110 // Emit pre-function debug information.
111 DW
->BeginFunction(&MF
);
113 // Number each basic block so that we can consistently refer to them
114 // in PC-relative references.
115 // FIXME: Why not use the MBB numbers?
117 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
119 NumberForBB
[I
->getBasicBlock()] = BBNumber
++;
122 // Print out code for the function.
123 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
125 // Print a label for the basic block.
126 if (I
!= MF
.begin()) {
127 EmitBasicBlockStart(I
);
130 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
132 // Print the assembly for the instruction.
133 processDebugLoc(II
->getDebugLoc());
134 printInstruction(II
);
136 if (VerboseAsm
&& !II
->getDebugLoc().isUnknown())
144 // Emit post-function debug information.
145 DW
->EndFunction(&MF
);
147 // We didn't modify anything.
151 void SparcAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
) {
152 const MachineOperand
&MO
= MI
->getOperand (opNum
);
153 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
154 bool CloseParen
= false;
155 if (MI
->getOpcode() == SP::SETHIi
&& !MO
.isReg() && !MO
.isImm()) {
158 } else if ((MI
->getOpcode() == SP::ORri
|| MI
->getOpcode() == SP::ADDri
) &&
159 !MO
.isReg() && !MO
.isImm()) {
163 switch (MO
.getType()) {
164 case MachineOperand::MO_Register
:
165 O
<< "%" << LowercaseString(getRegisterName(MO
.getReg()));
168 case MachineOperand::MO_Immediate
:
169 O
<< (int)MO
.getImm();
171 case MachineOperand::MO_MachineBasicBlock
:
172 GetMBBSymbol(MO
.getMBB()->getNumber())->print(O
, MAI
);
174 case MachineOperand::MO_GlobalAddress
:
175 O
<< Mang
->getMangledName(MO
.getGlobal());
177 case MachineOperand::MO_ExternalSymbol
:
178 O
<< MO
.getSymbolName();
180 case MachineOperand::MO_ConstantPoolIndex
:
181 O
<< MAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
185 llvm_unreachable("<unknown operand type>");
187 if (CloseParen
) O
<< ")";
190 void SparcAsmPrinter::printMemOperand(const MachineInstr
*MI
, int opNum
,
191 const char *Modifier
) {
192 printOperand(MI
, opNum
);
194 // If this is an ADD operand, emit it like normal operands.
195 if (Modifier
&& !strcmp(Modifier
, "arith")) {
197 printOperand(MI
, opNum
+1);
201 if (MI
->getOperand(opNum
+1).isReg() &&
202 MI
->getOperand(opNum
+1).getReg() == SP::G0
)
203 return; // don't print "+%g0"
204 if (MI
->getOperand(opNum
+1).isImm() &&
205 MI
->getOperand(opNum
+1).getImm() == 0)
206 return; // don't print "+0"
209 if (MI
->getOperand(opNum
+1).isGlobal() ||
210 MI
->getOperand(opNum
+1).isCPI()) {
212 printOperand(MI
, opNum
+1);
215 printOperand(MI
, opNum
+1);
219 void SparcAsmPrinter::printCCOperand(const MachineInstr
*MI
, int opNum
) {
220 int CC
= (int)MI
->getOperand(opNum
).getImm();
221 O
<< SPARCCondCodeToString((SPCC::CondCodes
)CC
);
224 void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable
* GVar
) {
225 const TargetData
*TD
= TM
.getTargetData();
227 if (!GVar
->hasInitializer())
228 return; // External global require no code
230 // Check to see if this is a special global used by LLVM, if so, emit it.
231 if (EmitSpecialLLVMGlobal(GVar
))
235 std::string name
= Mang
->getMangledName(GVar
);
236 Constant
*C
= GVar
->getInitializer();
237 unsigned Size
= TD
->getTypeAllocSize(C
->getType());
238 unsigned Align
= TD
->getPreferredAlignment(GVar
);
240 printVisibility(name
, GVar
->getVisibility());
242 OutStreamer
.SwitchSection(getObjFileLowering().SectionForGlobal(GVar
, Mang
,
245 if (C
->isNullValue() && !GVar
->hasSection()) {
246 if (!GVar
->isThreadLocal() &&
247 (GVar
->hasLocalLinkage() || GVar
->isWeakForLinker())) {
248 if (Size
== 0) Size
= 1; // .comm Foo, 0 is undefined, avoid it.
250 if (GVar
->hasLocalLinkage())
251 O
<< "\t.local " << name
<< '\n';
253 O
<< MAI
->getCOMMDirective() << name
<< ',' << Size
;
254 if (MAI
->getCOMMDirectiveTakesAlignment())
255 O
<< ',' << (1 << Align
);
262 switch (GVar
->getLinkage()) {
263 case GlobalValue::CommonLinkage
:
264 case GlobalValue::LinkOnceAnyLinkage
:
265 case GlobalValue::LinkOnceODRLinkage
:
266 case GlobalValue::WeakAnyLinkage
: // FIXME: Verify correct for weak.
267 case GlobalValue::WeakODRLinkage
: // FIXME: Verify correct for weak.
268 // Nonnull linkonce -> weak
269 O
<< "\t.weak " << name
<< '\n';
271 case GlobalValue::AppendingLinkage
:
272 // FIXME: appending linkage variables should go into a section of
273 // their name or something. For now, just emit them as external.
274 case GlobalValue::ExternalLinkage
:
275 // If external or appending, declare as a global symbol
276 O
<< MAI
->getGlobalDirective() << name
<< '\n';
278 case GlobalValue::PrivateLinkage
:
279 case GlobalValue::LinkerPrivateLinkage
:
280 case GlobalValue::InternalLinkage
:
282 case GlobalValue::GhostLinkage
:
283 llvm_unreachable("Should not have any unmaterialized functions!");
284 case GlobalValue::DLLImportLinkage
:
285 llvm_unreachable("DLLImport linkage is not supported by this target!");
286 case GlobalValue::DLLExportLinkage
:
287 llvm_unreachable("DLLExport linkage is not supported by this target!");
289 llvm_unreachable("Unknown linkage type!");
292 EmitAlignment(Align
, GVar
);
294 if (MAI
->hasDotTypeDotSizeDirective()) {
295 O
<< "\t.type " << name
<< ",#object\n";
296 O
<< "\t.size " << name
<< ',' << Size
<< '\n';
300 EmitGlobalConstant(C
);
303 /// PrintAsmOperand - Print out an operand for an inline asm expression.
305 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
307 const char *ExtraCode
) {
308 if (ExtraCode
&& ExtraCode
[0]) {
309 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
311 switch (ExtraCode
[0]) {
312 default: return true; // Unknown modifier.
318 printOperand(MI
, OpNo
);
323 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
326 const char *ExtraCode
) {
327 if (ExtraCode
&& ExtraCode
[0])
328 return true; // Unknown modifier
331 printMemOperand(MI
, OpNo
);
337 // Force static initialization.
338 extern "C" void LLVMInitializeSparcAsmPrinter() {
339 RegisterAsmPrinter
<SparcAsmPrinter
> X(TheSparcTarget
);