Overhaul my earlier submission due to feedback. It's a large patch, but most of
[llvm/msp430.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
blob474a8ad3a4c7f590b3b48166e0bcc10602a1d78c
1 //===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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"
17 #include "SPU.h"
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"
40 #include <set>
41 using namespace llvm;
43 namespace {
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;
50 public:
51 SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
52 const TargetAsmInfo *T, bool F) :
53 AsmPrinter(O, TM, T, F) {}
55 virtual const char *getPassName() const {
56 return "STI CBEA SPU Assembly Printer";
59 SPUTargetMachine &getTM() {
60 return static_cast<SPUTargetMachine&>(TM);
63 /// printInstruction - This method is automatically generated by tablegen
64 /// from the instruction set description. This method returns true if the
65 /// machine instruction was sufficiently described to print it, otherwise it
66 /// returns false.
67 bool printInstruction(const MachineInstr *MI);
69 void printMachineInstruction(const MachineInstr *MI);
70 void printOp(const MachineOperand &MO);
72 /// printRegister - Print register according to target requirements.
73 ///
74 void printRegister(const MachineOperand &MO, bool R0AsZero) {
75 unsigned RegNo = MO.getReg();
76 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
77 "Not physreg??");
78 O << TM.getRegisterInfo()->get(RegNo).AsmName;
81 void printOperand(const MachineInstr *MI, unsigned OpNo) {
82 const MachineOperand &MO = MI->getOperand(OpNo);
83 if (MO.isReg()) {
84 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
85 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
86 } else if (MO.isImm()) {
87 O << MO.getImm();
88 } else {
89 printOp(MO);
93 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
94 unsigned AsmVariant, const char *ExtraCode);
95 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
96 unsigned AsmVariant, const char *ExtraCode);
99 void
100 printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
102 int value = MI->getOperand(OpNo).getImm();
103 value = (value << (32 - 7)) >> (32 - 7);
105 assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
106 && "Invalid s7 argument");
107 O << value;
110 void
111 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
113 unsigned int value = MI->getOperand(OpNo).getImm();
114 assert(value < (1 << 8) && "Invalid u7 argument");
115 O << value;
118 void
119 printShufAddr(const MachineInstr *MI, unsigned OpNo)
121 char value = MI->getOperand(OpNo).getImm();
122 O << (int) value;
123 O << "(";
124 printOperand(MI, OpNo+1);
125 O << ")";
128 void
129 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
131 O << (short) MI->getOperand(OpNo).getImm();
134 void
135 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
137 O << (unsigned short)MI->getOperand(OpNo).getImm();
140 void
141 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
143 O << (unsigned)MI->getOperand(OpNo).getImm();
146 void
147 printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
148 // When used as the base register, r0 reads constant zero rather than
149 // the value contained in the register. For this reason, the darwin
150 // assembler requires that we print r0 as 0 (no r) when used as the base.
151 const MachineOperand &MO = MI->getOperand(OpNo);
152 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
153 O << ", ";
154 printOperand(MI, OpNo+1);
157 void
158 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
160 unsigned int value = MI->getOperand(OpNo).getImm();
161 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
162 O << value;
165 void
166 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
168 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
169 >> 16);
170 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
171 && "Invalid s10 argument");
172 O << value;
175 void
176 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
178 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
179 >> 16);
180 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
181 O << value;
184 void
185 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
187 assert(MI->getOperand(OpNo).isImm() &&
188 "printDFormAddr first operand is not immediate");
189 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
190 int16_t value16 = int16_t(value);
191 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
192 && "Invalid dform s10 offset argument");
193 O << (value16 & ~0xf) << "(";
194 printOperand(MI, OpNo+1);
195 O << ")";
198 void
199 printAddr256K(const MachineInstr *MI, unsigned OpNo)
201 /* Note: operand 1 is an offset or symbol name. */
202 if (MI->getOperand(OpNo).isImm()) {
203 printS16ImmOperand(MI, OpNo);
204 } else {
205 printOp(MI->getOperand(OpNo));
206 if (MI->getOperand(OpNo+1).isImm()) {
207 int displ = int(MI->getOperand(OpNo+1).getImm());
208 if (displ > 0)
209 O << "+" << displ;
210 else if (displ < 0)
211 O << displ;
216 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
217 printOp(MI->getOperand(OpNo));
220 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
221 // Used to generate a ".-<target>", but it turns out that the assembler
222 // really wants the target.
224 // N.B.: This operand is used for call targets. Branch hints are another
225 // animal entirely.
226 printOp(MI->getOperand(OpNo));
229 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
230 // HBR operands are generated in front of branches, hence, the
231 // program counter plus the target.
232 O << ".+";
233 printOp(MI->getOperand(OpNo));
236 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
237 if (MI->getOperand(OpNo).isImm()) {
238 printS16ImmOperand(MI, OpNo);
239 } else {
240 printOp(MI->getOperand(OpNo));
241 O << "@h";
245 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
246 if (MI->getOperand(OpNo).isImm()) {
247 printS16ImmOperand(MI, OpNo);
248 } else {
249 printOp(MI->getOperand(OpNo));
250 O << "@l";
254 /// Print local store address
255 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
256 printOp(MI->getOperand(OpNo));
259 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
260 if (MI->getOperand(OpNo).isImm()) {
261 int value = (int) MI->getOperand(OpNo).getImm();
262 assert((value >= 0 && value < 16)
263 && "Invalid negated immediate rotate 7-bit argument");
264 O << -value;
265 } else {
266 assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
270 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
271 if (MI->getOperand(OpNo).isImm()) {
272 int value = (int) MI->getOperand(OpNo).getImm();
273 assert((value >= 0 && value <= 32)
274 && "Invalid negated immediate rotate 7-bit argument");
275 O << -value;
276 } else {
277 assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
281 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
282 //! Assembly printer cleanup after function has been emitted
283 virtual bool doFinalization(Module &M) = 0;
286 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
287 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
288 DwarfWriter *DW;
289 MachineModuleInfo *MMI;
290 public:
291 LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
292 const TargetAsmInfo *T, bool F)
293 : SPUAsmPrinter(O, TM, T, F), DW(0), MMI(0) {}
295 virtual const char *getPassName() const {
296 return "STI CBEA SPU Assembly Printer";
299 bool runOnMachineFunction(MachineFunction &F);
300 bool doInitialization(Module &M);
301 //! Dump globals, perform cleanup after function emission
302 bool doFinalization(Module &M);
304 void getAnalysisUsage(AnalysisUsage &AU) const {
305 AU.setPreservesAll();
306 AU.addRequired<MachineModuleInfo>();
307 AU.addRequired<DwarfWriter>();
308 SPUAsmPrinter::getAnalysisUsage(AU);
311 //! Emit a global variable according to its section and type
312 void printModuleLevelGV(const GlobalVariable* GVar);
314 } // end of anonymous namespace
316 // Include the auto-generated portion of the assembly writer
317 #include "SPUGenAsmWriter.inc"
319 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
320 switch (MO.getType()) {
321 case MachineOperand::MO_Immediate:
322 cerr << "printOp() does not handle immediate values\n";
323 abort();
324 return;
326 case MachineOperand::MO_MachineBasicBlock:
327 printBasicBlockLabel(MO.getMBB());
328 return;
329 case MachineOperand::MO_JumpTableIndex:
330 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
331 << '_' << MO.getIndex();
332 return;
333 case MachineOperand::MO_ConstantPoolIndex:
334 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
335 << '_' << MO.getIndex();
336 return;
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";
343 return;
345 O << TAI->getGlobalPrefix() << MO.getSymbolName();
346 return;
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
353 // stubs
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";
359 return;
362 O << Name;
364 if (GV->hasExternalWeakLinkage())
365 ExtWeakSymbols.insert(GV);
366 return;
369 default:
370 O << "<unknown operand type: " << MO.getType() << ">";
371 return;
375 /// PrintAsmOperand - Print out an operand for an inline asm expression.
377 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
378 unsigned AsmVariant,
379 const char *ExtraCode) {
380 // Does this asm operand have a single letter operand modifier?
381 if (ExtraCode && ExtraCode[0]) {
382 if (ExtraCode[1] != 0) return true; // Unknown modifier.
384 switch (ExtraCode[0]) {
385 default: return true; // Unknown modifier.
386 case 'L': // Write second word of DImode reference.
387 // Verify that this operand has two consecutive registers.
388 if (!MI->getOperand(OpNo).isReg() ||
389 OpNo+1 == MI->getNumOperands() ||
390 !MI->getOperand(OpNo+1).isReg())
391 return true;
392 ++OpNo; // Return the high-part.
393 break;
397 printOperand(MI, OpNo);
398 return false;
401 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
402 unsigned OpNo,
403 unsigned AsmVariant,
404 const char *ExtraCode) {
405 if (ExtraCode && ExtraCode[0])
406 return true; // Unknown modifier.
407 printMemRegReg(MI, OpNo);
408 return false;
411 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
412 /// to the current output stream.
414 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
415 ++EmittedInsts;
416 printInstruction(MI);
419 /// runOnMachineFunction - This uses the printMachineInstruction()
420 /// method to print assembly for each instruction.
422 bool
423 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
425 this->MF = &MF;
427 SetupMachineFunction(MF);
428 O << "\n\n";
430 // Print out constants referenced by the function
431 EmitConstantPool(MF.getConstantPool());
433 // Print out labels for the function.
434 const Function *F = MF.getFunction();
436 SwitchToSection(TAI->SectionForGlobal(F));
437 EmitAlignment(3, F);
439 switch (F->getLinkage()) {
440 default: assert(0 && "Unknown linkage type!");
441 case Function::PrivateLinkage:
442 case Function::InternalLinkage: // Symbols default to internal.
443 break;
444 case Function::ExternalLinkage:
445 O << "\t.global\t" << CurrentFnName << "\n"
446 << "\t.type\t" << CurrentFnName << ", @function\n";
447 break;
448 case Function::WeakLinkage:
449 case Function::LinkOnceLinkage:
450 O << "\t.global\t" << CurrentFnName << "\n";
451 O << "\t.weak_definition\t" << CurrentFnName << "\n";
452 break;
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();
461 I != E; ++I) {
462 // Print a label for the basic block.
463 if (I != MF.begin()) {
464 printBasicBlockLabel(I, true, true);
465 O << '\n';
467 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
468 II != E; ++II) {
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.
483 return false;
487 bool LinuxAsmPrinter::doInitialization(Module &M) {
488 bool Result = AsmPrinter::doInitialization(M);
489 SwitchToTextSection("\t.text");
490 // Emit initial debug information.
491 DW = getAnalysisIfAvailable<DwarfWriter>();
492 assert(DW && "Dwarf Writer is not available");
493 MMI = getAnalysisIfAvailable<MachineModuleInfo>();
494 DW->BeginModule(&M, MMI, O, this, TAI);
495 return Result;
498 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
499 /// Don't print things like \n or \0.
500 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
501 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
502 Name != E; ++Name)
503 if (isprint(*Name))
504 OS << *Name;
508 Emit a global variable according to its section, alignment, etc.
510 \note This code was shamelessly copied from the PowerPC's assembly printer,
511 which sort of screams for some kind of refactorization of common code.
513 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
514 const TargetData *TD = TM.getTargetData();
516 if (!GVar->hasInitializer())
517 return;
519 // Check to see if this is a special global used by LLVM, if so, emit it.
520 if (EmitSpecialLLVMGlobal(GVar))
521 return;
523 std::string name = Mang->getValueName(GVar);
525 printVisibility(name, GVar->getVisibility());
527 Constant *C = GVar->getInitializer();
528 const Type *Type = C->getType();
529 unsigned Size = TD->getTypePaddedSize(Type);
530 unsigned Align = TD->getPreferredAlignmentLog(GVar);
532 SwitchToSection(TAI->SectionForGlobal(GVar));
534 if (C->isNullValue() && /* FIXME: Verify correct */
535 !GVar->hasSection() &&
536 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
537 GVar->mayBeOverridden())) {
538 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
540 if (GVar->hasExternalLinkage()) {
541 O << "\t.global " << name << '\n';
542 O << "\t.type " << name << ", @object\n";
543 O << name << ":\n";
544 O << "\t.zero " << Size << '\n';
545 } else if (GVar->hasLocalLinkage()) {
546 O << TAI->getLCOMMDirective() << name << ',' << Size;
547 } else {
548 O << ".comm " << name << ',' << Size;
550 O << "\t\t" << TAI->getCommentString() << " '";
551 PrintUnmangledNameSafely(GVar, O);
552 O << "'\n";
553 return;
556 switch (GVar->getLinkage()) {
557 // Should never be seen for the CellSPU platform...
558 case GlobalValue::LinkOnceLinkage:
559 case GlobalValue::WeakLinkage:
560 case GlobalValue::CommonLinkage:
561 O << "\t.global " << name << '\n'
562 << "\t.type " << name << ", @object\n"
563 << "\t.weak " << name << '\n';
564 break;
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";
572 // FALL THROUGH
573 case GlobalValue::PrivateLinkage:
574 case GlobalValue::InternalLinkage:
575 break;
576 default:
577 cerr << "Unknown linkage type!";
578 abort();
581 EmitAlignment(Align, GVar);
582 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
583 PrintUnmangledNameSafely(GVar, O);
584 O << "'\n";
586 // If the initializer is a extern weak symbol, remember to emit the weak
587 // reference!
588 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
589 if (GV->hasExternalWeakLinkage())
590 ExtWeakSymbols.insert(GV);
592 EmitGlobalConstant(C);
593 O << '\n';
596 bool LinuxAsmPrinter::doFinalization(Module &M) {
597 // Print out module-level global variables here.
598 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
599 I != E; ++I)
600 printModuleLevelGV(I);
602 // Emit initial debug information.
603 DW->EndModule();
605 return AsmPrinter::doFinalization(M);
608 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
609 /// assembly code for a MachineFunction to the given output stream, in a format
610 /// that the Linux SPU assembler can deal with.
612 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
613 SPUTargetMachine &tm,
614 bool fast) {
615 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), fast);