PPCAsmPrinter.cpp revision 0561b3ff9fd08f9cda48551f2f91590ca5f60656
1//===-- PowerPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source 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 PowerPC assembly language. This printer is
12// the output mechanism used by `llc'.
13//
14// Documentation at http://developer.apple.com/documentation/DeveloperTools/
15// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
16//
17//===----------------------------------------------------------------------===//
18
19#define DEBUG_TYPE "asmprinter"
20#include "PowerPC.h"
21#include "PowerPCTargetMachine.h"
22#include "llvm/Constants.h"
23#include "llvm/DerivedTypes.h"
24#include "llvm/Module.h"
25#include "llvm/Assembly/Writer.h"
26#include "llvm/CodeGen/AsmPrinter.h"
27#include "llvm/CodeGen/MachineConstantPool.h"
28#include "llvm/CodeGen/MachineFunctionPass.h"
29#include "llvm/CodeGen/MachineInstr.h"
30#include "llvm/CodeGen/ValueTypes.h"
31#include "llvm/Support/Mangler.h"
32#include "llvm/Support/MathExtras.h"
33#include "llvm/Support/CommandLine.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Target/MRegisterInfo.h"
36#include "llvm/Target/TargetInstrInfo.h"
37#include "llvm/ADT/Statistic.h"
38#include "llvm/ADT/StringExtras.h"
39#include <set>
40using namespace llvm;
41
42namespace {
43  Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
44
45  struct PowerPCAsmPrinter : public AsmPrinter {
46    std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
47
48    PowerPCAsmPrinter(std::ostream &O, TargetMachine &TM)
49      : AsmPrinter(O, TM), LabelNumber(0) {}
50
51    /// Unique incrementer for label values for referencing Global values.
52    ///
53    unsigned LabelNumber;
54
55    virtual const char *getPassName() const {
56      return "PowerPC Assembly Printer";
57    }
58
59    PowerPCTargetMachine &getTM() {
60      return static_cast<PowerPCTargetMachine&>(TM);
61    }
62
63    unsigned enumRegToMachineReg(unsigned enumReg) {
64      switch (enumReg) {
65      default: assert(0 && "Unhandled register!"); break;
66      case PPC::CR0:  return  0;
67      case PPC::CR1:  return  1;
68      case PPC::CR2:  return  2;
69      case PPC::CR3:  return  3;
70      case PPC::CR4:  return  4;
71      case PPC::CR5:  return  5;
72      case PPC::CR6:  return  6;
73      case PPC::CR7:  return  7;
74      }
75      abort();
76    }
77
78    /// printInstruction - This method is automatically generated by tablegen
79    /// from the instruction set description.  This method returns true if the
80    /// machine instruction was sufficiently described to print it, otherwise it
81    /// returns false.
82    bool printInstruction(const MachineInstr *MI);
83
84    void printMachineInstruction(const MachineInstr *MI);
85    void printOp(const MachineOperand &MO, bool IsCallOp = false);
86
87    void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
88      const MachineOperand &MO = MI->getOperand(OpNo);
89      if (MO.getType() == MachineOperand::MO_MachineRegister) {
90        assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
91        O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name);
92      } else if (MO.isImmediate()) {
93        O << MO.getImmedValue();
94      } else {
95        printOp(MO);
96      }
97    }
98
99    void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo,
100                            MVT::ValueType VT) {
101      unsigned char value = MI->getOperand(OpNo).getImmedValue();
102      assert(value <= 31 && "Invalid u5imm argument!");
103      O << (unsigned int)value;
104    }
105    void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo,
106                            MVT::ValueType VT) {
107      unsigned char value = MI->getOperand(OpNo).getImmedValue();
108      assert(value <= 63 && "Invalid u6imm argument!");
109      O << (unsigned int)value;
110    }
111    void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo,
112                            MVT::ValueType VT) {
113      O << (short)MI->getOperand(OpNo).getImmedValue();
114    }
115    void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
116                            MVT::ValueType VT) {
117      O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
118    }
119    void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
120                            MVT::ValueType VT) {
121      // Branches can take an immediate operand.  This is used by the branch
122      // selection pass to print $+8, an eight byte displacement from the PC.
123      if (MI->getOperand(OpNo).isImmediate()) {
124        O << "$+" << MI->getOperand(OpNo).getImmedValue();
125      } else {
126        printOp(MI->getOperand(OpNo),
127                TM.getInstrInfo()->isCall(MI->getOpcode()));
128      }
129    }
130    void printPICLabel(const MachineInstr *MI, unsigned OpNo,
131                       MVT::ValueType VT) {
132      // FIXME: should probably be converted to cout.width and cout.fill
133      O << "\"L0000" << LabelNumber << "$pb\"\n";
134      O << "\"L0000" << LabelNumber << "$pb\":";
135    }
136    void printSymbolHi(const MachineInstr *MI, unsigned OpNo,
137                       MVT::ValueType VT) {
138      if (MI->getOperand(OpNo).isImmediate()) {
139        printS16ImmOperand(MI, OpNo, VT);
140      } else {
141        O << "ha16(";
142        printOp(MI->getOperand(OpNo));
143        if (PICEnabled)
144          O << "-\"L0000" << LabelNumber << "$pb\")";
145        else
146          O << ')';
147      }
148    }
149    void printSymbolLo(const MachineInstr *MI, unsigned OpNo,
150                       MVT::ValueType VT) {
151      if (MI->getOperand(OpNo).isImmediate()) {
152        printS16ImmOperand(MI, OpNo, VT);
153      } else {
154        O << "lo16(";
155        printOp(MI->getOperand(OpNo));
156        if (PICEnabled)
157          O << "-\"L0000" << LabelNumber << "$pb\")";
158        else
159          O << ')';
160      }
161    }
162    void printcrbit(const MachineInstr *MI, unsigned OpNo,
163                       MVT::ValueType VT) {
164      unsigned char value = MI->getOperand(OpNo).getImmedValue();
165      assert(value <= 3 && "Invalid crbit argument!");
166      unsigned CCReg = MI->getOperand(OpNo-1).getReg();
167      unsigned RegNo = enumRegToMachineReg(CCReg);
168      O << 4 * RegNo + value;
169    }
170    void printcrbitm(const MachineInstr *MI, unsigned OpNo,
171                       MVT::ValueType VT) {
172      unsigned CCReg = MI->getOperand(OpNo).getReg();
173      unsigned RegNo = enumRegToMachineReg(CCReg);
174      O << (0x80 >> RegNo);
175    }
176
177    virtual void printConstantPool(MachineConstantPool *MCP) = 0;
178    virtual bool runOnMachineFunction(MachineFunction &F) = 0;
179    virtual bool doFinalization(Module &M) = 0;
180  };
181
182  /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS
183  /// X
184  ///
185  struct DarwinAsmPrinter : public PowerPCAsmPrinter {
186
187    DarwinAsmPrinter(std::ostream &O, TargetMachine &TM)
188      : PowerPCAsmPrinter(O, TM) {
189      CommentString = ";";
190      GlobalPrefix = "_";
191      ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
192      Data64bitsDirective = 0;       // we can't emit a 64-bit unit
193      AlignmentIsInBytes = false;    // Alignment is by power of 2.
194    }
195
196    virtual const char *getPassName() const {
197      return "Darwin PPC Assembly Printer";
198    }
199
200    void printConstantPool(MachineConstantPool *MCP);
201    bool runOnMachineFunction(MachineFunction &F);
202    bool doInitialization(Module &M);
203    bool doFinalization(Module &M);
204  };
205
206  /// AIXAsmPrinter - PowerPC assembly printer, customized for AIX
207  ///
208  struct AIXAsmPrinter : public PowerPCAsmPrinter {
209    /// Map for labels corresponding to global variables
210    ///
211    std::map<const GlobalVariable*,std::string> GVToLabelMap;
212
213    AIXAsmPrinter(std::ostream &O, TargetMachine &TM)
214      : PowerPCAsmPrinter(O, TM) {
215      CommentString = "#";
216      GlobalPrefix = "_";
217      ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
218      Data64bitsDirective = 0;       // we can't emit a 64-bit unit
219      AlignmentIsInBytes = false;    // Alignment is by power of 2.
220    }
221
222    virtual const char *getPassName() const {
223      return "AIX PPC Assembly Printer";
224    }
225
226    void printConstantPool(MachineConstantPool *MCP);
227    bool runOnMachineFunction(MachineFunction &F);
228    bool doInitialization(Module &M);
229    bool doFinalization(Module &M);
230  };
231} // end of anonymous namespace
232
233// SwitchSection - Switch to the specified section of the executable if we are
234// not already in it!
235//
236static void SwitchSection(std::ostream &OS, std::string &CurSection,
237                          const char *NewSection) {
238  if (CurSection != NewSection) {
239    CurSection = NewSection;
240    if (!CurSection.empty())
241      OS << "\t" << NewSection << "\n";
242  }
243}
244
245/// createDarwinAsmPrinterPass - Returns a pass that prints the PPC assembly
246/// code for a MachineFunction to the given output stream, in a format that the
247/// Darwin assembler can deal with.
248///
249FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
250  return new DarwinAsmPrinter(o, tm);
251}
252
253/// createAIXAsmPrinterPass - Returns a pass that prints the PPC assembly code
254/// for a MachineFunction to the given output stream, in a format that the
255/// AIX 5L assembler can deal with.
256///
257FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
258  return new AIXAsmPrinter(o, tm);
259}
260
261// Include the auto-generated portion of the assembly writer
262#include "PowerPCGenAsmWriter.inc"
263
264void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
265  const MRegisterInfo &RI = *TM.getRegisterInfo();
266  int new_symbol;
267
268  switch (MO.getType()) {
269  case MachineOperand::MO_VirtualRegister:
270    if (Value *V = MO.getVRegValueOrNull()) {
271      O << "<" << V->getName() << ">";
272      return;
273    }
274    // FALLTHROUGH
275  case MachineOperand::MO_MachineRegister:
276  case MachineOperand::MO_CCRegister:
277    O << LowercaseString(RI.get(MO.getReg()).Name);
278    return;
279
280  case MachineOperand::MO_SignExtendedImmed:
281  case MachineOperand::MO_UnextendedImmed:
282    std::cerr << "printOp() does not handle immediate values\n";
283    abort();
284    return;
285
286  case MachineOperand::MO_PCRelativeDisp:
287    std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
288    abort();
289    return;
290
291  case MachineOperand::MO_MachineBasicBlock: {
292    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
293    O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
294      << "_" << MBBOp->getNumber() << "\t; "
295      << MBBOp->getBasicBlock()->getName();
296    return;
297  }
298
299  case MachineOperand::MO_ConstantPoolIndex:
300    O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
301    return;
302
303  case MachineOperand::MO_ExternalSymbol:
304    if (IsCallOp) {
305      std::string Name(GlobalPrefix); Name += MO.getSymbolName();
306      FnStubs.insert(Name);
307      O << "L" << Name << "$stub";
308      return;
309    }
310    O << GlobalPrefix << MO.getSymbolName();
311    return;
312
313  case MachineOperand::MO_GlobalAddress: {
314    GlobalValue *GV = MO.getGlobal();
315    std::string Name = Mang->getValueName(GV);
316
317    // Dynamically-resolved functions need a stub for the function.  Be
318    // wary however not to output $stub for external functions whose addresses
319    // are taken.  Those should be emitted as $non_lazy_ptr below.
320    Function *F = dyn_cast<Function>(GV);
321    if (F && IsCallOp && F->isExternal()) {
322      FnStubs.insert(Name);
323      O << "L" << Name << "$stub";
324      return;
325    }
326
327    // External or weakly linked global variables need non-lazily-resolved stubs
328    if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())){
329      if (GV->hasLinkOnceLinkage())
330        LinkOnceStubs.insert(Name);
331      else
332        GVStubs.insert(Name);
333      O << "L" << Name << "$non_lazy_ptr";
334      return;
335    }
336
337    O << Mang->getValueName(GV);
338    return;
339  }
340
341  default:
342    O << "<unknown operand type: " << MO.getType() << ">";
343    return;
344  }
345}
346
347/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
348/// the current output stream.
349///
350void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
351  ++EmittedInsts;
352  // Check for slwi/srwi mnemonics.
353  if (MI->getOpcode() == PPC::RLWINM) {
354    bool FoundMnemonic = false;
355    unsigned char SH = MI->getOperand(2).getImmedValue();
356    unsigned char MB = MI->getOperand(3).getImmedValue();
357    unsigned char ME = MI->getOperand(4).getImmedValue();
358    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
359      O << "slwi "; FoundMnemonic = true;
360    }
361    if (SH <= 31 && MB == (32-SH) && ME == 31) {
362      O << "srwi "; FoundMnemonic = true;
363      SH = 32-SH;
364    }
365    if (FoundMnemonic) {
366      printOperand(MI, 0, MVT::i64);
367      O << ", ";
368      printOperand(MI, 1, MVT::i64);
369      O << ", " << (unsigned int)SH << "\n";
370      return;
371    }
372  }
373
374  if (printInstruction(MI))
375    return; // Printer was automatically generated
376
377  assert(0 && "Unhandled instruction in asm writer!");
378  abort();
379  return;
380}
381
382/// runOnMachineFunction - This uses the printMachineInstruction()
383/// method to print assembly for each instruction.
384///
385bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
386  setupMachineFunction(MF);
387  O << "\n\n";
388
389  // Print out constants referenced by the function
390  printConstantPool(MF.getConstantPool());
391
392  // Print out labels for the function.
393  O << "\t.text\n";
394  emitAlignment(2);
395  O << "\t.globl\t" << CurrentFnName << "\n";
396  O << CurrentFnName << ":\n";
397
398  // Print out code for the function.
399  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
400       I != E; ++I) {
401    // Print a label for the basic block.
402    O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
403      << CommentString << " " << I->getBasicBlock()->getName() << "\n";
404    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
405         II != E; ++II) {
406      // Print the assembly for the instruction.
407      O << "\t";
408      printMachineInstruction(II);
409    }
410  }
411  ++LabelNumber;
412
413  // We didn't modify anything.
414  return false;
415}
416
417/// printConstantPool - Print to the current output stream assembly
418/// representations of the constants in the constant pool MCP. This is
419/// used to print out constants which have been "spilled to memory" by
420/// the code generator.
421///
422void DarwinAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
423  const std::vector<Constant*> &CP = MCP->getConstants();
424  const TargetData &TD = TM.getTargetData();
425
426  if (CP.empty()) return;
427
428  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
429    O << "\t.const\n";
430    emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
431    O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
432      << *CP[i] << "\n";
433    emitGlobalConstant(CP[i]);
434  }
435}
436
437bool DarwinAsmPrinter::doInitialization(Module &M) {
438  if (GPOPT) O << "\t.machine ppc970\n";
439  AsmPrinter::doInitialization(M);
440  return false;
441}
442
443bool DarwinAsmPrinter::doFinalization(Module &M) {
444  const TargetData &TD = TM.getTargetData();
445  std::string CurSection;
446
447  // Print out module-level global variables here.
448  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
449    if (I->hasInitializer()) {   // External global require no code
450      O << '\n';
451      std::string name = Mang->getValueName(I);
452      Constant *C = I->getInitializer();
453      unsigned Size = TD.getTypeSize(C->getType());
454      unsigned Align = TD.getTypeAlignmentShift(C->getType());
455
456      if (C->isNullValue() && /* FIXME: Verify correct */
457          (I->hasInternalLinkage() || I->hasWeakLinkage() ||
458           I->hasLinkOnceLinkage())) {
459        SwitchSection(O, CurSection, ".data");
460        if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
461        if (I->hasInternalLinkage())
462          O << ".lcomm " << name << "," << Size << "," << Align;
463        else
464          O << ".comm " << name << "," << Size;
465        O << "\t\t; ";
466        WriteAsOperand(O, I, true, true, &M);
467        O << '\n';
468      } else {
469        switch (I->getLinkage()) {
470        case GlobalValue::LinkOnceLinkage:
471          O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n"
472            << ".weak_definition " << name << '\n'
473            << ".private_extern " << name << '\n'
474            << ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
475          LinkOnceStubs.insert(name);
476          break;
477        case GlobalValue::WeakLinkage:
478          O << ".weak_definition " << name << '\n'
479            << ".private_extern " << name << '\n';
480          break;
481        case GlobalValue::AppendingLinkage:
482          // FIXME: appending linkage variables should go into a section of
483          // their name or something.  For now, just emit them as external.
484        case GlobalValue::ExternalLinkage:
485          // If external or appending, declare as a global symbol
486          O << "\t.globl " << name << "\n";
487          // FALL THROUGH
488        case GlobalValue::InternalLinkage:
489          SwitchSection(O, CurSection, ".data");
490          break;
491        case GlobalValue::GhostLinkage:
492          std::cerr << "Error: unmaterialized (GhostLinkage) function in asm!";
493          abort();
494        }
495
496        emitAlignment(Align);
497        O << name << ":\t\t\t\t; ";
498        WriteAsOperand(O, I, true, true, &M);
499        O << " = ";
500        WriteAsOperand(O, C, false, false, &M);
501        O << "\n";
502        emitGlobalConstant(C);
503      }
504    }
505
506  // Output stubs for dynamically-linked functions
507  for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
508       i != e; ++i)
509  {
510    if (PICEnabled) {
511    O << ".data\n";
512    O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
513    emitAlignment(2);
514    O << "L" << *i << "$stub:\n";
515    O << "\t.indirect_symbol " << *i << "\n";
516    O << "\tmflr r0\n";
517    O << "\tbcl 20,31,L0$" << *i << "\n";
518    O << "L0$" << *i << ":\n";
519    O << "\tmflr r11\n";
520    O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
521    O << "\tmtlr r0\n";
522    O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
523    O << "\tmtctr r12\n";
524    O << "\tbctr\n";
525    O << ".data\n";
526    O << ".lazy_symbol_pointer\n";
527    O << "L" << *i << "$lazy_ptr:\n";
528    O << "\t.indirect_symbol " << *i << "\n";
529    O << "\t.long dyld_stub_binding_helper\n";
530    } else {
531    O << "\t.section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16\n";
532    emitAlignment(4);
533    O << "L" << *i << "$stub:\n";
534    O << "\t.indirect_symbol " << *i << "\n";
535    O << "\tlis r11,ha16(L" << *i << "$lazy_ptr)\n";
536    O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr)(r11)\n";
537    O << "\tmtctr r12\n";
538    O << "\tbctr\n";
539    O << "\t.lazy_symbol_pointer\n";
540    O << "L" << *i << "$lazy_ptr:\n";
541    O << "\t.indirect_symbol " << *i << "\n";
542    O << "\t.long dyld_stub_binding_helper\n";
543    }
544  }
545
546  O << "\n";
547
548  // Output stubs for external global variables
549  if (GVStubs.begin() != GVStubs.end())
550    O << ".data\n.non_lazy_symbol_pointer\n";
551  for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
552       i != e; ++i) {
553    O << "L" << *i << "$non_lazy_ptr:\n";
554    O << "\t.indirect_symbol " << *i << "\n";
555    O << "\t.long\t0\n";
556  }
557
558  // Output stubs for link-once variables
559  if (LinkOnceStubs.begin() != LinkOnceStubs.end())
560    O << ".data\n.align 2\n";
561  for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
562         e = LinkOnceStubs.end(); i != e; ++i) {
563    O << "L" << *i << "$non_lazy_ptr:\n"
564      << "\t.long\t" << *i << '\n';
565  }
566
567  AsmPrinter::doFinalization(M);
568  return false; // success
569}
570
571/// runOnMachineFunction - This uses the printMachineInstruction()
572/// method to print assembly for each instruction.
573///
574bool AIXAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
575  CurrentFnName = MF.getFunction()->getName();
576
577  // Print out constants referenced by the function
578  printConstantPool(MF.getConstantPool());
579
580  // Print out header for the function.
581  O << "\t.csect .text[PR]\n"
582    << "\t.align 2\n"
583    << "\t.globl "  << CurrentFnName << '\n'
584    << "\t.globl ." << CurrentFnName << '\n'
585    << "\t.csect "  << CurrentFnName << "[DS],3\n"
586    << CurrentFnName << ":\n"
587    << "\t.llong ." << CurrentFnName << ", TOC[tc0], 0\n"
588    << "\t.csect .text[PR]\n"
589    << '.' << CurrentFnName << ":\n";
590
591  // Print out code for the function.
592  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
593       I != E; ++I) {
594    // Print a label for the basic block.
595    O << "LBB" << CurrentFnName << "_" << I->getNumber() << ":\t# "
596      << I->getBasicBlock()->getName() << "\n";
597    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
598      II != E; ++II) {
599      // Print the assembly for the instruction.
600      O << "\t";
601      printMachineInstruction(II);
602    }
603  }
604  ++LabelNumber;
605
606  O << "LT.." << CurrentFnName << ":\n"
607    << "\t.long 0\n"
608    << "\t.byte 0,0,32,65,128,0,0,0\n"
609    << "\t.long LT.." << CurrentFnName << "-." << CurrentFnName << '\n'
610    << "\t.short 3\n"
611    << "\t.byte \"" << CurrentFnName << "\"\n"
612    << "\t.align 2\n";
613
614  // We didn't modify anything.
615  return false;
616}
617
618/// printConstantPool - Print to the current output stream assembly
619/// representations of the constants in the constant pool MCP. This is
620/// used to print out constants which have been "spilled to memory" by
621/// the code generator.
622///
623void AIXAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
624  const std::vector<Constant*> &CP = MCP->getConstants();
625  const TargetData &TD = TM.getTargetData();
626
627  if (CP.empty()) return;
628
629  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
630    O << "\t.const\n";
631    O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
632      << "\n";
633    O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;"
634      << *CP[i] << "\n";
635    emitGlobalConstant(CP[i]);
636  }
637}
638
639bool AIXAsmPrinter::doInitialization(Module &M) {
640  const TargetData &TD = TM.getTargetData();
641  std::string CurSection;
642
643  O << "\t.machine \"ppc64\"\n"
644    << "\t.toc\n"
645    << "\t.csect .text[PR]\n";
646
647  // Print out module-level global variables
648  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
649       I != E; ++I) {
650    if (!I->hasInitializer())
651      continue;
652
653    std::string Name = I->getName();
654    Constant *C = I->getInitializer();
655    // N.B.: We are defaulting to writable strings
656    if (I->hasExternalLinkage()) {
657      O << "\t.globl " << Name << '\n'
658        << "\t.csect .data[RW],3\n";
659    } else {
660      O << "\t.csect _global.rw_c[RW],3\n";
661    }
662    O << Name << ":\n";
663    emitGlobalConstant(C);
664  }
665
666  // Output labels for globals
667  if (M.global_begin() != M.global_end()) O << "\t.toc\n";
668  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
669       I != E; ++I) {
670    const GlobalVariable *GV = I;
671    // Do not output labels for unused variables
672    if (GV->isExternal() && GV->use_begin() == GV->use_end())
673      continue;
674
675    std::string Name = GV->getName();
676    std::string Label = "LC.." + utostr(LabelNumber++);
677    GVToLabelMap[GV] = Label;
678    O << Label << ":\n"
679      << "\t.tc " << Name << "[TC]," << Name;
680    if (GV->isExternal()) O << "[RW]";
681    O << '\n';
682  }
683
684  Mang = new Mangler(M, ".");
685  return false; // success
686}
687
688bool AIXAsmPrinter::doFinalization(Module &M) {
689  const TargetData &TD = TM.getTargetData();
690  // Print out module-level global variables
691  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
692       I != E; ++I) {
693    if (I->hasInitializer() || I->hasExternalLinkage())
694      continue;
695
696    std::string Name = I->getName();
697    if (I->hasInternalLinkage()) {
698      O << "\t.lcomm " << Name << ",16,_global.bss_c";
699    } else {
700      O << "\t.comm " << Name << "," << TD.getTypeSize(I->getType())
701        << "," << Log2_32((unsigned)TD.getTypeAlignment(I->getType()));
702    }
703    O << "\t\t# ";
704    WriteAsOperand(O, I, true, true, &M);
705    O << "\n";
706  }
707
708  O << "_section_.text:\n"
709    << "\t.csect .data[RW],3\n"
710    << "\t.llong _section_.text\n";
711
712  delete Mang;
713  return false; // success
714}
715