blob: cc320e5a2bc4f43778cf9b6acc8ce0763456762e [file] [log] [blame]
pingbakddfd8692008-11-08 18:59:02 +00001//===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to Cell SPU assembly language. This printer
12// is the output mechanism used by `llc'.
13//
14//===----------------------------------------------------------------------===//
15
16#define DEBUG_TYPE "asmprinter"
17#include "SPU.h"
18#include "SPUTargetMachine.h"
19#include "llvm/Constants.h"
20#include "llvm/DerivedTypes.h"
21#include "llvm/Module.h"
22#include "llvm/Assembly/Writer.h"
23#include "llvm/CodeGen/AsmPrinter.h"
24#include "llvm/CodeGen/DwarfWriter.h"
25#include "llvm/CodeGen/MachineModuleInfo.h"
26#include "llvm/CodeGen/MachineFunctionPass.h"
27#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner73266f92009-08-19 05:49:37 +000028#include "llvm/MC/MCStreamer.h"
Chris Lattner621c44d2009-08-22 20:48:53 +000029#include "llvm/MC/MCAsmInfo.h"
Chris Lattnerc6f802d2009-09-13 17:14:04 +000030#include "llvm/MC/MCSymbol.h"
Chris Lattnerc4c40a92009-07-28 03:13:23 +000031#include "llvm/Target/TargetLoweringObjectFile.h"
pingbakddfd8692008-11-08 18:59:02 +000032#include "llvm/Target/TargetInstrInfo.h"
33#include "llvm/Target/TargetOptions.h"
Chris Lattnerc4c40a92009-07-28 03:13:23 +000034#include "llvm/Target/TargetRegisterInfo.h"
Daniel Dunbarfe5939f2009-07-15 20:24:03 +000035#include "llvm/Target/TargetRegistry.h"
pingbakddfd8692008-11-08 18:59:02 +000036#include "llvm/ADT/Statistic.h"
37#include "llvm/ADT/StringExtras.h"
Chris Lattner73266f92009-08-19 05:49:37 +000038#include "llvm/Support/CommandLine.h"
39#include "llvm/Support/Compiler.h"
40#include "llvm/Support/Debug.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/FormattedStream.h"
43#include "llvm/Support/Mangler.h"
44#include "llvm/Support/MathExtras.h"
pingbakddfd8692008-11-08 18:59:02 +000045#include <set>
46using namespace llvm;
47
48namespace {
49 STATISTIC(EmittedInsts, "Number of machine instrs printed");
50
51 const std::string bss_section(".bss");
52
Bill Wendling4f405312009-02-24 08:30:20 +000053 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
pingbakddfd8692008-11-08 18:59:02 +000054 std::set<std::string> FnStubs, GVStubs;
Bill Wendling4f405312009-02-24 08:30:20 +000055 public:
David Greene302008d2009-07-14 20:18:05 +000056 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
Chris Lattner621c44d2009-08-22 20:48:53 +000057 const MCAsmInfo *T, bool V) :
Daniel Dunbarb10d2222009-07-01 01:48:54 +000058 AsmPrinter(O, TM, T, V) {}
pingbakddfd8692008-11-08 18:59:02 +000059
60 virtual const char *getPassName() const {
61 return "STI CBEA SPU Assembly Printer";
62 }
63
64 SPUTargetMachine &getTM() {
65 return static_cast<SPUTargetMachine&>(TM);
66 }
67
68 /// printInstruction - This method is automatically generated by tablegen
69 /// from the instruction set description. This method returns true if the
70 /// machine instruction was sufficiently described to print it, otherwise it
71 /// returns false.
Chris Lattnerddb259a2009-08-08 01:32:19 +000072 void printInstruction(const MachineInstr *MI);
pingbakddfd8692008-11-08 18:59:02 +000073
74 void printMachineInstruction(const MachineInstr *MI);
75 void printOp(const MachineOperand &MO);
76
77 /// printRegister - Print register according to target requirements.
78 ///
79 void printRegister(const MachineOperand &MO, bool R0AsZero) {
80 unsigned RegNo = MO.getReg();
81 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
82 "Not physreg??");
83 O << TM.getRegisterInfo()->get(RegNo).AsmName;
84 }
85
86 void printOperand(const MachineInstr *MI, unsigned OpNo) {
87 const MachineOperand &MO = MI->getOperand(OpNo);
88 if (MO.isReg()) {
89 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
90 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
91 } else if (MO.isImm()) {
92 O << MO.getImm();
93 } else {
94 printOp(MO);
95 }
96 }
Scott Michelc899a122009-01-26 22:33:37 +000097
pingbakddfd8692008-11-08 18:59:02 +000098 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
99 unsigned AsmVariant, const char *ExtraCode);
100 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
101 unsigned AsmVariant, const char *ExtraCode);
Scott Michelc899a122009-01-26 22:33:37 +0000102
103
pingbakddfd8692008-11-08 18:59:02 +0000104 void
105 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
106 {
107 int value = MI->getOperand(OpNo).getImm();
108 value = (value << (32 - 7)) >> (32 - 7);
109
110 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
111 && "Invalid s7 argument");
112 O << value;
113 }
114
115 void
116 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
117 {
118 unsigned int value = MI->getOperand(OpNo).getImm();
119 assert(value < (1 << 8) && "Invalid u7 argument");
120 O << value;
121 }
Scott Michelc899a122009-01-26 22:33:37 +0000122
pingbakddfd8692008-11-08 18:59:02 +0000123 void
Scott Michel06eabde2008-12-27 04:51:36 +0000124 printShufAddr(const MachineInstr *MI, unsigned OpNo)
pingbakddfd8692008-11-08 18:59:02 +0000125 {
126 char value = MI->getOperand(OpNo).getImm();
127 O << (int) value;
128 O << "(";
129 printOperand(MI, OpNo+1);
130 O << ")";
131 }
132
133 void
134 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
135 {
136 O << (short) MI->getOperand(OpNo).getImm();
137 }
138
139 void
140 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
141 {
142 O << (unsigned short)MI->getOperand(OpNo).getImm();
143 }
144
145 void
146 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
147 {
148 O << (unsigned)MI->getOperand(OpNo).getImm();
149 }
Scott Michelc899a122009-01-26 22:33:37 +0000150
pingbakddfd8692008-11-08 18:59:02 +0000151 void
152 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
153 // When used as the base register, r0 reads constant zero rather than
154 // the value contained in the register. For this reason, the darwin
155 // assembler requires that we print r0 as 0 (no r) when used as the base.
156 const MachineOperand &MO = MI->getOperand(OpNo);
157 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
158 O << ", ";
159 printOperand(MI, OpNo+1);
160 }
161
162 void
163 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
164 {
165 unsigned int value = MI->getOperand(OpNo).getImm();
166 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
167 O << value;
168 }
169
170 void
171 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
172 {
173 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
174 >> 16);
175 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
176 && "Invalid s10 argument");
177 O << value;
178 }
179
180 void
181 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
182 {
183 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
184 >> 16);
185 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
186 O << value;
187 }
188
189 void
Scott Michel06eabde2008-12-27 04:51:36 +0000190 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
pingbakddfd8692008-11-08 18:59:02 +0000191 {
Chris Lattner4c4fb3a2009-01-21 18:38:18 +0000192 assert(MI->getOperand(OpNo).isImm() &&
193 "printDFormAddr first operand is not immediate");
pingbakddfd8692008-11-08 18:59:02 +0000194 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
Scott Michelffca41d2008-11-20 05:01:09 +0000195 int16_t value16 = int16_t(value);
196 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
pingbakddfd8692008-11-08 18:59:02 +0000197 && "Invalid dform s10 offset argument");
Scott Michel06eabde2008-12-27 04:51:36 +0000198 O << (value16 & ~0xf) << "(";
pingbakddfd8692008-11-08 18:59:02 +0000199 printOperand(MI, OpNo+1);
200 O << ")";
201 }
202
203 void
204 printAddr256K(const MachineInstr *MI, unsigned OpNo)
205 {
206 /* Note: operand 1 is an offset or symbol name. */
207 if (MI->getOperand(OpNo).isImm()) {
208 printS16ImmOperand(MI, OpNo);
209 } else {
210 printOp(MI->getOperand(OpNo));
211 if (MI->getOperand(OpNo+1).isImm()) {
212 int displ = int(MI->getOperand(OpNo+1).getImm());
213 if (displ > 0)
214 O << "+" << displ;
215 else if (displ < 0)
216 O << displ;
217 }
218 }
219 }
220
221 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
222 printOp(MI->getOperand(OpNo));
223 }
224
225 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
Scott Michel61895fe2008-12-10 00:15:19 +0000226 // Used to generate a ".-<target>", but it turns out that the assembler
227 // really wants the target.
228 //
229 // N.B.: This operand is used for call targets. Branch hints are another
230 // animal entirely.
231 printOp(MI->getOperand(OpNo));
232 }
233
234 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
235 // HBR operands are generated in front of branches, hence, the
236 // program counter plus the target.
237 O << ".+";
pingbakddfd8692008-11-08 18:59:02 +0000238 printOp(MI->getOperand(OpNo));
pingbakddfd8692008-11-08 18:59:02 +0000239 }
240
241 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
242 if (MI->getOperand(OpNo).isImm()) {
243 printS16ImmOperand(MI, OpNo);
244 } else {
245 printOp(MI->getOperand(OpNo));
246 O << "@h";
247 }
248 }
249
250 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
251 if (MI->getOperand(OpNo).isImm()) {
252 printS16ImmOperand(MI, OpNo);
253 } else {
254 printOp(MI->getOperand(OpNo));
255 O << "@l";
256 }
257 }
258
259 /// Print local store address
260 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
261 printOp(MI->getOperand(OpNo));
262 }
263
264 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
265 if (MI->getOperand(OpNo).isImm()) {
266 int value = (int) MI->getOperand(OpNo).getImm();
267 assert((value >= 0 && value < 16)
268 && "Invalid negated immediate rotate 7-bit argument");
269 O << -value;
270 } else {
Edwin Törökbd448e32009-07-14 16:55:14 +0000271 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
pingbakddfd8692008-11-08 18:59:02 +0000272 }
273 }
274
275 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
276 if (MI->getOperand(OpNo).isImm()) {
277 int value = (int) MI->getOperand(OpNo).getImm();
Scott Michelc630c412008-11-24 17:11:17 +0000278 assert((value >= 0 && value <= 32)
pingbakddfd8692008-11-08 18:59:02 +0000279 && "Invalid negated immediate rotate 7-bit argument");
280 O << -value;
281 } else {
Edwin Törökbd448e32009-07-14 16:55:14 +0000282 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
pingbakddfd8692008-11-08 18:59:02 +0000283 }
284 }
285
286 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
pingbakddfd8692008-11-08 18:59:02 +0000287 };
288
289 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
Bill Wendling4f405312009-02-24 08:30:20 +0000290 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
Devang Patelaa1e8432009-01-08 23:40:34 +0000291 DwarfWriter *DW;
Bill Wendling4f405312009-02-24 08:30:20 +0000292 public:
Daniel Dunbarfe5939f2009-07-15 20:24:03 +0000293 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
Chris Lattner621c44d2009-08-22 20:48:53 +0000294 const MCAsmInfo *T, bool V)
Daniel Dunbarb10d2222009-07-01 01:48:54 +0000295 : SPUAsmPrinter(O, TM, T, V), DW(0) {}
pingbakddfd8692008-11-08 18:59:02 +0000296
297 virtual const char *getPassName() const {
298 return "STI CBEA SPU Assembly Printer";
299 }
Scott Michelc899a122009-01-26 22:33:37 +0000300
pingbakddfd8692008-11-08 18:59:02 +0000301 bool runOnMachineFunction(MachineFunction &F);
302 bool doInitialization(Module &M);
Scott Michelc899a122009-01-26 22:33:37 +0000303
pingbakddfd8692008-11-08 18:59:02 +0000304 void getAnalysisUsage(AnalysisUsage &AU) const {
305 AU.setPreservesAll();
306 AU.addRequired<MachineModuleInfo>();
Devang Patelaa1e8432009-01-08 23:40:34 +0000307 AU.addRequired<DwarfWriter>();
pingbakddfd8692008-11-08 18:59:02 +0000308 SPUAsmPrinter::getAnalysisUsage(AU);
309 }
310
311 //! Emit a global variable according to its section and type
Chris Lattnerae982212009-07-21 18:38:57 +0000312 void PrintGlobalVariable(const GlobalVariable* GVar);
pingbakddfd8692008-11-08 18:59:02 +0000313 };
314} // end of anonymous namespace
315
316// Include the auto-generated portion of the assembly writer
317#include "SPUGenAsmWriter.inc"
318
319void SPUAsmPrinter::printOp(const MachineOperand &MO) {
320 switch (MO.getType()) {
321 case MachineOperand::MO_Immediate:
Edwin Török4d9756a2009-07-08 20:53:28 +0000322 llvm_report_error("printOp() does not handle immediate values");
pingbakddfd8692008-11-08 18:59:02 +0000323 return;
324
325 case MachineOperand::MO_MachineBasicBlock:
Chris Lattnerc6f802d2009-09-13 17:14:04 +0000326 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
pingbakddfd8692008-11-08 18:59:02 +0000327 return;
328 case MachineOperand::MO_JumpTableIndex:
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000329 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
pingbakddfd8692008-11-08 18:59:02 +0000330 << '_' << MO.getIndex();
331 return;
332 case MachineOperand::MO_ConstantPoolIndex:
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000333 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
pingbakddfd8692008-11-08 18:59:02 +0000334 << '_' << MO.getIndex();
335 return;
336 case MachineOperand::MO_ExternalSymbol:
337 // Computing the address of an external symbol, not calling it.
338 if (TM.getRelocationModel() != Reloc::Static) {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000339 std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName();
pingbakddfd8692008-11-08 18:59:02 +0000340 GVStubs.insert(Name);
341 O << "L" << Name << "$non_lazy_ptr";
342 return;
343 }
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000344 O << MAI->getGlobalPrefix() << MO.getSymbolName();
pingbakddfd8692008-11-08 18:59:02 +0000345 return;
346 case MachineOperand::MO_GlobalAddress: {
347 // Computing the address of a global symbol, not calling it.
348 GlobalValue *GV = MO.getGlobal();
Chris Lattnerb3cdde62009-07-14 18:17:16 +0000349 std::string Name = Mang->getMangledName(GV);
pingbakddfd8692008-11-08 18:59:02 +0000350
351 // External or weakly linked global variables need non-lazily-resolved
352 // stubs
353 if (TM.getRelocationModel() != Reloc::Static) {
354 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
355 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
356 GVStubs.insert(Name);
357 O << "L" << Name << "$non_lazy_ptr";
358 return;
359 }
360 }
361 O << Name;
pingbakddfd8692008-11-08 18:59:02 +0000362 return;
363 }
364
365 default:
366 O << "<unknown operand type: " << MO.getType() << ">";
367 return;
368 }
369}
370
371/// PrintAsmOperand - Print out an operand for an inline asm expression.
372///
373bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
Scott Michelc899a122009-01-26 22:33:37 +0000374 unsigned AsmVariant,
pingbakddfd8692008-11-08 18:59:02 +0000375 const char *ExtraCode) {
376 // Does this asm operand have a single letter operand modifier?
377 if (ExtraCode && ExtraCode[0]) {
378 if (ExtraCode[1] != 0) return true; // Unknown modifier.
Scott Michelc899a122009-01-26 22:33:37 +0000379
pingbakddfd8692008-11-08 18:59:02 +0000380 switch (ExtraCode[0]) {
381 default: return true; // Unknown modifier.
Scott Michelc899a122009-01-26 22:33:37 +0000382 case 'L': // Write second word of DImode reference.
pingbakddfd8692008-11-08 18:59:02 +0000383 // Verify that this operand has two consecutive registers.
384 if (!MI->getOperand(OpNo).isReg() ||
385 OpNo+1 == MI->getNumOperands() ||
386 !MI->getOperand(OpNo+1).isReg())
387 return true;
388 ++OpNo; // Return the high-part.
389 break;
390 }
391 }
Scott Michelc899a122009-01-26 22:33:37 +0000392
pingbakddfd8692008-11-08 18:59:02 +0000393 printOperand(MI, OpNo);
394 return false;
395}
396
397bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
398 unsigned OpNo,
Scott Michelc899a122009-01-26 22:33:37 +0000399 unsigned AsmVariant,
pingbakddfd8692008-11-08 18:59:02 +0000400 const char *ExtraCode) {
401 if (ExtraCode && ExtraCode[0])
402 return true; // Unknown modifier.
403 printMemRegReg(MI, OpNo);
404 return false;
405}
406
407/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
408/// to the current output stream.
409///
410void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
411 ++EmittedInsts;
Chris Lattnere34788c2009-09-09 20:34:59 +0000412 processDebugLoc(MI->getDebugLoc());
pingbakddfd8692008-11-08 18:59:02 +0000413 printInstruction(MI);
Chris Lattner32d4cc72009-09-09 23:14:36 +0000414
415 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
416 EmitComments(*MI);
417 O << '\n';
pingbakddfd8692008-11-08 18:59:02 +0000418}
419
420/// runOnMachineFunction - This uses the printMachineInstruction()
421/// method to print assembly for each instruction.
422///
Chris Lattnere34788c2009-09-09 20:34:59 +0000423bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Bill Wendling4f405312009-02-24 08:30:20 +0000424 this->MF = &MF;
425
pingbakddfd8692008-11-08 18:59:02 +0000426 SetupMachineFunction(MF);
427 O << "\n\n";
Scott Michelc899a122009-01-26 22:33:37 +0000428
pingbakddfd8692008-11-08 18:59:02 +0000429 // Print out constants referenced by the function
430 EmitConstantPool(MF.getConstantPool());
431
432 // Print out labels for the function.
433 const Function *F = MF.getFunction();
434
Chris Lattner73266f92009-08-19 05:49:37 +0000435 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
Bill Wendling25a8ae32009-06-30 22:38:32 +0000436 EmitAlignment(MF.getAlignment(), F);
pingbakddfd8692008-11-08 18:59:02 +0000437
438 switch (F->getLinkage()) {
Edwin Törökbd448e32009-07-14 16:55:14 +0000439 default: llvm_unreachable("Unknown linkage type!");
Rafael Espindolaa168fc92009-01-15 20:18:42 +0000440 case Function::PrivateLinkage:
Bill Wendling41a07852009-07-20 01:03:30 +0000441 case Function::LinkerPrivateLinkage:
pingbakddfd8692008-11-08 18:59:02 +0000442 case Function::InternalLinkage: // Symbols default to internal.
443 break;
444 case Function::ExternalLinkage:
445 O << "\t.global\t" << CurrentFnName << "\n"
446 << "\t.type\t" << CurrentFnName << ", @function\n";
447 break;
Duncan Sands19d161f2009-03-07 15:45:40 +0000448 case Function::WeakAnyLinkage:
449 case Function::WeakODRLinkage:
450 case Function::LinkOnceAnyLinkage:
451 case Function::LinkOnceODRLinkage:
pingbakddfd8692008-11-08 18:59:02 +0000452 O << "\t.global\t" << CurrentFnName << "\n";
453 O << "\t.weak_definition\t" << CurrentFnName << "\n";
454 break;
455 }
456 O << CurrentFnName << ":\n";
457
458 // Emit pre-function debug information.
Devang Patelaa1e8432009-01-08 23:40:34 +0000459 DW->BeginFunction(&MF);
pingbakddfd8692008-11-08 18:59:02 +0000460
461 // Print out code for the function.
462 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
463 I != E; ++I) {
464 // Print a label for the basic block.
465 if (I != MF.begin()) {
Chris Lattner2faa4ef2009-09-13 18:25:37 +0000466 EmitBasicBlockStart(I);
pingbakddfd8692008-11-08 18:59:02 +0000467 O << '\n';
468 }
469 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
470 II != E; ++II) {
471 // Print the assembly for the instruction.
472 printMachineInstruction(II);
473 }
474 }
475
476 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
477
478 // Print out jump tables referenced by the function.
479 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
Scott Michelc899a122009-01-26 22:33:37 +0000480
pingbakddfd8692008-11-08 18:59:02 +0000481 // Emit post-function debug information.
Devang Patelaa1e8432009-01-08 23:40:34 +0000482 DW->EndFunction(&MF);
Scott Michelc899a122009-01-26 22:33:37 +0000483
pingbakddfd8692008-11-08 18:59:02 +0000484 // We didn't modify anything.
485 return false;
486}
487
488
489bool LinuxAsmPrinter::doInitialization(Module &M) {
490 bool Result = AsmPrinter::doInitialization(M);
Duncan Sands4e0d6a72009-01-28 13:14:17 +0000491 DW = getAnalysisIfAvailable<DwarfWriter>();
pingbakddfd8692008-11-08 18:59:02 +0000492 return Result;
493}
494
pingbakddfd8692008-11-08 18:59:02 +0000495/*!
496 Emit a global variable according to its section, alignment, etc.
Scott Michelc899a122009-01-26 22:33:37 +0000497
pingbakddfd8692008-11-08 18:59:02 +0000498 \note This code was shamelessly copied from the PowerPC's assembly printer,
499 which sort of screams for some kind of refactorization of common code.
500 */
Chris Lattnerae982212009-07-21 18:38:57 +0000501void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
pingbakddfd8692008-11-08 18:59:02 +0000502 const TargetData *TD = TM.getTargetData();
503
504 if (!GVar->hasInitializer())
505 return;
506
507 // Check to see if this is a special global used by LLVM, if so, emit it.
508 if (EmitSpecialLLVMGlobal(GVar))
509 return;
510
Chris Lattnerb3cdde62009-07-14 18:17:16 +0000511 std::string name = Mang->getMangledName(GVar);
pingbakddfd8692008-11-08 18:59:02 +0000512
513 printVisibility(name, GVar->getVisibility());
514
515 Constant *C = GVar->getInitializer();
516 const Type *Type = C->getType();
Duncan Sandsec4f97d2009-05-09 07:06:46 +0000517 unsigned Size = TD->getTypeAllocSize(Type);
pingbakddfd8692008-11-08 18:59:02 +0000518 unsigned Align = TD->getPreferredAlignmentLog(GVar);
519
Chris Lattner73266f92009-08-19 05:49:37 +0000520 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
521 TM));
pingbakddfd8692008-11-08 18:59:02 +0000522
523 if (C->isNullValue() && /* FIXME: Verify correct */
524 !GVar->hasSection() &&
Rafael Espindolaa168fc92009-01-15 20:18:42 +0000525 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
Duncan Sands19d161f2009-03-07 15:45:40 +0000526 GVar->isWeakForLinker())) {
pingbakddfd8692008-11-08 18:59:02 +0000527 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
528
529 if (GVar->hasExternalLinkage()) {
530 O << "\t.global " << name << '\n';
531 O << "\t.type " << name << ", @object\n";
532 O << name << ":\n";
533 O << "\t.zero " << Size << '\n';
Rafael Espindolaa168fc92009-01-15 20:18:42 +0000534 } else if (GVar->hasLocalLinkage()) {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000535 O << MAI->getLCOMMDirective() << name << ',' << Size;
pingbakddfd8692008-11-08 18:59:02 +0000536 } else {
537 O << ".comm " << name << ',' << Size;
538 }
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000539 O << "\t\t" << MAI->getCommentString() << " '";
Dan Gohman2aa282f2009-08-13 01:36:44 +0000540 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
pingbakddfd8692008-11-08 18:59:02 +0000541 O << "'\n";
542 return;
543 }
544
545 switch (GVar->getLinkage()) {
546 // Should never be seen for the CellSPU platform...
Duncan Sands19d161f2009-03-07 15:45:40 +0000547 case GlobalValue::LinkOnceAnyLinkage:
548 case GlobalValue::LinkOnceODRLinkage:
549 case GlobalValue::WeakAnyLinkage:
550 case GlobalValue::WeakODRLinkage:
Duncan Sandsb95df792009-03-11 20:14:15 +0000551 case GlobalValue::CommonLinkage:
pingbakddfd8692008-11-08 18:59:02 +0000552 O << "\t.global " << name << '\n'
553 << "\t.type " << name << ", @object\n"
554 << "\t.weak " << name << '\n';
555 break;
556 case GlobalValue::AppendingLinkage:
557 // FIXME: appending linkage variables should go into a section of
558 // their name or something. For now, just emit them as external.
559 case GlobalValue::ExternalLinkage:
560 // If external or appending, declare as a global symbol
561 O << "\t.global " << name << '\n'
562 << "\t.type " << name << ", @object\n";
563 // FALL THROUGH
Rafael Espindolaa168fc92009-01-15 20:18:42 +0000564 case GlobalValue::PrivateLinkage:
Bill Wendling41a07852009-07-20 01:03:30 +0000565 case GlobalValue::LinkerPrivateLinkage:
pingbakddfd8692008-11-08 18:59:02 +0000566 case GlobalValue::InternalLinkage:
567 break;
568 default:
Edwin Török4d9756a2009-07-08 20:53:28 +0000569 llvm_report_error("Unknown linkage type!");
pingbakddfd8692008-11-08 18:59:02 +0000570 }
571
572 EmitAlignment(Align, GVar);
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000573 O << name << ":\t\t\t\t" << MAI->getCommentString() << " '";
Dan Gohman2aa282f2009-08-13 01:36:44 +0000574 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
pingbakddfd8692008-11-08 18:59:02 +0000575 O << "'\n";
576
pingbakddfd8692008-11-08 18:59:02 +0000577 EmitGlobalConstant(C);
578 O << '\n';
579}
580
Daniel Dunbarfe5939f2009-07-15 20:24:03 +0000581// Force static initialization.
582extern "C" void LLVMInitializeCellSPUAsmPrinter() {
Daniel Dunbarc680b012009-07-25 06:49:55 +0000583 RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
Daniel Dunbarfe5939f2009-07-15 20:24:03 +0000584}