Merge branch 'master' into msp430
[llvm/msp430.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
blobda1bf074de96a57fd31a11fed20b1fd0f981dff0
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 explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
52 const TargetAsmInfo *T, CodeGenOpt::Level OL,
53 bool V) :
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
67 /// returns false.
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.
74 ///
75 void printRegister(const MachineOperand &MO, bool R0AsZero) {
76 unsigned RegNo = MO.getReg();
77 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
78 "Not physreg??");
79 O << TM.getRegisterInfo()->get(RegNo).AsmName;
82 void printOperand(const MachineInstr *MI, unsigned OpNo) {
83 const MachineOperand &MO = MI->getOperand(OpNo);
84 if (MO.isReg()) {
85 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
86 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
87 } else if (MO.isImm()) {
88 O << MO.getImm();
89 } else {
90 printOp(MO);
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);
100 void
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");
108 O << value;
111 void
112 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
114 unsigned int value = MI->getOperand(OpNo).getImm();
115 assert(value < (1 << 8) && "Invalid u7 argument");
116 O << value;
119 void
120 printShufAddr(const MachineInstr *MI, unsigned OpNo)
122 char value = MI->getOperand(OpNo).getImm();
123 O << (int) value;
124 O << "(";
125 printOperand(MI, OpNo+1);
126 O << ")";
129 void
130 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
132 O << (short) MI->getOperand(OpNo).getImm();
135 void
136 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
138 O << (unsigned short)MI->getOperand(OpNo).getImm();
141 void
142 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
144 O << (unsigned)MI->getOperand(OpNo).getImm();
147 void
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;
154 O << ", ";
155 printOperand(MI, OpNo+1);
158 void
159 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
161 unsigned int value = MI->getOperand(OpNo).getImm();
162 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
163 O << value;
166 void
167 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
169 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
170 >> 16);
171 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
172 && "Invalid s10 argument");
173 O << value;
176 void
177 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
179 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
180 >> 16);
181 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
182 O << value;
185 void
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);
196 O << ")";
199 void
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);
205 } else {
206 printOp(MI->getOperand(OpNo));
207 if (MI->getOperand(OpNo+1).isImm()) {
208 int displ = int(MI->getOperand(OpNo+1).getImm());
209 if (displ > 0)
210 O << "+" << displ;
211 else if (displ < 0)
212 O << displ;
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
226 // animal entirely.
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.
233 O << ".+";
234 printOp(MI->getOperand(OpNo));
237 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
238 if (MI->getOperand(OpNo).isImm()) {
239 printS16ImmOperand(MI, OpNo);
240 } else {
241 printOp(MI->getOperand(OpNo));
242 O << "@h";
246 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
247 if (MI->getOperand(OpNo).isImm()) {
248 printS16ImmOperand(MI, OpNo);
249 } else {
250 printOp(MI->getOperand(OpNo));
251 O << "@l";
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");
265 O << -value;
266 } else {
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");
276 O << -value;
277 } else {
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 {
289 DwarfWriter *DW;
290 MachineModuleInfo *MMI;
291 public:
292 explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
293 const TargetAsmInfo *T, CodeGenOpt::Level F,
294 bool V)
295 : SPUAsmPrinter(O, TM, T, F, V), DW(0), MMI(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 cerr << "printOp() does not handle immediate values\n";
325 abort();
326 return;
328 case MachineOperand::MO_MachineBasicBlock:
329 printBasicBlockLabel(MO.getMBB());
330 return;
331 case MachineOperand::MO_JumpTableIndex:
332 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
333 << '_' << MO.getIndex();
334 return;
335 case MachineOperand::MO_ConstantPoolIndex:
336 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
337 << '_' << MO.getIndex();
338 return;
339 case MachineOperand::MO_ExternalSymbol:
340 // Computing the address of an external symbol, not calling it.
341 if (TM.getRelocationModel() != Reloc::Static) {
342 std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
343 GVStubs.insert(Name);
344 O << "L" << Name << "$non_lazy_ptr";
345 return;
347 O << TAI->getGlobalPrefix() << MO.getSymbolName();
348 return;
349 case MachineOperand::MO_GlobalAddress: {
350 // Computing the address of a global symbol, not calling it.
351 GlobalValue *GV = MO.getGlobal();
352 std::string Name = Mang->getValueName(GV);
354 // External or weakly linked global variables need non-lazily-resolved
355 // stubs
356 if (TM.getRelocationModel() != Reloc::Static) {
357 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
358 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
359 GVStubs.insert(Name);
360 O << "L" << Name << "$non_lazy_ptr";
361 return;
364 O << Name;
366 if (GV->hasExternalWeakLinkage())
367 ExtWeakSymbols.insert(GV);
368 return;
371 default:
372 O << "<unknown operand type: " << MO.getType() << ">";
373 return;
377 /// PrintAsmOperand - Print out an operand for an inline asm expression.
379 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
380 unsigned AsmVariant,
381 const char *ExtraCode) {
382 // Does this asm operand have a single letter operand modifier?
383 if (ExtraCode && ExtraCode[0]) {
384 if (ExtraCode[1] != 0) return true; // Unknown modifier.
386 switch (ExtraCode[0]) {
387 default: return true; // Unknown modifier.
388 case 'L': // Write second word of DImode reference.
389 // Verify that this operand has two consecutive registers.
390 if (!MI->getOperand(OpNo).isReg() ||
391 OpNo+1 == MI->getNumOperands() ||
392 !MI->getOperand(OpNo+1).isReg())
393 return true;
394 ++OpNo; // Return the high-part.
395 break;
399 printOperand(MI, OpNo);
400 return false;
403 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
404 unsigned OpNo,
405 unsigned AsmVariant,
406 const char *ExtraCode) {
407 if (ExtraCode && ExtraCode[0])
408 return true; // Unknown modifier.
409 printMemRegReg(MI, OpNo);
410 return false;
413 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
414 /// to the current output stream.
416 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
417 ++EmittedInsts;
418 printInstruction(MI);
421 /// runOnMachineFunction - This uses the printMachineInstruction()
422 /// method to print assembly for each instruction.
424 bool
425 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
427 this->MF = &MF;
429 SetupMachineFunction(MF);
430 O << "\n\n";
432 // Print out constants referenced by the function
433 EmitConstantPool(MF.getConstantPool());
435 // Print out labels for the function.
436 const Function *F = MF.getFunction();
438 SwitchToSection(TAI->SectionForGlobal(F));
439 EmitAlignment(3, F);
441 switch (F->getLinkage()) {
442 default: assert(0 && "Unknown linkage type!");
443 case Function::PrivateLinkage:
444 case Function::InternalLinkage: // Symbols default to internal.
445 break;
446 case Function::ExternalLinkage:
447 O << "\t.global\t" << CurrentFnName << "\n"
448 << "\t.type\t" << CurrentFnName << ", @function\n";
449 break;
450 case Function::WeakAnyLinkage:
451 case Function::WeakODRLinkage:
452 case Function::LinkOnceAnyLinkage:
453 case Function::LinkOnceODRLinkage:
454 O << "\t.global\t" << CurrentFnName << "\n";
455 O << "\t.weak_definition\t" << CurrentFnName << "\n";
456 break;
458 O << CurrentFnName << ":\n";
460 // Emit pre-function debug information.
461 DW->BeginFunction(&MF);
463 // Print out code for the function.
464 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
465 I != E; ++I) {
466 // Print a label for the basic block.
467 if (I != MF.begin()) {
468 printBasicBlockLabel(I, true, true);
469 O << '\n';
471 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
472 II != E; ++II) {
473 // Print the assembly for the instruction.
474 printMachineInstruction(II);
478 O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
480 // Print out jump tables referenced by the function.
481 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
483 // Emit post-function debug information.
484 DW->EndFunction(&MF);
486 // We didn't modify anything.
487 return false;
491 bool LinuxAsmPrinter::doInitialization(Module &M) {
492 bool Result = AsmPrinter::doInitialization(M);
493 SwitchToTextSection("\t.text");
494 // Emit initial debug information.
495 DW = getAnalysisIfAvailable<DwarfWriter>();
496 assert(DW && "Dwarf Writer is not available");
497 MMI = getAnalysisIfAvailable<MachineModuleInfo>();
498 DW->BeginModule(&M, MMI, O, this, TAI);
499 return Result;
502 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
503 /// Don't print things like \\n or \\0.
504 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
505 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
506 Name != E; ++Name)
507 if (isprint(*Name))
508 OS << *Name;
512 Emit a global variable according to its section, alignment, etc.
514 \note This code was shamelessly copied from the PowerPC's assembly printer,
515 which sort of screams for some kind of refactorization of common code.
517 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
518 const TargetData *TD = TM.getTargetData();
520 if (!GVar->hasInitializer())
521 return;
523 // Check to see if this is a special global used by LLVM, if so, emit it.
524 if (EmitSpecialLLVMGlobal(GVar))
525 return;
527 std::string name = Mang->getValueName(GVar);
529 printVisibility(name, GVar->getVisibility());
531 Constant *C = GVar->getInitializer();
532 const Type *Type = C->getType();
533 unsigned Size = TD->getTypeAllocSize(Type);
534 unsigned Align = TD->getPreferredAlignmentLog(GVar);
536 SwitchToSection(TAI->SectionForGlobal(GVar));
538 if (C->isNullValue() && /* FIXME: Verify correct */
539 !GVar->hasSection() &&
540 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
541 GVar->isWeakForLinker())) {
542 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
544 if (GVar->hasExternalLinkage()) {
545 O << "\t.global " << name << '\n';
546 O << "\t.type " << name << ", @object\n";
547 O << name << ":\n";
548 O << "\t.zero " << Size << '\n';
549 } else if (GVar->hasLocalLinkage()) {
550 O << TAI->getLCOMMDirective() << name << ',' << Size;
551 } else {
552 O << ".comm " << name << ',' << Size;
554 O << "\t\t" << TAI->getCommentString() << " '";
555 PrintUnmangledNameSafely(GVar, O);
556 O << "'\n";
557 return;
560 switch (GVar->getLinkage()) {
561 // Should never be seen for the CellSPU platform...
562 case GlobalValue::LinkOnceAnyLinkage:
563 case GlobalValue::LinkOnceODRLinkage:
564 case GlobalValue::WeakAnyLinkage:
565 case GlobalValue::WeakODRLinkage:
566 case GlobalValue::CommonLinkage:
567 O << "\t.global " << name << '\n'
568 << "\t.type " << name << ", @object\n"
569 << "\t.weak " << name << '\n';
570 break;
571 case GlobalValue::AppendingLinkage:
572 // FIXME: appending linkage variables should go into a section of
573 // their name or something. For now, just emit them as external.
574 case GlobalValue::ExternalLinkage:
575 // If external or appending, declare as a global symbol
576 O << "\t.global " << name << '\n'
577 << "\t.type " << name << ", @object\n";
578 // FALL THROUGH
579 case GlobalValue::PrivateLinkage:
580 case GlobalValue::InternalLinkage:
581 break;
582 default:
583 cerr << "Unknown linkage type!";
584 abort();
587 EmitAlignment(Align, GVar);
588 O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
589 PrintUnmangledNameSafely(GVar, O);
590 O << "'\n";
592 // If the initializer is a extern weak symbol, remember to emit the weak
593 // reference!
594 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
595 if (GV->hasExternalWeakLinkage())
596 ExtWeakSymbols.insert(GV);
598 EmitGlobalConstant(C);
599 O << '\n';
602 bool LinuxAsmPrinter::doFinalization(Module &M) {
603 // Print out module-level global variables here.
604 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
605 I != E; ++I)
606 printModuleLevelGV(I);
608 // Emit initial debug information.
609 DW->EndModule();
611 return AsmPrinter::doFinalization(M);
614 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
615 /// assembly code for a MachineFunction to the given output stream, in a format
616 /// that the Linux SPU assembler can deal with.
618 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
619 SPUTargetMachine &tm,
620 CodeGenOpt::Level OptLevel,
621 bool verbose) {
622 return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);