1 //===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=//
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 Cell SPU assembly language. This printer
12 // is the output mechanism used by `llc'.
14 //===----------------------------------------------------------------------===//
16 #define DEBUG_TYPE "asmprinter"
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/MathExtras.h"
46 STATISTIC(EmittedInsts, "Number of machine instrs printed");
48 const std::string bss_section(".bss");
50 class SPUAsmPrinter : public AsmPrinter {
52 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
53 const MCAsmInfo *T, bool V) :
54 AsmPrinter(O, TM, T, V) {}
56 virtual const char *getPassName() const {
57 return "STI CBEA SPU Assembly Printer";
60 SPUTargetMachine &getTM() {
61 return static_cast<SPUTargetMachine&>(TM);
64 /// printInstruction - This method is automatically generated by tablegen
65 /// from the instruction set description.
66 void printInstruction(const MachineInstr *MI);
67 static const char *getRegisterName(unsigned RegNo);
70 void printMachineInstruction(const MachineInstr *MI);
71 void printOp(const MachineOperand &MO);
73 /// printRegister - Print register according to target requirements.
75 void printRegister(const MachineOperand &MO, bool R0AsZero) {
76 unsigned RegNo = MO.getReg();
77 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
79 O << getRegisterName(RegNo);
82 void printOperand(const MachineInstr *MI, unsigned OpNo) {
83 const MachineOperand &MO = MI->getOperand(OpNo);
85 O << getRegisterName(MO.getReg());
86 } else if (MO.isImm()) {
93 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
94 unsigned AsmVariant, const char *ExtraCode);
95 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
96 unsigned AsmVariant, const char *ExtraCode);
100 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
102 int value = MI->getOperand(OpNo).getImm();
103 value = (value << (32 - 7)) >> (32 - 7);
105 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
106 && "Invalid s7 argument");
111 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
113 unsigned int value = MI->getOperand(OpNo).getImm();
114 assert(value < (1 << 8) && "Invalid u7 argument");
119 printShufAddr(const MachineInstr *MI, unsigned OpNo)
121 char value = MI->getOperand(OpNo).getImm();
124 printOperand(MI, OpNo+1);
129 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
131 O << (short) MI->getOperand(OpNo).getImm();
135 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
137 O << (unsigned short)MI->getOperand(OpNo).getImm();
141 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
143 O << (unsigned)MI->getOperand(OpNo).getImm();
147 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
148 // When used as the base register, r0 reads constant zero rather than
149 // the value contained in the register. For this reason, the darwin
150 // assembler requires that we print r0 as 0 (no r) when used as the base.
151 const MachineOperand &MO = MI->getOperand(OpNo);
152 O << getRegisterName(MO.getReg()) << ", ";
153 printOperand(MI, OpNo+1);
157 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
159 unsigned int value = MI->getOperand(OpNo).getImm();
160 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
165 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
167 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
169 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
170 && "Invalid s10 argument");
175 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
177 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
179 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
184 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
186 assert(MI->getOperand(OpNo).isImm() &&
187 "printDFormAddr first operand is not immediate");
188 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
189 int16_t value16 = int16_t(value);
190 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
191 && "Invalid dform s10 offset argument");
192 O << (value16 & ~0xf) << "(";
193 printOperand(MI, OpNo+1);
198 printAddr256K(const MachineInstr *MI, unsigned OpNo)
200 /* Note: operand 1 is an offset or symbol name. */
201 if (MI->getOperand(OpNo).isImm()) {
202 printS16ImmOperand(MI, OpNo);
204 printOp(MI->getOperand(OpNo));
205 if (MI->getOperand(OpNo+1).isImm()) {
206 int displ = int(MI->getOperand(OpNo+1).getImm());
215 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
216 printOp(MI->getOperand(OpNo));
219 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
220 // Used to generate a ".-<target>", but it turns out that the assembler
221 // really wants the target.
223 // N.B.: This operand is used for call targets. Branch hints are another
225 printOp(MI->getOperand(OpNo));
228 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
229 // HBR operands are generated in front of branches, hence, the
230 // program counter plus the target.
232 printOp(MI->getOperand(OpNo));
235 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
236 if (MI->getOperand(OpNo).isImm()) {
237 printS16ImmOperand(MI, OpNo);
239 printOp(MI->getOperand(OpNo));
244 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
245 if (MI->getOperand(OpNo).isImm()) {
246 printS16ImmOperand(MI, OpNo);
248 printOp(MI->getOperand(OpNo));
253 /// Print local store address
254 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
255 printOp(MI->getOperand(OpNo));
258 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
259 if (MI->getOperand(OpNo).isImm()) {
260 int value = (int) MI->getOperand(OpNo).getImm();
261 assert((value >= 0 && value < 16)
262 && "Invalid negated immediate rotate 7-bit argument");
265 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
269 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
270 if (MI->getOperand(OpNo).isImm()) {
271 int value = (int) MI->getOperand(OpNo).getImm();
272 assert((value >= 0 && value <= 32)
273 && "Invalid negated immediate rotate 7-bit argument");
276 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
280 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
283 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
284 class LinuxAsmPrinter : public SPUAsmPrinter {
286 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
287 const MCAsmInfo *T, bool V)
288 : SPUAsmPrinter(O, TM, T, V) {}
290 virtual const char *getPassName() const {
291 return "STI CBEA SPU Assembly Printer";
294 bool runOnMachineFunction(MachineFunction &F);
296 void getAnalysisUsage(AnalysisUsage &AU) const {
297 AU.setPreservesAll();
298 AU.addRequired<MachineModuleInfo>();
299 AU.addRequired<DwarfWriter>();
300 SPUAsmPrinter::getAnalysisUsage(AU);
303 //! Emit a global variable according to its section and type
304 void PrintGlobalVariable(const GlobalVariable* GVar);
306 } // end of anonymous namespace
308 // Include the auto-generated portion of the assembly writer
309 #include "SPUGenAsmWriter.inc"
311 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
312 switch (MO.getType()) {
313 case MachineOperand::MO_Immediate:
314 llvm_report_error("printOp() does not handle immediate values");
317 case MachineOperand::MO_MachineBasicBlock:
318 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
320 case MachineOperand::MO_JumpTableIndex:
321 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
322 << '_' << MO.getIndex();
324 case MachineOperand::MO_ConstantPoolIndex:
325 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
326 << '_' << MO.getIndex();
328 case MachineOperand::MO_ExternalSymbol:
329 // Computing the address of an external symbol, not calling it.
330 if (TM.getRelocationModel() != Reloc::Static) {
331 O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName()
335 GetExternalSymbolSymbol(MO.getSymbolName())->print(O, MAI);
337 case MachineOperand::MO_GlobalAddress:
338 // External or weakly linked global variables need non-lazily-resolved
340 if (TM.getRelocationModel() != Reloc::Static) {
341 GlobalValue *GV = MO.getGlobal();
342 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
343 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
344 GetPrivateGlobalValueSymbolStub(GV, "$non_lazy_ptr")->print(O, MAI);
348 GetGlobalValueSymbol(MO.getGlobal())->print(O, MAI);
351 O << "<unknown operand type: " << MO.getType() << ">";
356 /// PrintAsmOperand - Print out an operand for an inline asm expression.
358 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
360 const char *ExtraCode) {
361 // Does this asm operand have a single letter operand modifier?
362 if (ExtraCode && ExtraCode[0]) {
363 if (ExtraCode[1] != 0) return true; // Unknown modifier.
365 switch (ExtraCode[0]) {
366 default: return true; // Unknown modifier.
367 case 'L': // Write second word of DImode reference.
368 // Verify that this operand has two consecutive registers.
369 if (!MI->getOperand(OpNo).isReg() ||
370 OpNo+1 == MI->getNumOperands() ||
371 !MI->getOperand(OpNo+1).isReg())
373 ++OpNo; // Return the high-part.
378 printOperand(MI, OpNo);
382 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
385 const char *ExtraCode) {
386 if (ExtraCode && ExtraCode[0])
387 return true; // Unknown modifier.
388 printMemRegReg(MI, OpNo);
392 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
393 /// to the current output stream.
395 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
397 processDebugLoc(MI, true);
398 printInstruction(MI);
401 processDebugLoc(MI, false);
405 /// runOnMachineFunction - This uses the printMachineInstruction()
406 /// method to print assembly for each instruction.
408 bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
411 SetupMachineFunction(MF);
414 // Print out constants referenced by the function
415 EmitConstantPool(MF.getConstantPool());
417 // Print out labels for the function.
418 const Function *F = MF.getFunction();
420 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
421 EmitAlignment(MF.getAlignment(), F);
423 switch (F->getLinkage()) {
424 default: llvm_unreachable("Unknown linkage type!");
425 case Function::PrivateLinkage:
426 case Function::LinkerPrivateLinkage:
427 case Function::InternalLinkage: // Symbols default to internal.
429 case Function::ExternalLinkage:
431 CurrentFnSym->print(O, MAI);
432 O << "\n" << "\t.type\t";
433 CurrentFnSym->print(O, MAI);
434 O << ", @function\n";
436 case Function::WeakAnyLinkage:
437 case Function::WeakODRLinkage:
438 case Function::LinkOnceAnyLinkage:
439 case Function::LinkOnceODRLinkage:
441 CurrentFnSym->print(O, MAI);
443 O << "\t.weak_definition\t";
444 CurrentFnSym->print(O, MAI);
449 CurrentFnSym->print(O, MAI);
452 // Emit pre-function debug information.
453 DW->BeginFunction(&MF);
455 // Print out code for the function.
456 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
458 // Print a label for the basic block.
459 if (I != MF.begin()) {
460 EmitBasicBlockStart(I);
462 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
464 // Print the assembly for the instruction.
465 printMachineInstruction(II);
470 CurrentFnSym->print(O, MAI);
472 CurrentFnSym->print(O, MAI);
475 // Print out jump tables referenced by the function.
476 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
478 // Emit post-function debug information.
479 DW->EndFunction(&MF);
481 // We didn't modify anything.
487 Emit a global variable according to its section, alignment, etc.
489 \note This code was shamelessly copied from the PowerPC's assembly printer,
490 which sort of screams for some kind of refactorization of common code.
492 void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
493 const TargetData *TD = TM.getTargetData();
495 if (!GVar->hasInitializer())
498 // Check to see if this is a special global used by LLVM, if so, emit it.
499 if (EmitSpecialLLVMGlobal(GVar))
502 MCSymbol *GVarSym = GetGlobalValueSymbol(GVar);
504 printVisibility(GVarSym, GVar->getVisibility());
506 Constant *C = GVar->getInitializer();
507 const Type *Type = C->getType();
508 unsigned Size = TD->getTypeAllocSize(Type);
509 unsigned Align = TD->getPreferredAlignmentLog(GVar);
511 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
514 if (C->isNullValue() && /* FIXME: Verify correct */
515 !GVar->hasSection() &&
516 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
517 GVar->isWeakForLinker())) {
518 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
520 if (GVar->hasExternalLinkage()) {
522 GVarSym->print(O, MAI);
525 GVarSym->print(O, MAI);
527 GVarSym->print(O, MAI);
529 O << "\t.zero " << Size << '\n';
530 } else if (GVar->hasLocalLinkage()) {
531 O << MAI->getLCOMMDirective();
532 GVarSym->print(O, MAI);
536 GVarSym->print(O, MAI);
539 O << "\t\t" << MAI->getCommentString() << " '";
540 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
545 switch (GVar->getLinkage()) {
546 // Should never be seen for the CellSPU platform...
547 case GlobalValue::LinkOnceAnyLinkage:
548 case GlobalValue::LinkOnceODRLinkage:
549 case GlobalValue::WeakAnyLinkage:
550 case GlobalValue::WeakODRLinkage:
551 case GlobalValue::CommonLinkage:
553 GVarSym->print(O, MAI);
555 GVarSym->print(O, MAI);
556 O << ", @object\n" << "\t.weak ";
557 GVarSym->print(O, MAI);
560 case GlobalValue::AppendingLinkage:
561 // FIXME: appending linkage variables should go into a section of
562 // their name or something. For now, just emit them as external.
563 case GlobalValue::ExternalLinkage:
564 // If external or appending, declare as a global symbol
566 GVarSym->print(O, MAI);
568 GVarSym->print(O, MAI);
571 case GlobalValue::PrivateLinkage:
572 case GlobalValue::LinkerPrivateLinkage:
573 case GlobalValue::InternalLinkage:
576 llvm_report_error("Unknown linkage type!");
579 EmitAlignment(Align, GVar);
580 GVarSym->print(O, MAI);
581 O << ":\t\t\t\t" << MAI->getCommentString() << " '";
582 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
585 EmitGlobalConstant(C);
589 // Force static initialization.
590 extern "C" void LLVMInitializeCellSPUAsmPrinter() {
591 RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);