Remove includes of Support/Compiler.h that are no longer needed after the
[llvm.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
blob007fe8f7d4d1a21c1fae37de03f4dfec67118575
1 //===-- 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'.
14 //===----------------------------------------------------------------------===//
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"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/Target/TargetLoweringObjectFile.h"
32 #include "llvm/Target/TargetInstrInfo.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/Target/TargetRegisterInfo.h"
35 #include "llvm/Target/TargetRegistry.h"
36 #include "llvm/ADT/Statistic.h"
37 #include "llvm/ADT/StringExtras.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/FormattedStream.h"
42 #include "llvm/Support/Mangler.h"
43 #include "llvm/Support/MathExtras.h"
44 #include <set>
45 using namespace llvm;
47 namespace {
48 STATISTIC(EmittedInsts, "Number of machine instrs printed");
50 const std::string bss_section(".bss");
52 class SPUAsmPrinter : public AsmPrinter {
53 std::set<std::string> FnStubs, GVStubs;
54 public:
55 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56 const MCAsmInfo *T, bool V) :
57 AsmPrinter(O, TM, T, V) {}
59 virtual const char *getPassName() const {
60 return "STI CBEA SPU Assembly Printer";
63 SPUTargetMachine &getTM() {
64 return static_cast<SPUTargetMachine&>(TM);
67 /// printInstruction - This method is automatically generated by tablegen
68 /// from the instruction set description.
69 void printInstruction(const MachineInstr *MI);
70 static const char *getRegisterName(unsigned RegNo);
73 void printMachineInstruction(const MachineInstr *MI);
74 void printOp(const MachineOperand &MO);
76 /// printRegister - Print register according to target requirements.
77 ///
78 void printRegister(const MachineOperand &MO, bool R0AsZero) {
79 unsigned RegNo = MO.getReg();
80 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
81 "Not physreg??");
82 O << getRegisterName(RegNo);
85 void printOperand(const MachineInstr *MI, unsigned OpNo) {
86 const MachineOperand &MO = MI->getOperand(OpNo);
87 if (MO.isReg()) {
88 O << getRegisterName(MO.getReg());
89 } else if (MO.isImm()) {
90 O << MO.getImm();
91 } else {
92 printOp(MO);
96 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
97 unsigned AsmVariant, const char *ExtraCode);
98 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
99 unsigned AsmVariant, const char *ExtraCode);
102 void
103 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
105 int value = MI->getOperand(OpNo).getImm();
106 value = (value << (32 - 7)) >> (32 - 7);
108 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
109 && "Invalid s7 argument");
110 O << value;
113 void
114 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
116 unsigned int value = MI->getOperand(OpNo).getImm();
117 assert(value < (1 << 8) && "Invalid u7 argument");
118 O << value;
121 void
122 printShufAddr(const MachineInstr *MI, unsigned OpNo)
124 char value = MI->getOperand(OpNo).getImm();
125 O << (int) value;
126 O << "(";
127 printOperand(MI, OpNo+1);
128 O << ")";
131 void
132 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
134 O << (short) MI->getOperand(OpNo).getImm();
137 void
138 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
140 O << (unsigned short)MI->getOperand(OpNo).getImm();
143 void
144 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
146 O << (unsigned)MI->getOperand(OpNo).getImm();
149 void
150 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
151 // When used as the base register, r0 reads constant zero rather than
152 // the value contained in the register. For this reason, the darwin
153 // assembler requires that we print r0 as 0 (no r) when used as the base.
154 const MachineOperand &MO = MI->getOperand(OpNo);
155 O << getRegisterName(MO.getReg()) << ", ";
156 printOperand(MI, OpNo+1);
159 void
160 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
162 unsigned int value = MI->getOperand(OpNo).getImm();
163 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
164 O << value;
167 void
168 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
170 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
171 >> 16);
172 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
173 && "Invalid s10 argument");
174 O << value;
177 void
178 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
180 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
181 >> 16);
182 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
183 O << value;
186 void
187 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
189 assert(MI->getOperand(OpNo).isImm() &&
190 "printDFormAddr first operand is not immediate");
191 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
192 int16_t value16 = int16_t(value);
193 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
194 && "Invalid dform s10 offset argument");
195 O << (value16 & ~0xf) << "(";
196 printOperand(MI, OpNo+1);
197 O << ")";
200 void
201 printAddr256K(const MachineInstr *MI, unsigned OpNo)
203 /* Note: operand 1 is an offset or symbol name. */
204 if (MI->getOperand(OpNo).isImm()) {
205 printS16ImmOperand(MI, OpNo);
206 } else {
207 printOp(MI->getOperand(OpNo));
208 if (MI->getOperand(OpNo+1).isImm()) {
209 int displ = int(MI->getOperand(OpNo+1).getImm());
210 if (displ > 0)
211 O << "+" << displ;
212 else if (displ < 0)
213 O << displ;
218 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
219 printOp(MI->getOperand(OpNo));
222 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
223 // Used to generate a ".-<target>", but it turns out that the assembler
224 // really wants the target.
226 // N.B.: This operand is used for call targets. Branch hints are another
227 // animal entirely.
228 printOp(MI->getOperand(OpNo));
231 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
232 // HBR operands are generated in front of branches, hence, the
233 // program counter plus the target.
234 O << ".+";
235 printOp(MI->getOperand(OpNo));
238 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
239 if (MI->getOperand(OpNo).isImm()) {
240 printS16ImmOperand(MI, OpNo);
241 } else {
242 printOp(MI->getOperand(OpNo));
243 O << "@h";
247 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
248 if (MI->getOperand(OpNo).isImm()) {
249 printS16ImmOperand(MI, OpNo);
250 } else {
251 printOp(MI->getOperand(OpNo));
252 O << "@l";
256 /// Print local store address
257 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
258 printOp(MI->getOperand(OpNo));
261 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
262 if (MI->getOperand(OpNo).isImm()) {
263 int value = (int) MI->getOperand(OpNo).getImm();
264 assert((value >= 0 && value < 16)
265 && "Invalid negated immediate rotate 7-bit argument");
266 O << -value;
267 } else {
268 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
272 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
273 if (MI->getOperand(OpNo).isImm()) {
274 int value = (int) MI->getOperand(OpNo).getImm();
275 assert((value >= 0 && value <= 32)
276 && "Invalid negated immediate rotate 7-bit argument");
277 O << -value;
278 } else {
279 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
283 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
286 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
287 class LinuxAsmPrinter : public SPUAsmPrinter {
288 public:
289 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
290 const MCAsmInfo *T, bool V)
291 : SPUAsmPrinter(O, TM, T, V) {}
293 virtual const char *getPassName() const {
294 return "STI CBEA SPU Assembly Printer";
297 bool runOnMachineFunction(MachineFunction &F);
299 void getAnalysisUsage(AnalysisUsage &AU) const {
300 AU.setPreservesAll();
301 AU.addRequired<MachineModuleInfo>();
302 AU.addRequired<DwarfWriter>();
303 SPUAsmPrinter::getAnalysisUsage(AU);
306 //! Emit a global variable according to its section and type
307 void PrintGlobalVariable(const GlobalVariable* GVar);
309 } // end of anonymous namespace
311 // Include the auto-generated portion of the assembly writer
312 #include "SPUGenAsmWriter.inc"
314 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
315 switch (MO.getType()) {
316 case MachineOperand::MO_Immediate:
317 llvm_report_error("printOp() does not handle immediate values");
318 return;
320 case MachineOperand::MO_MachineBasicBlock:
321 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
322 return;
323 case MachineOperand::MO_JumpTableIndex:
324 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
325 << '_' << MO.getIndex();
326 return;
327 case MachineOperand::MO_ConstantPoolIndex:
328 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
329 << '_' << MO.getIndex();
330 return;
331 case MachineOperand::MO_ExternalSymbol:
332 // Computing the address of an external symbol, not calling it.
333 if (TM.getRelocationModel() != Reloc::Static) {
334 std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName();
335 GVStubs.insert(Name);
336 O << "L" << Name << "$non_lazy_ptr";
337 return;
339 O << MAI->getGlobalPrefix() << MO.getSymbolName();
340 return;
341 case MachineOperand::MO_GlobalAddress: {
342 // Computing the address of a global symbol, not calling it.
343 GlobalValue *GV = MO.getGlobal();
344 std::string Name = Mang->getMangledName(GV);
346 // External or weakly linked global variables need non-lazily-resolved
347 // stubs
348 if (TM.getRelocationModel() != Reloc::Static) {
349 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
350 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
351 GVStubs.insert(Name);
352 O << "L" << Name << "$non_lazy_ptr";
353 return;
356 O << Name;
357 return;
360 default:
361 O << "<unknown operand type: " << MO.getType() << ">";
362 return;
366 /// PrintAsmOperand - Print out an operand for an inline asm expression.
368 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
369 unsigned AsmVariant,
370 const char *ExtraCode) {
371 // Does this asm operand have a single letter operand modifier?
372 if (ExtraCode && ExtraCode[0]) {
373 if (ExtraCode[1] != 0) return true; // Unknown modifier.
375 switch (ExtraCode[0]) {
376 default: return true; // Unknown modifier.
377 case 'L': // Write second word of DImode reference.
378 // Verify that this operand has two consecutive registers.
379 if (!MI->getOperand(OpNo).isReg() ||
380 OpNo+1 == MI->getNumOperands() ||
381 !MI->getOperand(OpNo+1).isReg())
382 return true;
383 ++OpNo; // Return the high-part.
384 break;
388 printOperand(MI, OpNo);
389 return false;
392 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
393 unsigned OpNo,
394 unsigned AsmVariant,
395 const char *ExtraCode) {
396 if (ExtraCode && ExtraCode[0])
397 return true; // Unknown modifier.
398 printMemRegReg(MI, OpNo);
399 return false;
402 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
403 /// to the current output stream.
405 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
406 ++EmittedInsts;
407 processDebugLoc(MI, true);
408 printInstruction(MI);
409 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
410 EmitComments(*MI);
411 processDebugLoc(MI, false);
412 O << '\n';
415 /// runOnMachineFunction - This uses the printMachineInstruction()
416 /// method to print assembly for each instruction.
418 bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
419 this->MF = &MF;
421 SetupMachineFunction(MF);
422 O << "\n\n";
424 // Print out constants referenced by the function
425 EmitConstantPool(MF.getConstantPool());
427 // Print out labels for the function.
428 const Function *F = MF.getFunction();
430 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
431 EmitAlignment(MF.getAlignment(), F);
433 switch (F->getLinkage()) {
434 default: llvm_unreachable("Unknown linkage type!");
435 case Function::PrivateLinkage:
436 case Function::LinkerPrivateLinkage:
437 case Function::InternalLinkage: // Symbols default to internal.
438 break;
439 case Function::ExternalLinkage:
440 O << "\t.global\t" << CurrentFnName << "\n"
441 << "\t.type\t" << CurrentFnName << ", @function\n";
442 break;
443 case Function::WeakAnyLinkage:
444 case Function::WeakODRLinkage:
445 case Function::LinkOnceAnyLinkage:
446 case Function::LinkOnceODRLinkage:
447 O << "\t.global\t" << CurrentFnName << "\n";
448 O << "\t.weak_definition\t" << CurrentFnName << "\n";
449 break;
451 O << CurrentFnName << ":\n";
453 // Emit pre-function debug information.
454 DW->BeginFunction(&MF);
456 // Print out code for the function.
457 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
458 I != E; ++I) {
459 // Print a label for the basic block.
460 if (I != MF.begin()) {
461 EmitBasicBlockStart(I);
463 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
464 II != E; ++II) {
465 // Print the assembly for the instruction.
466 printMachineInstruction(II);
470 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
472 // Print out jump tables referenced by the function.
473 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
475 // Emit post-function debug information.
476 DW->EndFunction(&MF);
478 // We didn't modify anything.
479 return false;
484 Emit a global variable according to its section, alignment, etc.
486 \note This code was shamelessly copied from the PowerPC's assembly printer,
487 which sort of screams for some kind of refactorization of common code.
489 void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
490 const TargetData *TD = TM.getTargetData();
492 if (!GVar->hasInitializer())
493 return;
495 // Check to see if this is a special global used by LLVM, if so, emit it.
496 if (EmitSpecialLLVMGlobal(GVar))
497 return;
499 std::string name = Mang->getMangledName(GVar);
501 printVisibility(name, GVar->getVisibility());
503 Constant *C = GVar->getInitializer();
504 const Type *Type = C->getType();
505 unsigned Size = TD->getTypeAllocSize(Type);
506 unsigned Align = TD->getPreferredAlignmentLog(GVar);
508 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
509 TM));
511 if (C->isNullValue() && /* FIXME: Verify correct */
512 !GVar->hasSection() &&
513 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
514 GVar->isWeakForLinker())) {
515 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
517 if (GVar->hasExternalLinkage()) {
518 O << "\t.global " << name << '\n';
519 O << "\t.type " << name << ", @object\n";
520 O << name << ":\n";
521 O << "\t.zero " << Size << '\n';
522 } else if (GVar->hasLocalLinkage()) {
523 O << MAI->getLCOMMDirective() << name << ',' << Size;
524 } else {
525 O << ".comm " << name << ',' << Size;
527 O << "\t\t" << MAI->getCommentString() << " '";
528 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
529 O << "'\n";
530 return;
533 switch (GVar->getLinkage()) {
534 // Should never be seen for the CellSPU platform...
535 case GlobalValue::LinkOnceAnyLinkage:
536 case GlobalValue::LinkOnceODRLinkage:
537 case GlobalValue::WeakAnyLinkage:
538 case GlobalValue::WeakODRLinkage:
539 case GlobalValue::CommonLinkage:
540 O << "\t.global " << name << '\n'
541 << "\t.type " << name << ", @object\n"
542 << "\t.weak " << name << '\n';
543 break;
544 case GlobalValue::AppendingLinkage:
545 // FIXME: appending linkage variables should go into a section of
546 // their name or something. For now, just emit them as external.
547 case GlobalValue::ExternalLinkage:
548 // If external or appending, declare as a global symbol
549 O << "\t.global " << name << '\n'
550 << "\t.type " << name << ", @object\n";
551 // FALL THROUGH
552 case GlobalValue::PrivateLinkage:
553 case GlobalValue::LinkerPrivateLinkage:
554 case GlobalValue::InternalLinkage:
555 break;
556 default:
557 llvm_report_error("Unknown linkage type!");
560 EmitAlignment(Align, GVar);
561 O << name << ":\t\t\t\t" << MAI->getCommentString() << " '";
562 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
563 O << "'\n";
565 EmitGlobalConstant(C);
566 O << '\n';
569 // Force static initialization.
570 extern "C" void LLVMInitializeCellSPUAsmPrinter() {
571 RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);