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 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
49 std::set<std::string> FnStubs, GVStubs;
51 explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
52 const TargetAsmInfo *T, CodeGenOpt::Level OL,
54 AsmPrinter(O, TM, T, OL, 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. 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 assert(MI->getOperand(OpNo).isImm() &&
189 "printDFormAddr first operand is not immediate");
190 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
191 int16_t value16 = int16_t(value);
192 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
193 && "Invalid dform s10 offset argument");
194 O << (value16 & ~0xf) << "(";
195 printOperand(MI, OpNo+1);
200 printAddr256K(const MachineInstr *MI, unsigned OpNo)
202 /* Note: operand 1 is an offset or symbol name. */
203 if (MI->getOperand(OpNo).isImm()) {
204 printS16ImmOperand(MI, OpNo);
206 printOp(MI->getOperand(OpNo));
207 if (MI->getOperand(OpNo+1).isImm()) {
208 int displ = int(MI->getOperand(OpNo+1).getImm());
217 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
218 printOp(MI->getOperand(OpNo));
221 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
222 // Used to generate a ".-<target>", but it turns out that the assembler
223 // really wants the target.
225 // N.B.: This operand is used for call targets. Branch hints are another
227 printOp(MI->getOperand(OpNo));
230 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
231 // HBR operands are generated in front of branches, hence, the
232 // program counter plus the target.
234 printOp(MI->getOperand(OpNo));
237 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
238 if (MI->getOperand(OpNo).isImm()) {
239 printS16ImmOperand(MI, OpNo);
241 printOp(MI->getOperand(OpNo));
246 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
247 if (MI->getOperand(OpNo).isImm()) {
248 printS16ImmOperand(MI, OpNo);
250 printOp(MI->getOperand(OpNo));
255 /// Print local store address
256 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
257 printOp(MI->getOperand(OpNo));
260 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
261 if (MI->getOperand(OpNo).isImm()) {
262 int value = (int) MI->getOperand(OpNo).getImm();
263 assert((value >= 0 && value < 16)
264 && "Invalid negated immediate rotate 7-bit argument");
267 assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
271 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
272 if (MI->getOperand(OpNo).isImm()) {
273 int value = (int) MI->getOperand(OpNo).getImm();
274 assert((value >= 0 && value <= 32)
275 && "Invalid negated immediate rotate 7-bit argument");
278 assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
282 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
283 //! Assembly printer cleanup after function has been emitted
284 virtual bool doFinalization(Module &M) = 0;
287 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
288 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
291 explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
292 const TargetAsmInfo *T, CodeGenOpt::Level F,
294 : SPUAsmPrinter(O, TM, T, F, 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 cerr << "printOp() does not handle immediate values\n";
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->getValueName(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";
365 if (GV->hasExternalWeakLinkage())
366 ExtWeakSymbols.insert(GV);
371 O << "<unknown operand type: " << MO.getType() << ">";
376 /// PrintAsmOperand - Print out an operand for an inline asm expression.
378 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
380 const char *ExtraCode) {
381 // Does this asm operand have a single letter operand modifier?
382 if (ExtraCode && ExtraCode[0]) {
383 if (ExtraCode[1] != 0) return true; // Unknown modifier.
385 switch (ExtraCode[0]) {
386 default: return true; // Unknown modifier.
387 case 'L': // Write second word of DImode reference.
388 // Verify that this operand has two consecutive registers.
389 if (!MI->getOperand(OpNo).isReg() ||
390 OpNo+1 == MI->getNumOperands() ||
391 !MI->getOperand(OpNo+1).isReg())
393 ++OpNo; // Return the high-part.
398 printOperand(MI, OpNo);
402 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
405 const char *ExtraCode) {
406 if (ExtraCode && ExtraCode[0])
407 return true; // Unknown modifier.
408 printMemRegReg(MI, OpNo);
412 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
413 /// to the current output stream.
415 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
417 printInstruction(MI);
420 /// runOnMachineFunction - This uses the printMachineInstruction()
421 /// method to print assembly for each instruction.
424 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
428 SetupMachineFunction(MF);
431 // Print out constants referenced by the function
432 EmitConstantPool(MF.getConstantPool());
434 // Print out labels for the function.
435 const Function *F = MF.getFunction();
437 SwitchToSection(TAI->SectionForGlobal(F));
440 switch (F->getLinkage()) {
441 default: assert(0 && "Unknown linkage type!");
442 case Function::PrivateLinkage:
443 case Function::InternalLinkage: // Symbols default to internal.
445 case Function::ExternalLinkage:
446 O << "\t.global\t" << CurrentFnName << "\n"
447 << "\t.type\t" << CurrentFnName << ", @function\n";
449 case Function::WeakAnyLinkage:
450 case Function::WeakODRLinkage:
451 case Function::LinkOnceAnyLinkage:
452 case Function::LinkOnceODRLinkage:
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 DW = getAnalysisIfAvailable<DwarfWriter>();
493 SwitchToTextSection("\t.text");
497 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
498 /// Don't print things like \\n or \\0.
499 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
500 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
507 Emit a global variable according to its section, alignment, etc.
509 \note This code was shamelessly copied from the PowerPC's assembly printer,
510 which sort of screams for some kind of refactorization of common code.
512 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
513 const TargetData *TD = TM.getTargetData();
515 if (!GVar->hasInitializer())
518 // Check to see if this is a special global used by LLVM, if so, emit it.
519 if (EmitSpecialLLVMGlobal(GVar))
522 std::string name = Mang->getValueName(GVar);
524 printVisibility(name, GVar->getVisibility());
526 Constant *C = GVar->getInitializer();
527 const Type *Type = C->getType();
528 unsigned Size = TD->getTypeAllocSize(Type);
529 unsigned Align = TD->getPreferredAlignmentLog(GVar);
531 SwitchToSection(TAI->SectionForGlobal(GVar));
533 if (C->isNullValue() && /* FIXME: Verify correct */
534 !GVar->hasSection() &&
535 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
536 GVar->isWeakForLinker())) {
537 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
539 if (GVar->hasExternalLinkage()) {
540 O << "\t.global " << name << '\n';
541 O << "\t.type " << name << ", @object\n";
543 O << "\t.zero " << Size << '\n';
544 } else if (GVar->hasLocalLinkage()) {
545 O << TAI->getLCOMMDirective() << name << ',' << Size;
547 O << ".comm " << name << ',' << Size;
549 O << "\t\t" << TAI->getCommentString() << " '";
550 PrintUnmangledNameSafely(GVar, O);
555 switch (GVar->getLinkage()) {
556 // Should never be seen for the CellSPU platform...
557 case GlobalValue::LinkOnceAnyLinkage:
558 case GlobalValue::LinkOnceODRLinkage:
559 case GlobalValue::WeakAnyLinkage:
560 case GlobalValue::WeakODRLinkage:
561 case GlobalValue::CommonLinkage:
562 O << "\t.global " << name << '\n'
563 << "\t.type " << name << ", @object\n"
564 << "\t.weak " << name << '\n';
566 case GlobalValue::AppendingLinkage:
567 // FIXME: appending linkage variables should go into a section of
568 // their name or something. For now, just emit them as external.
569 case GlobalValue::ExternalLinkage:
570 // If external or appending, declare as a global symbol
571 O << "\t.global " << name << '\n'
572 << "\t.type " << name << ", @object\n";
574 case GlobalValue::PrivateLinkage:
575 case GlobalValue::InternalLinkage:
578 cerr << "Unknown linkage type!";
582 EmitAlignment(Align, GVar);
583 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
584 PrintUnmangledNameSafely(GVar, O);
587 // If the initializer is a extern weak symbol, remember to emit the weak
589 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
590 if (GV->hasExternalWeakLinkage())
591 ExtWeakSymbols.insert(GV);
593 EmitGlobalConstant(C);
597 bool LinuxAsmPrinter::doFinalization(Module &M) {
598 // Print out module-level global variables here.
599 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
601 printModuleLevelGV(I);
603 // Emit initial debug information.
606 return AsmPrinter::doFinalization(M);
609 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
610 /// assembly code for a MachineFunction to the given output stream, in a format
611 /// that the Linux SPU assembler can deal with.
613 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
614 SPUTargetMachine &tm,
615 CodeGenOpt::Level OptLevel,
617 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
620 // Force static initialization.
621 extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
624 static struct Register {
626 SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);