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