pass machinemoduleinfo down into getSymbolForDwarfGlobalReference,
[llvm/avr.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
blob13f01c6635e59fa69ad82aa53adeae2407b41596
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/MC/MCStreamer.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/Target/TargetLoweringObjectFile.h"
32 #include "llvm/Target/TargetInstrInfo.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/Target/TargetRegisterInfo.h"
35 #include "llvm/Target/TargetRegistry.h"
36 #include "llvm/ADT/Statistic.h"
37 #include "llvm/ADT/StringExtras.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Compiler.h"
40 #include "llvm/Support/Debug.h"
41 #include "llvm/Support/ErrorHandling.h"
42 #include "llvm/Support/FormattedStream.h"
43 #include "llvm/Support/Mangler.h"
44 #include "llvm/Support/MathExtras.h"
45 #include <set>
46 using namespace llvm;
48 namespace {
49 STATISTIC(EmittedInsts, "Number of machine instrs printed");
51 const std::string bss_section(".bss");
53 class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
54 std::set<std::string> FnStubs, GVStubs;
55 public:
56 explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
57 const MCAsmInfo *T, bool V) :
58 AsmPrinter(O, TM, T, V) {}
60 virtual const char *getPassName() const {
61 return "STI CBEA SPU Assembly Printer";
64 SPUTargetMachine &getTM() {
65 return static_cast<SPUTargetMachine&>(TM);
68 /// printInstruction - This method is automatically generated by tablegen
69 /// from the instruction set description.
70 void printInstruction(const MachineInstr *MI);
71 static const char *getRegisterName(unsigned RegNo);
74 void printMachineInstruction(const MachineInstr *MI);
75 void printOp(const MachineOperand &MO);
77 /// printRegister - Print register according to target requirements.
78 ///
79 void printRegister(const MachineOperand &MO, bool R0AsZero) {
80 unsigned RegNo = MO.getReg();
81 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
82 "Not physreg??");
83 O << getRegisterName(RegNo);
86 void printOperand(const MachineInstr *MI, unsigned OpNo) {
87 const MachineOperand &MO = MI->getOperand(OpNo);
88 if (MO.isReg()) {
89 O << getRegisterName(MO.getReg());
90 } else if (MO.isImm()) {
91 O << MO.getImm();
92 } else {
93 printOp(MO);
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);
103 void
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");
111 O << value;
114 void
115 printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
117 unsigned int value = MI->getOperand(OpNo).getImm();
118 assert(value < (1 << 8) && "Invalid u7 argument");
119 O << value;
122 void
123 printShufAddr(const MachineInstr *MI, unsigned OpNo)
125 char value = MI->getOperand(OpNo).getImm();
126 O << (int) value;
127 O << "(";
128 printOperand(MI, OpNo+1);
129 O << ")";
132 void
133 printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
135 O << (short) MI->getOperand(OpNo).getImm();
138 void
139 printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
141 O << (unsigned short)MI->getOperand(OpNo).getImm();
144 void
145 printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
147 O << (unsigned)MI->getOperand(OpNo).getImm();
150 void
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 << getRegisterName(MO.getReg()) << ", ";
157 printOperand(MI, OpNo+1);
160 void
161 printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
163 unsigned int value = MI->getOperand(OpNo).getImm();
164 assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
165 O << value;
168 void
169 printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
171 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
172 >> 16);
173 assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
174 && "Invalid s10 argument");
175 O << value;
178 void
179 printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
181 short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
182 >> 16);
183 assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
184 O << value;
187 void
188 printDFormAddr(const MachineInstr *MI, unsigned OpNo)
190 assert(MI->getOperand(OpNo).isImm() &&
191 "printDFormAddr first operand is not immediate");
192 int64_t value = int64_t(MI->getOperand(OpNo).getImm());
193 int16_t value16 = int16_t(value);
194 assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
195 && "Invalid dform s10 offset argument");
196 O << (value16 & ~0xf) << "(";
197 printOperand(MI, OpNo+1);
198 O << ")";
201 void
202 printAddr256K(const MachineInstr *MI, unsigned OpNo)
204 /* Note: operand 1 is an offset or symbol name. */
205 if (MI->getOperand(OpNo).isImm()) {
206 printS16ImmOperand(MI, OpNo);
207 } else {
208 printOp(MI->getOperand(OpNo));
209 if (MI->getOperand(OpNo+1).isImm()) {
210 int displ = int(MI->getOperand(OpNo+1).getImm());
211 if (displ > 0)
212 O << "+" << displ;
213 else if (displ < 0)
214 O << displ;
219 void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
220 printOp(MI->getOperand(OpNo));
223 void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
224 // Used to generate a ".-<target>", but it turns out that the assembler
225 // really wants the target.
227 // N.B.: This operand is used for call targets. Branch hints are another
228 // animal entirely.
229 printOp(MI->getOperand(OpNo));
232 void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
233 // HBR operands are generated in front of branches, hence, the
234 // program counter plus the target.
235 O << ".+";
236 printOp(MI->getOperand(OpNo));
239 void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
240 if (MI->getOperand(OpNo).isImm()) {
241 printS16ImmOperand(MI, OpNo);
242 } else {
243 printOp(MI->getOperand(OpNo));
244 O << "@h";
248 void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
249 if (MI->getOperand(OpNo).isImm()) {
250 printS16ImmOperand(MI, OpNo);
251 } else {
252 printOp(MI->getOperand(OpNo));
253 O << "@l";
257 /// Print local store address
258 void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
259 printOp(MI->getOperand(OpNo));
262 void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
263 if (MI->getOperand(OpNo).isImm()) {
264 int value = (int) MI->getOperand(OpNo).getImm();
265 assert((value >= 0 && value < 16)
266 && "Invalid negated immediate rotate 7-bit argument");
267 O << -value;
268 } else {
269 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
273 void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
274 if (MI->getOperand(OpNo).isImm()) {
275 int value = (int) MI->getOperand(OpNo).getImm();
276 assert((value >= 0 && value <= 32)
277 && "Invalid negated immediate rotate 7-bit argument");
278 O << -value;
279 } else {
280 llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
284 virtual bool runOnMachineFunction(MachineFunction &F) = 0;
287 /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
288 class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
289 DwarfWriter *DW;
290 public:
291 explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
292 const MCAsmInfo *T, bool V)
293 : SPUAsmPrinter(O, TM, T, V), DW(0) {}
295 virtual const char *getPassName() const {
296 return "STI CBEA SPU Assembly Printer";
299 bool runOnMachineFunction(MachineFunction &F);
300 bool doInitialization(Module &M);
302 void getAnalysisUsage(AnalysisUsage &AU) const {
303 AU.setPreservesAll();
304 AU.addRequired<MachineModuleInfo>();
305 AU.addRequired<DwarfWriter>();
306 SPUAsmPrinter::getAnalysisUsage(AU);
309 //! Emit a global variable according to its section and type
310 void PrintGlobalVariable(const GlobalVariable* GVar);
312 } // end of anonymous namespace
314 // Include the auto-generated portion of the assembly writer
315 #include "SPUGenAsmWriter.inc"
317 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
318 switch (MO.getType()) {
319 case MachineOperand::MO_Immediate:
320 llvm_report_error("printOp() does not handle immediate values");
321 return;
323 case MachineOperand::MO_MachineBasicBlock:
324 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
325 return;
326 case MachineOperand::MO_JumpTableIndex:
327 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
328 << '_' << MO.getIndex();
329 return;
330 case MachineOperand::MO_ConstantPoolIndex:
331 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
332 << '_' << MO.getIndex();
333 return;
334 case MachineOperand::MO_ExternalSymbol:
335 // Computing the address of an external symbol, not calling it.
336 if (TM.getRelocationModel() != Reloc::Static) {
337 std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName();
338 GVStubs.insert(Name);
339 O << "L" << Name << "$non_lazy_ptr";
340 return;
342 O << MAI->getGlobalPrefix() << MO.getSymbolName();
343 return;
344 case MachineOperand::MO_GlobalAddress: {
345 // Computing the address of a global symbol, not calling it.
346 GlobalValue *GV = MO.getGlobal();
347 std::string Name = Mang->getMangledName(GV);
349 // External or weakly linked global variables need non-lazily-resolved
350 // stubs
351 if (TM.getRelocationModel() != Reloc::Static) {
352 if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
353 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
354 GVStubs.insert(Name);
355 O << "L" << Name << "$non_lazy_ptr";
356 return;
359 O << Name;
360 return;
363 default:
364 O << "<unknown operand type: " << MO.getType() << ">";
365 return;
369 /// PrintAsmOperand - Print out an operand for an inline asm expression.
371 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
372 unsigned AsmVariant,
373 const char *ExtraCode) {
374 // Does this asm operand have a single letter operand modifier?
375 if (ExtraCode && ExtraCode[0]) {
376 if (ExtraCode[1] != 0) return true; // Unknown modifier.
378 switch (ExtraCode[0]) {
379 default: return true; // Unknown modifier.
380 case 'L': // Write second word of DImode reference.
381 // Verify that this operand has two consecutive registers.
382 if (!MI->getOperand(OpNo).isReg() ||
383 OpNo+1 == MI->getNumOperands() ||
384 !MI->getOperand(OpNo+1).isReg())
385 return true;
386 ++OpNo; // Return the high-part.
387 break;
391 printOperand(MI, OpNo);
392 return false;
395 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
396 unsigned OpNo,
397 unsigned AsmVariant,
398 const char *ExtraCode) {
399 if (ExtraCode && ExtraCode[0])
400 return true; // Unknown modifier.
401 printMemRegReg(MI, OpNo);
402 return false;
405 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
406 /// to the current output stream.
408 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
409 ++EmittedInsts;
410 processDebugLoc(MI->getDebugLoc());
411 printInstruction(MI);
413 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
414 EmitComments(*MI);
415 O << '\n';
418 /// runOnMachineFunction - This uses the printMachineInstruction()
419 /// method to print assembly for each instruction.
421 bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
422 this->MF = &MF;
424 SetupMachineFunction(MF);
425 O << "\n\n";
427 // Print out constants referenced by the function
428 EmitConstantPool(MF.getConstantPool());
430 // Print out labels for the function.
431 const Function *F = MF.getFunction();
433 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
434 EmitAlignment(MF.getAlignment(), F);
436 switch (F->getLinkage()) {
437 default: llvm_unreachable("Unknown linkage type!");
438 case Function::PrivateLinkage:
439 case Function::LinkerPrivateLinkage:
440 case Function::InternalLinkage: // Symbols default to internal.
441 break;
442 case Function::ExternalLinkage:
443 O << "\t.global\t" << CurrentFnName << "\n"
444 << "\t.type\t" << CurrentFnName << ", @function\n";
445 break;
446 case Function::WeakAnyLinkage:
447 case Function::WeakODRLinkage:
448 case Function::LinkOnceAnyLinkage:
449 case Function::LinkOnceODRLinkage:
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 EmitBasicBlockStart(I);
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 DW = getAnalysisIfAvailable<DwarfWriter>();
490 return Result;
494 Emit a global variable according to its section, alignment, etc.
496 \note This code was shamelessly copied from the PowerPC's assembly printer,
497 which sort of screams for some kind of refactorization of common code.
499 void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
500 const TargetData *TD = TM.getTargetData();
502 if (!GVar->hasInitializer())
503 return;
505 // Check to see if this is a special global used by LLVM, if so, emit it.
506 if (EmitSpecialLLVMGlobal(GVar))
507 return;
509 std::string name = Mang->getMangledName(GVar);
511 printVisibility(name, GVar->getVisibility());
513 Constant *C = GVar->getInitializer();
514 const Type *Type = C->getType();
515 unsigned Size = TD->getTypeAllocSize(Type);
516 unsigned Align = TD->getPreferredAlignmentLog(GVar);
518 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
519 TM));
521 if (C->isNullValue() && /* FIXME: Verify correct */
522 !GVar->hasSection() &&
523 (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
524 GVar->isWeakForLinker())) {
525 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
527 if (GVar->hasExternalLinkage()) {
528 O << "\t.global " << name << '\n';
529 O << "\t.type " << name << ", @object\n";
530 O << name << ":\n";
531 O << "\t.zero " << Size << '\n';
532 } else if (GVar->hasLocalLinkage()) {
533 O << MAI->getLCOMMDirective() << name << ',' << Size;
534 } else {
535 O << ".comm " << name << ',' << Size;
537 O << "\t\t" << MAI->getCommentString() << " '";
538 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
539 O << "'\n";
540 return;
543 switch (GVar->getLinkage()) {
544 // Should never be seen for the CellSPU platform...
545 case GlobalValue::LinkOnceAnyLinkage:
546 case GlobalValue::LinkOnceODRLinkage:
547 case GlobalValue::WeakAnyLinkage:
548 case GlobalValue::WeakODRLinkage:
549 case GlobalValue::CommonLinkage:
550 O << "\t.global " << name << '\n'
551 << "\t.type " << name << ", @object\n"
552 << "\t.weak " << name << '\n';
553 break;
554 case GlobalValue::AppendingLinkage:
555 // FIXME: appending linkage variables should go into a section of
556 // their name or something. For now, just emit them as external.
557 case GlobalValue::ExternalLinkage:
558 // If external or appending, declare as a global symbol
559 O << "\t.global " << name << '\n'
560 << "\t.type " << name << ", @object\n";
561 // FALL THROUGH
562 case GlobalValue::PrivateLinkage:
563 case GlobalValue::LinkerPrivateLinkage:
564 case GlobalValue::InternalLinkage:
565 break;
566 default:
567 llvm_report_error("Unknown linkage type!");
570 EmitAlignment(Align, GVar);
571 O << name << ":\t\t\t\t" << MAI->getCommentString() << " '";
572 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
573 O << "'\n";
575 EmitGlobalConstant(C);
576 O << '\n';
579 // Force static initialization.
580 extern "C" void LLVMInitializeCellSPUAsmPrinter() {
581 RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);