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/Support/Mangler.h"
29 #include "llvm/Support/MathExtras.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Target/TargetAsmInfo.h"
35 #include "llvm/Target/TargetRegisterInfo.h"
36 #include "llvm/Target/TargetInstrInfo.h"
37 #include "llvm/Target/TargetOptions.h"
38 #include "llvm/ADT/Statistic.h"
39 #include "llvm/ADT/StringExtras.h"
44 STATISTIC(EmittedInsts, "Number of machine instrs printed");
46 const std::string bss_section(".bss");
48 struct VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
49 std::set<std::string> FnStubs, GVStubs;
51 SPUAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) :
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. This method returns true if the
66 /// machine instruction was sufficiently described to print it, otherwise it
68 bool printInstruction(const MachineInstr *MI);
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 << TM.getRegisterInfo()->get(RegNo).AsmName;
82 void printOperand(const MachineInstr *MI, unsigned OpNo) {
83 const MachineOperand &MO = MI->getOperand(OpNo);
85 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
86 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
87 } else if (MO.isImm()) {
94 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
95 unsigned AsmVariant, const char *ExtraCode);
96 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
97 unsigned AsmVariant, const char *ExtraCode);
101 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
103 int value = MI->getOperand(OpNo).getImm();
104 value = (value << (32 - 7)) >> (32 - 7);
106 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
107 && "Invalid s7 argument");
112 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
114 unsigned int value = MI->getOperand(OpNo).getImm();
115 assert(value < (1 << 8) && "Invalid u7 argument");
120 printShufAddr(const MachineInstr *MI, unsigned OpNo)
122 char value = MI->getOperand(OpNo).getImm();
125 printOperand(MI, OpNo+1);
130 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
132 O << (short) MI->getOperand(OpNo).getImm();
136 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
138 O << (unsigned short)MI->getOperand(OpNo).getImm();
142 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
144 O << (unsigned)MI->getOperand(OpNo).getImm();
148 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
149 // When used as the base register, r0 reads constant zero rather than
150 // the value contained in the register. For this reason, the darwin
151 // assembler requires that we print r0 as 0 (no r) when used as the base.
152 const MachineOperand &MO = MI->getOperand(OpNo);
153 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
155 printOperand(MI, OpNo+1);
159 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
161 unsigned int value = MI->getOperand(OpNo).getImm();
162 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
167 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
169 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
171 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
172 && "Invalid s10 argument");
177 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
179 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
181 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
186 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
188 const MachineOperand &MO = MI->getOperand(OpNo);
190 "printDFormAddr first operand is not immedate");
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 assert(0 &&"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 assert(0 &&"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 struct VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
292 MachineModuleInfo *MMI;
294 LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
295 const TargetAsmInfo *T) :
296 SPUAsmPrinter(O, TM, T),
301 virtual const char *getPassName() const {
302 return "STI CBEA SPU Assembly Printer";
305 bool runOnMachineFunction(MachineFunction &F);
306 bool doInitialization(Module &M);
307 //! Dump globals, perform cleanup after function emission
308 bool doFinalization(Module &M);
310 void getAnalysisUsage(AnalysisUsage &AU) const {
311 AU.setPreservesAll();
312 AU.addRequired<MachineModuleInfo>();
313 AU.addRequired<DwarfWriter>();
314 SPUAsmPrinter::getAnalysisUsage(AU);
317 //! Emit a global variable according to its section and type
318 void printModuleLevelGV(const GlobalVariable* GVar);
320 } // end of anonymous namespace
322 // Include the auto-generated portion of the assembly writer
323 #include "SPUGenAsmWriter.inc"
325 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
326 switch (MO.getType()) {
327 case MachineOperand::MO_Immediate:
328 cerr << "printOp() does not handle immediate values\n";
332 case MachineOperand::MO_MachineBasicBlock:
333 printBasicBlockLabel(MO.getMBB());
335 case MachineOperand::MO_JumpTableIndex:
336 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
337 << '_' << MO.getIndex();
339 case MachineOperand::MO_ConstantPoolIndex:
340 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
341 << '_' << MO.getIndex();
343 case MachineOperand::MO_ExternalSymbol:
344 // Computing the address of an external symbol, not calling it.
345 if (TM.getRelocationModel() != Reloc::Static) {
346 std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
347 GVStubs.insert(Name);
348 O << "L" << Name << "$non_lazy_ptr";
351 O << TAI->getGlobalPrefix() << MO.getSymbolName();
353 case MachineOperand::MO_GlobalAddress: {
354 // Computing the address of a global symbol, not calling it.
355 GlobalValue *GV = MO.getGlobal();
356 std::string Name = Mang->getValueName(GV);
358 // External or weakly linked global variables need non-lazily-resolved
360 if (TM.getRelocationModel() != Reloc::Static) {
361 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
362 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
363 GVStubs.insert(Name);
364 O << "L" << Name << "$non_lazy_ptr";
370 if (GV->hasExternalWeakLinkage())
371 ExtWeakSymbols.insert(GV);
376 O << "<unknown operand type: " << MO.getType() << ">";
381 /// PrintAsmOperand - Print out an operand for an inline asm expression.
383 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
385 const char *ExtraCode) {
386 // Does this asm operand have a single letter operand modifier?
387 if (ExtraCode && ExtraCode[0]) {
388 if (ExtraCode[1] != 0) return true; // Unknown modifier.
390 switch (ExtraCode[0]) {
391 default: return true; // Unknown modifier.
392 case 'L': // Write second word of DImode reference.
393 // Verify that this operand has two consecutive registers.
394 if (!MI->getOperand(OpNo).isReg() ||
395 OpNo+1 == MI->getNumOperands() ||
396 !MI->getOperand(OpNo+1).isReg())
398 ++OpNo; // Return the high-part.
403 printOperand(MI, OpNo);
407 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
410 const char *ExtraCode) {
411 if (ExtraCode && ExtraCode[0])
412 return true; // Unknown modifier.
413 printMemRegReg(MI, OpNo);
417 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
418 /// to the current output stream.
420 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
422 printInstruction(MI);
425 /// runOnMachineFunction - This uses the printMachineInstruction()
426 /// method to print assembly for each instruction.
429 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
431 SetupMachineFunction(MF);
434 // Print out constants referenced by the function
435 EmitConstantPool(MF.getConstantPool());
437 // Print out labels for the function.
438 const Function *F = MF.getFunction();
440 SwitchToSection(TAI->SectionForGlobal(F));
443 switch (F->getLinkage()) {
444 default: assert(0 && "Unknown linkage type!");
445 case Function::InternalLinkage: // Symbols default to internal.
447 case Function::ExternalLinkage:
448 O << "\t.global\t" << CurrentFnName << "\n"
449 << "\t.type\t" << CurrentFnName << ", @function\n";
451 case Function::WeakLinkage:
452 case Function::LinkOnceLinkage:
453 O << "\t.global\t" << CurrentFnName << "\n";
454 O << "\t.weak_definition\t" << CurrentFnName << "\n";
457 O << CurrentFnName << ":\n";
459 // Emit pre-function debug information.
460 DW->BeginFunction(&MF);
462 // Print out code for the function.
463 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
465 // Print a label for the basic block.
466 if (I != MF.begin()) {
467 printBasicBlockLabel(I, true, true);
470 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
472 // Print the assembly for the instruction.
473 printMachineInstruction(II);
477 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
479 // Print out jump tables referenced by the function.
480 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
482 // Emit post-function debug information.
483 DW->EndFunction(&MF);
485 // We didn't modify anything.
490 bool LinuxAsmPrinter::doInitialization(Module &M) {
491 bool Result = AsmPrinter::doInitialization(M);
492 SwitchToTextSection("\t.text");
493 // Emit initial debug information.
494 DW = getAnalysisToUpdate<DwarfWriter>();
495 assert(DW && "Dwarf Writer is not available");
496 MMI = getAnalysisToUpdate<MachineModuleInfo>();
497 DW->BeginModule(&M, MMI, O, this, TAI);
501 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
502 /// Don't print things like \n or \0.
503 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
504 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
511 Emit a global variable according to its section, alignment, etc.
513 \note This code was shamelessly copied from the PowerPC's assembly printer,
514 which sort of screams for some kind of refactorization of common code.
516 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
517 const TargetData *TD = TM.getTargetData();
519 if (!GVar->hasInitializer())
522 // Check to see if this is a special global used by LLVM, if so, emit it.
523 if (EmitSpecialLLVMGlobal(GVar))
526 std::string name = Mang->getValueName(GVar);
528 printVisibility(name, GVar->getVisibility());
530 Constant *C = GVar->getInitializer();
531 const Type *Type = C->getType();
532 unsigned Size = TD->getABITypeSize(Type);
533 unsigned Align = TD->getPreferredAlignmentLog(GVar);
535 SwitchToSection(TAI->SectionForGlobal(GVar));
537 if (C->isNullValue() && /* FIXME: Verify correct */
538 !GVar->hasSection() &&
539 (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() ||
540 GVar->mayBeOverridden())) {
541 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
543 if (GVar->hasExternalLinkage()) {
544 O << "\t.global " << name << '\n';
545 O << "\t.type " << name << ", @object\n";
547 O << "\t.zero " << Size << '\n';
548 } else if (GVar->hasInternalLinkage()) {
549 O << TAI->getLCOMMDirective() << name << ',' << Size;
551 O << ".comm " << name << ',' << Size;
553 O << "\t\t" << TAI->getCommentString() << " '";
554 PrintUnmangledNameSafely(GVar, O);
559 switch (GVar->getLinkage()) {
560 // Should never be seen for the CellSPU platform...
561 case GlobalValue::LinkOnceLinkage:
562 case GlobalValue::WeakLinkage:
563 case GlobalValue::CommonLinkage:
564 O << "\t.global " << name << '\n'
565 << "\t.type " << name << ", @object\n"
566 << "\t.weak " << name << '\n';
568 case GlobalValue::AppendingLinkage:
569 // FIXME: appending linkage variables should go into a section of
570 // their name or something. For now, just emit them as external.
571 case GlobalValue::ExternalLinkage:
572 // If external or appending, declare as a global symbol
573 O << "\t.global " << name << '\n'
574 << "\t.type " << name << ", @object\n";
576 case GlobalValue::InternalLinkage:
579 cerr << "Unknown linkage type!";
583 EmitAlignment(Align, GVar);
584 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
585 PrintUnmangledNameSafely(GVar, O);
588 // If the initializer is a extern weak symbol, remember to emit the weak
590 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
591 if (GV->hasExternalWeakLinkage())
592 ExtWeakSymbols.insert(GV);
594 EmitGlobalConstant(C);
598 bool LinuxAsmPrinter::doFinalization(Module &M) {
599 // Print out module-level global variables here.
600 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
602 printModuleLevelGV(I);
606 // Emit initial debug information.
609 return AsmPrinter::doFinalization(M);
612 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
613 /// assembly code for a MachineFunction to the given output stream, in a format
614 /// that the Linux SPU assembler can deal with.
616 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
617 SPUTargetMachine &tm) {
618 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo());