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/MDNode.h"
23 #include "llvm/Assembly/Writer.h"
24 #include "llvm/CodeGen/AsmPrinter.h"
25 #include "llvm/CodeGen/DwarfWriter.h"
26 #include "llvm/CodeGen/MachineModuleInfo.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/Support/Mangler.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include "llvm/Target/TargetAsmInfo.h"
37 #include "llvm/Target/TargetRegisterInfo.h"
38 #include "llvm/Target/TargetInstrInfo.h"
39 #include "llvm/Target/TargetOptions.h"
40 #include "llvm/ADT/Statistic.h"
41 #include "llvm/ADT/StringExtras.h"
46 STATISTIC(EmittedInsts, "Number of machine instrs printed");
48 const std::string bss_section(".bss");
50 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
51 std::set<std::string> FnStubs, GVStubs;
53 explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
54 const TargetAsmInfo *T, bool V) :
55 AsmPrinter(O, TM, T, V) {}
57 virtual const char *getPassName() const {
58 return "STI CBEA SPU Assembly Printer";
61 SPUTargetMachine &getTM() {
62 return static_cast<SPUTargetMachine&>(TM);
65 /// printInstruction - This method is automatically generated by tablegen
66 /// from the instruction set description. This method returns true if the
67 /// machine instruction was sufficiently described to print it, otherwise it
69 bool printInstruction(const MachineInstr *MI);
71 void printMachineInstruction(const MachineInstr *MI);
72 void printOp(const MachineOperand &MO);
74 /// printRegister - Print register according to target requirements.
76 void printRegister(const MachineOperand &MO, bool R0AsZero) {
77 unsigned RegNo = MO.getReg();
78 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
80 O << TM.getRegisterInfo()->get(RegNo).AsmName;
83 void printOperand(const MachineInstr *MI, unsigned OpNo) {
84 const MachineOperand &MO = MI->getOperand(OpNo);
86 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
87 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
88 } else if (MO.isImm()) {
95 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
96 unsigned AsmVariant, const char *ExtraCode);
97 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
98 unsigned AsmVariant, const char *ExtraCode);
102 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
104 int value = MI->getOperand(OpNo).getImm();
105 value = (value << (32 - 7)) >> (32 - 7);
107 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
108 && "Invalid s7 argument");
113 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
115 unsigned int value = MI->getOperand(OpNo).getImm();
116 assert(value < (1 << 8) && "Invalid u7 argument");
121 printShufAddr(const MachineInstr *MI, unsigned OpNo)
123 char value = MI->getOperand(OpNo).getImm();
126 printOperand(MI, OpNo+1);
131 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
133 O << (short) MI->getOperand(OpNo).getImm();
137 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
139 O << (unsigned short)MI->getOperand(OpNo).getImm();
143 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
145 O << (unsigned)MI->getOperand(OpNo).getImm();
149 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
150 // When used as the base register, r0 reads constant zero rather than
151 // the value contained in the register. For this reason, the darwin
152 // assembler requires that we print r0 as 0 (no r) when used as the base.
153 const MachineOperand &MO = MI->getOperand(OpNo);
154 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
156 printOperand(MI, OpNo+1);
160 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
162 unsigned int value = MI->getOperand(OpNo).getImm();
163 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
168 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
170 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
172 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
173 && "Invalid s10 argument");
178 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
180 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
182 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
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);
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);
207 printOp(MI->getOperand(OpNo));
208 if (MI->getOperand(OpNo+1).isImm()) {
209 int displ = int(MI->getOperand(OpNo+1).getImm());
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
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.
235 printOp(MI->getOperand(OpNo));
238 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
239 if (MI->getOperand(OpNo).isImm()) {
240 printS16ImmOperand(MI, OpNo);
242 printOp(MI->getOperand(OpNo));
247 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
248 if (MI->getOperand(OpNo).isImm()) {
249 printS16ImmOperand(MI, OpNo);
251 printOp(MI->getOperand(OpNo));
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");
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");
279 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
283 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
284 //! Assembly printer cleanup after function has been emitted
285 virtual bool doFinalization(Module &M) = 0;
288 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
289 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
292 explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
293 const TargetAsmInfo *T, bool V)
294 : SPUAsmPrinter(O, TM, T, V), DW(0) {}
296 virtual const char *getPassName() const {
297 return "STI CBEA SPU Assembly Printer";
300 bool runOnMachineFunction(MachineFunction &F);
301 bool doInitialization(Module &M);
302 //! Dump globals, perform cleanup after function emission
303 bool doFinalization(Module &M);
305 void getAnalysisUsage(AnalysisUsage &AU) const {
306 AU.setPreservesAll();
307 AU.addRequired<MachineModuleInfo>();
308 AU.addRequired<DwarfWriter>();
309 SPUAsmPrinter::getAnalysisUsage(AU);
312 //! Emit a global variable according to its section and type
313 void printModuleLevelGV(const GlobalVariable* GVar);
315 } // end of anonymous namespace
317 // Include the auto-generated portion of the assembly writer
318 #include "SPUGenAsmWriter.inc"
320 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
321 switch (MO.getType()) {
322 case MachineOperand::MO_Immediate:
323 llvm_report_error("printOp() does not handle immediate values");
326 case MachineOperand::MO_MachineBasicBlock:
327 printBasicBlockLabel(MO.getMBB());
329 case MachineOperand::MO_JumpTableIndex:
330 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
331 << '_' << MO.getIndex();
333 case MachineOperand::MO_ConstantPoolIndex:
334 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
335 << '_' << MO.getIndex();
337 case MachineOperand::MO_ExternalSymbol:
338 // Computing the address of an external symbol, not calling it.
339 if (TM.getRelocationModel() != Reloc::Static) {
340 std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
341 GVStubs.insert(Name);
342 O << "L" << Name << "$non_lazy_ptr";
345 O << TAI->getGlobalPrefix() << MO.getSymbolName();
347 case MachineOperand::MO_GlobalAddress: {
348 // Computing the address of a global symbol, not calling it.
349 GlobalValue *GV = MO.getGlobal();
350 std::string Name = Mang->getValueName(GV);
352 // External or weakly linked global variables need non-lazily-resolved
354 if (TM.getRelocationModel() != Reloc::Static) {
355 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
356 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
357 GVStubs.insert(Name);
358 O << "L" << Name << "$non_lazy_ptr";
367 O << "<unknown operand type: " << MO.getType() << ">";
372 /// PrintAsmOperand - Print out an operand for an inline asm expression.
374 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
376 const char *ExtraCode) {
377 // Does this asm operand have a single letter operand modifier?
378 if (ExtraCode && ExtraCode[0]) {
379 if (ExtraCode[1] != 0) return true; // Unknown modifier.
381 switch (ExtraCode[0]) {
382 default: return true; // Unknown modifier.
383 case 'L': // Write second word of DImode reference.
384 // Verify that this operand has two consecutive registers.
385 if (!MI->getOperand(OpNo).isReg() ||
386 OpNo+1 == MI->getNumOperands() ||
387 !MI->getOperand(OpNo+1).isReg())
389 ++OpNo; // Return the high-part.
394 printOperand(MI, OpNo);
398 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
401 const char *ExtraCode) {
402 if (ExtraCode && ExtraCode[0])
403 return true; // Unknown modifier.
404 printMemRegReg(MI, OpNo);
408 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
409 /// to the current output stream.
411 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
413 printInstruction(MI);
416 /// runOnMachineFunction - This uses the printMachineInstruction()
417 /// method to print assembly for each instruction.
420 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
424 SetupMachineFunction(MF);
427 // Print out constants referenced by the function
428 EmitConstantPool(MF.getConstantPool());
430 // Print out labels for the function.
431 const Function *F = MF.getFunction();
433 SwitchToSection(TAI->SectionForGlobal(F));
434 EmitAlignment(MF.getAlignment(), F);
436 switch (F->getLinkage()) {
437 default: llvm_unreachable("Unknown linkage type!");
438 case Function::PrivateLinkage:
439 case Function::InternalLinkage: // Symbols default to internal.
441 case Function::ExternalLinkage:
442 O << "\t.global\t" << CurrentFnName << "\n"
443 << "\t.type\t" << CurrentFnName << ", @function\n";
445 case Function::WeakAnyLinkage:
446 case Function::WeakODRLinkage:
447 case Function::LinkOnceAnyLinkage:
448 case Function::LinkOnceODRLinkage:
449 O << "\t.global\t" << CurrentFnName << "\n";
450 O << "\t.weak_definition\t" << CurrentFnName << "\n";
453 O << CurrentFnName << ":\n";
455 // Emit pre-function debug information.
456 DW->BeginFunction(&MF);
458 // Print out code for the function.
459 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
461 // Print a label for the basic block.
462 if (I != MF.begin()) {
463 printBasicBlockLabel(I, true, true);
466 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
468 // Print the assembly for the instruction.
469 printMachineInstruction(II);
473 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
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.
486 bool LinuxAsmPrinter::doInitialization(Module &M) {
487 bool Result = AsmPrinter::doInitialization(M);
488 DW = getAnalysisIfAvailable<DwarfWriter>();
489 SwitchToTextSection("\t.text");
493 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
494 /// Don't print things like \\n or \\0.
495 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
496 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
503 Emit a global variable according to its section, alignment, etc.
505 \note This code was shamelessly copied from the PowerPC's assembly printer,
506 which sort of screams for some kind of refactorization of common code.
508 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
509 const TargetData *TD = TM.getTargetData();
511 if (!GVar->hasInitializer())
514 // Check to see if this is a special global used by LLVM, if so, emit it.
515 if (EmitSpecialLLVMGlobal(GVar))
518 std::string name = Mang->getValueName(GVar);
520 printVisibility(name, GVar->getVisibility());
522 Constant *C = GVar->getInitializer();
523 if (isa<MDNode>(C) || isa<MDString>(C))
525 const Type *Type = C->getType();
526 unsigned Size = TD->getTypeAllocSize(Type);
527 unsigned Align = TD->getPreferredAlignmentLog(GVar);
529 SwitchToSection(TAI->SectionForGlobal(GVar));
531 if (C->isNullValue() && /* FIXME: Verify correct */
532 !GVar->hasSection() &&
533 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
534 GVar->isWeakForLinker())) {
535 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
537 if (GVar->hasExternalLinkage()) {
538 O << "\t.global " << name << '\n';
539 O << "\t.type " << name << ", @object\n";
541 O << "\t.zero " << Size << '\n';
542 } else if (GVar->hasLocalLinkage()) {
543 O << TAI->getLCOMMDirective() << name << ',' << Size;
545 O << ".comm " << name << ',' << Size;
547 O << "\t\t" << TAI->getCommentString() << " '";
548 PrintUnmangledNameSafely(GVar, O);
553 switch (GVar->getLinkage()) {
554 // Should never be seen for the CellSPU platform...
555 case GlobalValue::LinkOnceAnyLinkage:
556 case GlobalValue::LinkOnceODRLinkage:
557 case GlobalValue::WeakAnyLinkage:
558 case GlobalValue::WeakODRLinkage:
559 case GlobalValue::CommonLinkage:
560 O << "\t.global " << name << '\n'
561 << "\t.type " << name << ", @object\n"
562 << "\t.weak " << name << '\n';
564 case GlobalValue::AppendingLinkage:
565 // FIXME: appending linkage variables should go into a section of
566 // their name or something. For now, just emit them as external.
567 case GlobalValue::ExternalLinkage:
568 // If external or appending, declare as a global symbol
569 O << "\t.global " << name << '\n'
570 << "\t.type " << name << ", @object\n";
572 case GlobalValue::PrivateLinkage:
573 case GlobalValue::InternalLinkage:
576 llvm_report_error("Unknown linkage type!");
579 EmitAlignment(Align, GVar);
580 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
581 PrintUnmangledNameSafely(GVar, O);
584 EmitGlobalConstant(C);
588 bool LinuxAsmPrinter::doFinalization(Module &M) {
589 // Print out module-level global variables here.
590 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
592 printModuleLevelGV(I);
594 return AsmPrinter::doFinalization(M);
597 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
598 /// assembly code for a MachineFunction to the given output stream, in a format
599 /// that the Linux SPU assembler can deal with.
601 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
602 SPUTargetMachine &tm,
604 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
607 // Force static initialization.
608 extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
611 static struct Register {
613 SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);