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/Metadata.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/TargetLoweringObjectFile.h"
38 #include "llvm/Target/TargetInstrInfo.h"
39 #include "llvm/Target/TargetOptions.h"
40 #include "llvm/Target/TargetRegisterInfo.h"
41 #include "llvm/Target/TargetRegistry.h"
42 #include "llvm/ADT/Statistic.h"
43 #include "llvm/ADT/StringExtras.h"
48 STATISTIC(EmittedInsts, "Number of machine instrs printed");
50 const std::string bss_section(".bss");
52 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
53 std::set<std::string> FnStubs, GVStubs;
55 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56 const TargetAsmInfo *T, bool V) :
57 AsmPrinter(O, TM, T, V) {}
59 virtual const char *getPassName() const {
60 return "STI CBEA SPU Assembly Printer";
63 SPUTargetMachine &getTM() {
64 return static_cast<SPUTargetMachine&>(TM);
67 /// printInstruction - This method is automatically generated by tablegen
68 /// from the instruction set description. This method returns true if the
69 /// machine instruction was sufficiently described to print it, otherwise it
71 bool printInstruction(const MachineInstr *MI);
73 void printMachineInstruction(const MachineInstr *MI);
74 void printOp(const MachineOperand &MO);
76 /// printRegister - Print register according to target requirements.
78 void printRegister(const MachineOperand &MO, bool R0AsZero) {
79 unsigned RegNo = MO.getReg();
80 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
82 O << TM.getRegisterInfo()->get(RegNo).AsmName;
85 void printOperand(const MachineInstr *MI, unsigned OpNo) {
86 const MachineOperand &MO = MI->getOperand(OpNo);
88 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
89 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
90 } else if (MO.isImm()) {
97 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
98 unsigned AsmVariant, const char *ExtraCode);
99 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
100 unsigned AsmVariant, const char *ExtraCode);
104 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
106 int value = MI->getOperand(OpNo).getImm();
107 value = (value << (32 - 7)) >> (32 - 7);
109 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
110 && "Invalid s7 argument");
115 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
117 unsigned int value = MI->getOperand(OpNo).getImm();
118 assert(value < (1 << 8) && "Invalid u7 argument");
123 printShufAddr(const MachineInstr *MI, unsigned OpNo)
125 char value = MI->getOperand(OpNo).getImm();
128 printOperand(MI, OpNo+1);
133 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
135 O << (short) MI->getOperand(OpNo).getImm();
139 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
141 O << (unsigned short)MI->getOperand(OpNo).getImm();
145 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
147 O << (unsigned)MI->getOperand(OpNo).getImm();
151 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
152 // When used as the base register, r0 reads constant zero rather than
153 // the value contained in the register. For this reason, the darwin
154 // assembler requires that we print r0 as 0 (no r) when used as the base.
155 const MachineOperand &MO = MI->getOperand(OpNo);
156 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
158 printOperand(MI, OpNo+1);
162 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
164 unsigned int value = MI->getOperand(OpNo).getImm();
165 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
170 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
172 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
174 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
175 && "Invalid s10 argument");
180 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
182 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
184 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
189 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
191 assert(MI->getOperand(OpNo).isImm() &&
192 "printDFormAddr first operand is not immediate");
193 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
194 int16_t value16 = int16_t(value);
195 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
196 && "Invalid dform s10 offset argument");
197 O << (value16 & ~0xf) << "(";
198 printOperand(MI, OpNo+1);
203 printAddr256K(const MachineInstr *MI, unsigned OpNo)
205 /* Note: operand 1 is an offset or symbol name. */
206 if (MI->getOperand(OpNo).isImm()) {
207 printS16ImmOperand(MI, OpNo);
209 printOp(MI->getOperand(OpNo));
210 if (MI->getOperand(OpNo+1).isImm()) {
211 int displ = int(MI->getOperand(OpNo+1).getImm());
220 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
221 printOp(MI->getOperand(OpNo));
224 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
225 // Used to generate a ".-<target>", but it turns out that the assembler
226 // really wants the target.
228 // N.B.: This operand is used for call targets. Branch hints are another
230 printOp(MI->getOperand(OpNo));
233 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
234 // HBR operands are generated in front of branches, hence, the
235 // program counter plus the target.
237 printOp(MI->getOperand(OpNo));
240 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
241 if (MI->getOperand(OpNo).isImm()) {
242 printS16ImmOperand(MI, OpNo);
244 printOp(MI->getOperand(OpNo));
249 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
250 if (MI->getOperand(OpNo).isImm()) {
251 printS16ImmOperand(MI, OpNo);
253 printOp(MI->getOperand(OpNo));
258 /// Print local store address
259 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
260 printOp(MI->getOperand(OpNo));
263 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
264 if (MI->getOperand(OpNo).isImm()) {
265 int value = (int) MI->getOperand(OpNo).getImm();
266 assert((value >= 0 && value < 16)
267 && "Invalid negated immediate rotate 7-bit argument");
270 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
274 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
275 if (MI->getOperand(OpNo).isImm()) {
276 int value = (int) MI->getOperand(OpNo).getImm();
277 assert((value >= 0 && value <= 32)
278 && "Invalid negated immediate rotate 7-bit argument");
281 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
285 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
288 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
289 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
292 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &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);
303 void getAnalysisUsage(AnalysisUsage &AU) const {
304 AU.setPreservesAll();
305 AU.addRequired<MachineModuleInfo>();
306 AU.addRequired<DwarfWriter>();
307 SPUAsmPrinter::getAnalysisUsage(AU);
310 //! Emit a global variable according to its section and type
311 void PrintGlobalVariable(const GlobalVariable* GVar);
313 } // end of anonymous namespace
315 // Include the auto-generated portion of the assembly writer
316 #include "SPUGenAsmWriter.inc"
318 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
319 switch (MO.getType()) {
320 case MachineOperand::MO_Immediate:
321 llvm_report_error("printOp() does not handle immediate values");
324 case MachineOperand::MO_MachineBasicBlock:
325 printBasicBlockLabel(MO.getMBB());
327 case MachineOperand::MO_JumpTableIndex:
328 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
329 << '_' << MO.getIndex();
331 case MachineOperand::MO_ConstantPoolIndex:
332 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
333 << '_' << MO.getIndex();
335 case MachineOperand::MO_ExternalSymbol:
336 // Computing the address of an external symbol, not calling it.
337 if (TM.getRelocationModel() != Reloc::Static) {
338 std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
339 GVStubs.insert(Name);
340 O << "L" << Name << "$non_lazy_ptr";
343 O << TAI->getGlobalPrefix() << MO.getSymbolName();
345 case MachineOperand::MO_GlobalAddress: {
346 // Computing the address of a global symbol, not calling it.
347 GlobalValue *GV = MO.getGlobal();
348 std::string Name = Mang->getMangledName(GV);
350 // External or weakly linked global variables need non-lazily-resolved
352 if (TM.getRelocationModel() != Reloc::Static) {
353 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
354 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
355 GVStubs.insert(Name);
356 O << "L" << Name << "$non_lazy_ptr";
365 O << "<unknown operand type: " << MO.getType() << ">";
370 /// PrintAsmOperand - Print out an operand for an inline asm expression.
372 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
374 const char *ExtraCode) {
375 // Does this asm operand have a single letter operand modifier?
376 if (ExtraCode && ExtraCode[0]) {
377 if (ExtraCode[1] != 0) return true; // Unknown modifier.
379 switch (ExtraCode[0]) {
380 default: return true; // Unknown modifier.
381 case 'L': // Write second word of DImode reference.
382 // Verify that this operand has two consecutive registers.
383 if (!MI->getOperand(OpNo).isReg() ||
384 OpNo+1 == MI->getNumOperands() ||
385 !MI->getOperand(OpNo+1).isReg())
387 ++OpNo; // Return the high-part.
392 printOperand(MI, OpNo);
396 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
399 const char *ExtraCode) {
400 if (ExtraCode && ExtraCode[0])
401 return true; // Unknown modifier.
402 printMemRegReg(MI, OpNo);
406 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
407 /// to the current output stream.
409 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
411 printInstruction(MI);
414 /// runOnMachineFunction - This uses the printMachineInstruction()
415 /// method to print assembly for each instruction.
418 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
422 SetupMachineFunction(MF);
425 // Print out constants referenced by the function
426 EmitConstantPool(MF.getConstantPool());
428 // Print out labels for the function.
429 const Function *F = MF.getFunction();
431 SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
432 EmitAlignment(MF.getAlignment(), F);
434 switch (F->getLinkage()) {
435 default: llvm_unreachable("Unknown linkage type!");
436 case Function::PrivateLinkage:
437 case Function::LinkerPrivateLinkage:
438 case Function::InternalLinkage: // Symbols default to internal.
440 case Function::ExternalLinkage:
441 O << "\t.global\t" << CurrentFnName << "\n"
442 << "\t.type\t" << CurrentFnName << ", @function\n";
444 case Function::WeakAnyLinkage:
445 case Function::WeakODRLinkage:
446 case Function::LinkOnceAnyLinkage:
447 case Function::LinkOnceODRLinkage:
448 O << "\t.global\t" << CurrentFnName << "\n";
449 O << "\t.weak_definition\t" << CurrentFnName << "\n";
452 O << CurrentFnName << ":\n";
454 // Emit pre-function debug information.
455 DW->BeginFunction(&MF);
457 // Print out code for the function.
458 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
460 // Print a label for the basic block.
461 if (I != MF.begin()) {
462 printBasicBlockLabel(I, true, true);
465 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
467 // Print the assembly for the instruction.
468 printMachineInstruction(II);
472 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
474 // Print out jump tables referenced by the function.
475 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
477 // Emit post-function debug information.
478 DW->EndFunction(&MF);
480 // We didn't modify anything.
485 bool LinuxAsmPrinter::doInitialization(Module &M) {
486 bool Result = AsmPrinter::doInitialization(M);
487 DW = getAnalysisIfAvailable<DwarfWriter>();
488 SwitchToTextSection("\t.text");
492 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
493 /// Don't print things like \\n or \\0.
494 static void PrintUnmangledNameSafely(const Value *V,
495 formatted_raw_ostream &OS) {
496 for (StringRef::iterator it = V->getName().begin(),
497 ie = V->getName().end(); it != ie; ++it)
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::PrintGlobalVariable(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->getMangledName(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(getObjFileLowering().SectionForGlobal(GVar, TM));
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::LinkerPrivateLinkage:
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 // Force static initialization.
590 extern "C" void LLVMInitializeCellSPUAsmPrinter() {
591 RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);