X86AsmPrinter.cpp revision 3c992d291bc67d9ce9d742d586d24ade9a577c99
1//===-- X86AsmPrinter.cpp - Convert X86 LLVM IR to X86 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 the shared super class printer that converts from our internal
11// representation of machine-dependent LLVM code to Intel and AT&T format
12// assembly language.
13// This printer is the output mechanism used by `llc'.
14//
15//===----------------------------------------------------------------------===//
16
17#include "X86ATTAsmPrinter.h"
18#include "X86IntelAsmPrinter.h"
19#include "X86Subtarget.h"
20#include "X86.h"
21#include "llvm/Constants.h"
22#include "llvm/Module.h"
23#include "llvm/Type.h"
24#include "llvm/Assembly/Writer.h"
25#include "llvm/Support/Mangler.h"
26#include "llvm/Support/CommandLine.h"
27using namespace llvm;
28using namespace x86;
29
30Statistic<> llvm::x86::EmittedInsts("asm-printer",
31                                    "Number of machine instrs printed");
32
33enum AsmWriterFlavorTy { att, intel };
34cl::opt<AsmWriterFlavorTy>
35AsmWriterFlavor("x86-asm-syntax",
36                cl::desc("Choose style of code to emit from X86 backend:"),
37                cl::values(
38                           clEnumVal(att,   "  Emit AT&T-style assembly"),
39                           clEnumVal(intel, "  Emit Intel-style assembly"),
40                           clEnumValEnd),
41                cl::init(att));
42
43/// doInitialization
44bool X86SharedAsmPrinter::doInitialization(Module &M) {
45  const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
46
47  forDarwin = false;
48  PrivateGlobalPrefix = ".L";
49
50  switch (Subtarget->TargetType) {
51  case X86Subtarget::isDarwin:
52    AlignmentIsInBytes = false;
53    GlobalPrefix = "_";
54    Data64bitsDirective = 0;       // we can't emit a 64-bit unit
55    ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
56    PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
57    ConstantPoolSection = "\t.const\n";
58    LCOMMDirective = "\t.lcomm\t";
59    COMMDirectiveTakesAlignment = false;
60    HasDotTypeDotSizeDirective = false;
61    forDarwin = true;
62    StaticCtorsSection = ".mod_init_func";
63    StaticDtorsSection = ".mod_term_func";
64    InlineAsmStart = InlineAsmEnd = "";  // Don't use #APP/#NO_APP
65    break;
66  case X86Subtarget::isCygwin:
67    GlobalPrefix = "_";
68    COMMDirectiveTakesAlignment = false;
69    HasDotTypeDotSizeDirective = false;
70    break;
71  case X86Subtarget::isWindows:
72    GlobalPrefix = "_";
73    HasDotTypeDotSizeDirective = false;
74    break;
75  default: break;
76  }
77
78  // Emit initial debug information.
79  DW.BeginModule(M);
80
81  return AsmPrinter::doInitialization(M);
82}
83
84bool X86SharedAsmPrinter::doFinalization(Module &M) {
85  const TargetData &TD = TM.getTargetData();
86
87  // Print out module-level global variables here.
88  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
89       I != E; ++I) {
90    if (!I->hasInitializer()) continue;   // External global require no code
91
92    // Check to see if this is a special global used by LLVM, if so, emit it.
93    if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I))
94      continue;
95
96    std::string name = Mang->getValueName(I);
97    Constant *C = I->getInitializer();
98    unsigned Size = TD.getTypeSize(C->getType());
99    unsigned Align = getPreferredAlignmentLog(I);
100
101    if (C->isNullValue() && /* FIXME: Verify correct */
102        (I->hasInternalLinkage() || I->hasWeakLinkage() ||
103         I->hasLinkOnceLinkage() ||
104         (forDarwin && I->hasExternalLinkage() && !I->hasSection()))) {
105      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
106      if (I->hasExternalLinkage()) {
107          O << "\t.globl\t" << name << "\n";
108          O << "\t.zerofill __DATA__, __common, " << name << ", "
109            << Size << ", " << Align;
110      } else {
111        SwitchSection(".data", I);
112        if (LCOMMDirective != NULL) {
113          if (I->hasInternalLinkage()) {
114            O << LCOMMDirective << name << "," << Size;
115            if (forDarwin)
116              O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
117          } else
118            O << COMMDirective  << name << "," << Size;
119        } else {
120          if (I->hasInternalLinkage())
121            O << "\t.local\t" << name << "\n";
122          O << COMMDirective  << name << "," << Size;
123          if (COMMDirectiveTakesAlignment)
124            O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
125        }
126      }
127      O << "\t\t" << CommentString << " " << I->getName() << "\n";
128    } else {
129      switch (I->getLinkage()) {
130      case GlobalValue::LinkOnceLinkage:
131      case GlobalValue::WeakLinkage:
132        if (forDarwin) {
133          O << "\t.globl " << name << "\n"
134            << "\t.weak_definition " << name << "\n";
135          SwitchSection(".section __DATA,__datacoal_nt,coalesced", I);
136        } else {
137          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
138          O << "\t.weak " << name << "\n";
139        }
140        break;
141      case GlobalValue::AppendingLinkage:
142        // FIXME: appending linkage variables should go into a section of
143        // their name or something.  For now, just emit them as external.
144      case GlobalValue::ExternalLinkage:
145        // If external or appending, declare as a global symbol
146        O << "\t.globl " << name << "\n";
147        // FALL THROUGH
148      case GlobalValue::InternalLinkage:
149        SwitchSection(".data", I);
150        break;
151      default:
152        assert(0 && "Unknown linkage type!");
153      }
154
155      EmitAlignment(Align, I);
156      O << name << ":\t\t\t\t" << CommentString << " " << I->getName()
157        << "\n";
158      if (HasDotTypeDotSizeDirective)
159        O << "\t.size " << name << ", " << Size << "\n";
160
161      EmitGlobalConstant(C);
162      O << '\n';
163    }
164  }
165
166  if (forDarwin) {
167    SwitchSection("", 0);
168
169    // Output stubs for dynamically-linked functions
170    unsigned j = 1;
171    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
172         i != e; ++i, ++j) {
173      SwitchSection(".section __IMPORT,__jump_table,symbol_stubs,"
174                    "self_modifying_code+pure_instructions,5", 0);
175      O << "L" << *i << "$stub:\n";
176      O << "\t.indirect_symbol " << *i << "\n";
177      O << "\thlt ; hlt ; hlt ; hlt ; hlt\n";
178    }
179
180    O << "\n";
181
182    // Output stubs for external and common global variables.
183    if (GVStubs.begin() != GVStubs.end())
184      SwitchSection(".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0);
185    for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
186         i != e; ++i) {
187      O << "L" << *i << "$non_lazy_ptr:\n";
188      O << "\t.indirect_symbol " << *i << "\n";
189      O << "\t.long\t0\n";
190    }
191  }
192
193  // Emit initial debug information.
194  DW.EndModule(M);
195
196  AsmPrinter::doFinalization(M);
197  return false; // success
198}
199
200/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
201/// for a MachineFunction to the given output stream, using the given target
202/// machine description.
203///
204FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
205  switch (AsmWriterFlavor) {
206  default:
207    assert(0 && "Unknown asm flavor!");
208  case intel:
209    return new X86IntelAsmPrinter(o, tm);
210  case att:
211    return new X86ATTAsmPrinter(o, tm);
212  }
213}
214