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/FormattedStream.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/Target/TargetRegistry.h"
41 #include "llvm/ADT/Statistic.h"
42 #include "llvm/ADT/StringExtras.h"
47 STATISTIC(EmittedInsts, "Number of machine instrs printed");
49 const std::string bss_section(".bss");
51 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
52 std::set<std::string> FnStubs, GVStubs;
54 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
55 const TargetAsmInfo *T, bool V) :
56 AsmPrinter(O, TM, T, V) {}
58 virtual const char *getPassName() const {
59 return "STI CBEA SPU Assembly Printer";
62 SPUTargetMachine &getTM() {
63 return static_cast<SPUTargetMachine&>(TM);
66 /// printInstruction - This method is automatically generated by tablegen
67 /// from the instruction set description. This method returns true if the
68 /// machine instruction was sufficiently described to print it, otherwise it
70 bool printInstruction(const MachineInstr *MI);
72 void printMachineInstruction(const MachineInstr *MI);
73 void printOp(const MachineOperand &MO);
75 /// printRegister - Print register according to target requirements.
77 void printRegister(const MachineOperand &MO, bool R0AsZero) {
78 unsigned RegNo = MO.getReg();
79 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
81 O << TM.getRegisterInfo()->get(RegNo).AsmName;
84 void printOperand(const MachineInstr *MI, unsigned OpNo) {
85 const MachineOperand &MO = MI->getOperand(OpNo);
87 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
88 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
89 } else if (MO.isImm()) {
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);
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");
114 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
116 unsigned int value = MI->getOperand(OpNo).getImm();
117 assert(value < (1 << 8) && "Invalid u7 argument");
122 printShufAddr(const MachineInstr *MI, unsigned OpNo)
124 char value = MI->getOperand(OpNo).getImm();
127 printOperand(MI, OpNo+1);
132 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
134 O << (short) MI->getOperand(OpNo).getImm();
138 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
140 O << (unsigned short)MI->getOperand(OpNo).getImm();
144 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
146 O << (unsigned)MI->getOperand(OpNo).getImm();
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 << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
157 printOperand(MI, OpNo+1);
161 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
163 unsigned int value = MI->getOperand(OpNo).getImm();
164 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
169 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
171 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
173 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
174 && "Invalid s10 argument");
179 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
181 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
183 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
188 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
190 assert(MI->getOperand(OpNo).isImm() &&
191 "printDFormAddr first operand is not immediate");
192 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
193 int16_t value16 = int16_t(value);
194 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
195 && "Invalid dform s10 offset argument");
196 O << (value16 & ~0xf) << "(";
197 printOperand(MI, OpNo+1);
202 printAddr256K(const MachineInstr *MI, unsigned OpNo)
204 /* Note: operand 1 is an offset or symbol name. */
205 if (MI->getOperand(OpNo).isImm()) {
206 printS16ImmOperand(MI, OpNo);
208 printOp(MI->getOperand(OpNo));
209 if (MI->getOperand(OpNo+1).isImm()) {
210 int displ = int(MI->getOperand(OpNo+1).getImm());
219 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
220 printOp(MI->getOperand(OpNo));
223 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
224 // Used to generate a ".-<target>", but it turns out that the assembler
225 // really wants the target.
227 // N.B.: This operand is used for call targets. Branch hints are another
229 printOp(MI->getOperand(OpNo));
232 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
233 // HBR operands are generated in front of branches, hence, the
234 // program counter plus the target.
236 printOp(MI->getOperand(OpNo));
239 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
240 if (MI->getOperand(OpNo).isImm()) {
241 printS16ImmOperand(MI, OpNo);
243 printOp(MI->getOperand(OpNo));
248 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
249 if (MI->getOperand(OpNo).isImm()) {
250 printS16ImmOperand(MI, OpNo);
252 printOp(MI->getOperand(OpNo));
257 /// Print local store address
258 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
259 printOp(MI->getOperand(OpNo));
262 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
263 if (MI->getOperand(OpNo).isImm()) {
264 int value = (int) MI->getOperand(OpNo).getImm();
265 assert((value >= 0 && value < 16)
266 && "Invalid negated immediate rotate 7-bit argument");
269 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
273 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
274 if (MI->getOperand(OpNo).isImm()) {
275 int value = (int) MI->getOperand(OpNo).getImm();
276 assert((value >= 0 && value <= 32)
277 && "Invalid negated immediate rotate 7-bit argument");
280 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
284 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
285 //! Assembly printer cleanup after function has been emitted
286 virtual bool doFinalization(Module &M) = 0;
289 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
290 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
293 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
294 const TargetAsmInfo *T, bool V)
295 : SPUAsmPrinter(O, TM, T, V), DW(0) {}
297 virtual const char *getPassName() const {
298 return "STI CBEA SPU Assembly Printer";
301 bool runOnMachineFunction(MachineFunction &F);
302 bool doInitialization(Module &M);
303 //! Dump globals, perform cleanup after function emission
304 bool doFinalization(Module &M);
306 void getAnalysisUsage(AnalysisUsage &AU) const {
307 AU.setPreservesAll();
308 AU.addRequired<MachineModuleInfo>();
309 AU.addRequired<DwarfWriter>();
310 SPUAsmPrinter::getAnalysisUsage(AU);
313 //! Emit a global variable according to its section and type
314 void printModuleLevelGV(const GlobalVariable* GVar);
316 } // end of anonymous namespace
318 // Include the auto-generated portion of the assembly writer
319 #include "SPUGenAsmWriter.inc"
321 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
322 switch (MO.getType()) {
323 case MachineOperand::MO_Immediate:
324 llvm_report_error("printOp() does not handle immediate values");
327 case MachineOperand::MO_MachineBasicBlock:
328 printBasicBlockLabel(MO.getMBB());
330 case MachineOperand::MO_JumpTableIndex:
331 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
332 << '_' << MO.getIndex();
334 case MachineOperand::MO_ConstantPoolIndex:
335 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
336 << '_' << MO.getIndex();
338 case MachineOperand::MO_ExternalSymbol:
339 // Computing the address of an external symbol, not calling it.
340 if (TM.getRelocationModel() != Reloc::Static) {
341 std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
342 GVStubs.insert(Name);
343 O << "L" << Name << "$non_lazy_ptr";
346 O << TAI->getGlobalPrefix() << MO.getSymbolName();
348 case MachineOperand::MO_GlobalAddress: {
349 // Computing the address of a global symbol, not calling it.
350 GlobalValue *GV = MO.getGlobal();
351 std::string Name = Mang->getMangledName(GV);
353 // External or weakly linked global variables need non-lazily-resolved
355 if (TM.getRelocationModel() != Reloc::Static) {
356 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
357 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
358 GVStubs.insert(Name);
359 O << "L" << Name << "$non_lazy_ptr";
368 O << "<unknown operand type: " << MO.getType() << ">";
373 /// PrintAsmOperand - Print out an operand for an inline asm expression.
375 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
377 const char *ExtraCode) {
378 // Does this asm operand have a single letter operand modifier?
379 if (ExtraCode && ExtraCode[0]) {
380 if (ExtraCode[1] != 0) return true; // Unknown modifier.
382 switch (ExtraCode[0]) {
383 default: return true; // Unknown modifier.
384 case 'L': // Write second word of DImode reference.
385 // Verify that this operand has two consecutive registers.
386 if (!MI->getOperand(OpNo).isReg() ||
387 OpNo+1 == MI->getNumOperands() ||
388 !MI->getOperand(OpNo+1).isReg())
390 ++OpNo; // Return the high-part.
395 printOperand(MI, OpNo);
399 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
402 const char *ExtraCode) {
403 if (ExtraCode && ExtraCode[0])
404 return true; // Unknown modifier.
405 printMemRegReg(MI, OpNo);
409 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
410 /// to the current output stream.
412 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
414 printInstruction(MI);
417 /// runOnMachineFunction - This uses the printMachineInstruction()
418 /// method to print assembly for each instruction.
421 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
425 SetupMachineFunction(MF);
428 // Print out constants referenced by the function
429 EmitConstantPool(MF.getConstantPool());
431 // Print out labels for the function.
432 const Function *F = MF.getFunction();
434 SwitchToSection(TAI->SectionForGlobal(F));
435 EmitAlignment(MF.getAlignment(), F);
437 switch (F->getLinkage()) {
438 default: llvm_unreachable("Unknown linkage type!");
439 case Function::PrivateLinkage:
440 case Function::InternalLinkage: // Symbols default to internal.
442 case Function::ExternalLinkage:
443 O << "\t.global\t" << CurrentFnName << "\n"
444 << "\t.type\t" << CurrentFnName << ", @function\n";
446 case Function::WeakAnyLinkage:
447 case Function::WeakODRLinkage:
448 case Function::LinkOnceAnyLinkage:
449 case Function::LinkOnceODRLinkage:
450 O << "\t.global\t" << CurrentFnName << "\n";
451 O << "\t.weak_definition\t" << CurrentFnName << "\n";
454 O << CurrentFnName << ":\n";
456 // Emit pre-function debug information.
457 DW->BeginFunction(&MF);
459 // Print out code for the function.
460 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
462 // Print a label for the basic block.
463 if (I != MF.begin()) {
464 printBasicBlockLabel(I, true, true);
467 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
469 // Print the assembly for the instruction.
470 printMachineInstruction(II);
474 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
476 // Print out jump tables referenced by the function.
477 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
479 // Emit post-function debug information.
480 DW->EndFunction(&MF);
482 // We didn't modify anything.
487 bool LinuxAsmPrinter::doInitialization(Module &M) {
488 bool Result = AsmPrinter::doInitialization(M);
489 DW = getAnalysisIfAvailable<DwarfWriter>();
490 SwitchToTextSection("\t.text");
494 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
495 /// Don't print things like \\n or \\0.
496 static void PrintUnmangledNameSafely(const Value *V, formatted_raw_ostream &OS) {
497 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
504 Emit a global variable according to its section, alignment, etc.
506 \note This code was shamelessly copied from the PowerPC's assembly printer,
507 which sort of screams for some kind of refactorization of common code.
509 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
510 const TargetData *TD = TM.getTargetData();
512 if (!GVar->hasInitializer())
515 // Check to see if this is a special global used by LLVM, if so, emit it.
516 if (EmitSpecialLLVMGlobal(GVar))
519 std::string name = Mang->getMangledName(GVar);
521 printVisibility(name, GVar->getVisibility());
523 Constant *C = GVar->getInitializer();
524 if (isa<MDNode>(C) || isa<MDString>(C))
526 const Type *Type = C->getType();
527 unsigned Size = TD->getTypeAllocSize(Type);
528 unsigned Align = TD->getPreferredAlignmentLog(GVar);
530 SwitchToSection(TAI->SectionForGlobal(GVar));
532 if (C->isNullValue() && /* FIXME: Verify correct */
533 !GVar->hasSection() &&
534 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
535 GVar->isWeakForLinker())) {
536 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
538 if (GVar->hasExternalLinkage()) {
539 O << "\t.global " << name << '\n';
540 O << "\t.type " << name << ", @object\n";
542 O << "\t.zero " << Size << '\n';
543 } else if (GVar->hasLocalLinkage()) {
544 O << TAI->getLCOMMDirective() << name << ',' << Size;
546 O << ".comm " << name << ',' << Size;
548 O << "\t\t" << TAI->getCommentString() << " '";
549 PrintUnmangledNameSafely(GVar, O);
554 switch (GVar->getLinkage()) {
555 // Should never be seen for the CellSPU platform...
556 case GlobalValue::LinkOnceAnyLinkage:
557 case GlobalValue::LinkOnceODRLinkage:
558 case GlobalValue::WeakAnyLinkage:
559 case GlobalValue::WeakODRLinkage:
560 case GlobalValue::CommonLinkage:
561 O << "\t.global " << name << '\n'
562 << "\t.type " << name << ", @object\n"
563 << "\t.weak " << name << '\n';
565 case GlobalValue::AppendingLinkage:
566 // FIXME: appending linkage variables should go into a section of
567 // their name or something. For now, just emit them as external.
568 case GlobalValue::ExternalLinkage:
569 // If external or appending, declare as a global symbol
570 O << "\t.global " << name << '\n'
571 << "\t.type " << name << ", @object\n";
573 case GlobalValue::PrivateLinkage:
574 case GlobalValue::InternalLinkage:
577 llvm_report_error("Unknown linkage type!");
580 EmitAlignment(Align, GVar);
581 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
582 PrintUnmangledNameSafely(GVar, O);
585 EmitGlobalConstant(C);
589 bool LinuxAsmPrinter::doFinalization(Module &M) {
590 // Print out module-level global variables here.
591 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
593 printModuleLevelGV(I);
595 return AsmPrinter::doFinalization(M);
598 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
599 /// assembly code for a MachineFunction to the given output stream, in a format
600 /// that the Linux SPU assembler can deal with.
602 FunctionPass *llvm::createSPUAsmPrinterPass(formatted_raw_ostream &o,
605 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
608 // Force static initialization.
609 extern "C" void LLVMInitializeCellSPUAsmPrinter() {
610 extern Target TheCellSPUTarget;
611 TargetRegistry::RegisterAsmPrinter(TheCellSPUTarget, createSPUAsmPrinterPass);