X86AsmPrinter.cpp revision 07103d312aa1d20f1c9bbc40cbdafe1e312c4a3d
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 "X86AsmPrinter.h"
18#include "X86ATTAsmPrinter.h"
19#include "X86IntelAsmPrinter.h"
20#include "X86Subtarget.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;
28
29Statistic<> llvm::EmittedInsts("asm-printer",
30                               "Number of machine instrs printed");
31
32enum AsmWriterFlavorTy { att, intel };
33cl::opt<AsmWriterFlavorTy>
34AsmWriterFlavor("x86-asm-syntax",
35                cl::desc("Choose style of code to emit from X86 backend:"),
36                cl::values(
37                           clEnumVal(att,   "  Emit AT&T-style assembly"),
38                           clEnumVal(intel, "  Emit Intel-style assembly"),
39                           clEnumValEnd),
40#ifdef _MSC_VER
41                cl::init(intel)
42#else
43                cl::init(att)
44#endif
45                );
46
47/// doInitialization
48bool X86SharedAsmPrinter::doInitialization(Module &M) {
49  PrivateGlobalPrefix = ".L";
50  DefaultTextSection = ".text";
51  DefaultDataSection = ".data";
52
53  switch (Subtarget->TargetType) {
54  case X86Subtarget::isDarwin:
55    AlignmentIsInBytes = false;
56    GlobalPrefix = "_";
57    Data64bitsDirective = 0;       // we can't emit a 64-bit unit
58    ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
59    PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
60    ConstantPoolSection = "\t.const\n";
61    JumpTableSection = "\t.const\n"; // FIXME: depends on PIC mode
62    LCOMMDirective = "\t.lcomm\t";
63    COMMDirectiveTakesAlignment = false;
64    HasDotTypeDotSizeDirective = false;
65    StaticCtorsSection = ".mod_init_func";
66    StaticDtorsSection = ".mod_term_func";
67    InlineAsmStart = "# InlineAsm Start";
68    InlineAsmEnd = "# InlineAsm End";
69    break;
70  case X86Subtarget::isCygwin:
71    GlobalPrefix = "_";
72    COMMDirectiveTakesAlignment = false;
73    HasDotTypeDotSizeDirective = false;
74    StaticCtorsSection = "\t.section .ctors,\"aw\"";
75    StaticDtorsSection = "\t.section .dtors,\"aw\"";
76    break;
77  case X86Subtarget::isWindows:
78    GlobalPrefix = "_";
79    HasDotTypeDotSizeDirective = false;
80    break;
81  default: break;
82  }
83
84  if (Subtarget->TargetType == X86Subtarget::isDarwin) {
85    // Emit initial debug information.
86    DW.BeginModule(&M);
87  }
88
89  return AsmPrinter::doInitialization(M);
90}
91
92bool X86SharedAsmPrinter::doFinalization(Module &M) {
93  // Note: this code is not shared by the Intel printer as it is too different
94  // from how MASM does things.  When making changes here don't forget to look
95  // at X86IntelAsmPrinter::doFinalization().
96  const TargetData *TD = TM.getTargetData();
97
98  // Print out module-level global variables here.
99  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
100       I != E; ++I) {
101    if (!I->hasInitializer()) continue;   // External global require no code
102
103    // Check to see if this is a special global used by LLVM, if so, emit it.
104    if (EmitSpecialLLVMGlobal(I))
105      continue;
106
107    std::string name = Mang->getValueName(I);
108    Constant *C = I->getInitializer();
109    unsigned Size = TD->getTypeSize(C->getType());
110    unsigned Align = getPreferredAlignmentLog(I);
111
112    if (C->isNullValue() && /* FIXME: Verify correct */
113        (I->hasInternalLinkage() || I->hasWeakLinkage() ||
114         I->hasLinkOnceLinkage() ||
115         (Subtarget->TargetType == X86Subtarget::isDarwin &&
116          I->hasExternalLinkage() && !I->hasSection()))) {
117      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
118      if (I->hasExternalLinkage()) {
119          O << "\t.globl\t" << name << "\n";
120          O << "\t.zerofill __DATA__, __common, " << name << ", "
121            << Size << ", " << Align;
122      } else {
123        SwitchToDataSection(DefaultDataSection, I);
124        if (LCOMMDirective != NULL) {
125          if (I->hasInternalLinkage()) {
126            O << LCOMMDirective << name << "," << Size;
127            if (Subtarget->TargetType == X86Subtarget::isDarwin)
128              O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
129          } else
130            O << COMMDirective  << name << "," << Size;
131        } else {
132          if (Subtarget->TargetType != X86Subtarget::isCygwin) {
133            if (I->hasInternalLinkage())
134              O << "\t.local\t" << name << "\n";
135          }
136          O << COMMDirective  << name << "," << Size;
137          if (COMMDirectiveTakesAlignment)
138            O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
139        }
140      }
141      O << "\t\t" << CommentString << " " << I->getName() << "\n";
142    } else {
143      switch (I->getLinkage()) {
144      case GlobalValue::LinkOnceLinkage:
145      case GlobalValue::WeakLinkage:
146        if (Subtarget->TargetType == X86Subtarget::isDarwin) {
147          O << "\t.globl " << name << "\n"
148            << "\t.weak_definition " << name << "\n";
149          SwitchToDataSection(".section __DATA,__const_coal,coalesced", I);
150        } else if (Subtarget->TargetType == X86Subtarget::isCygwin) {
151          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\"\n"
152            << "\t.weak " << name << "\n";
153        } else {
154          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"
155            << "\t.weak " << name << "\n";
156        }
157        break;
158      case GlobalValue::AppendingLinkage:
159        // FIXME: appending linkage variables should go into a section of
160        // their name or something.  For now, just emit them as external.
161      case GlobalValue::ExternalLinkage:
162        // If external or appending, declare as a global symbol
163        O << "\t.globl " << name << "\n";
164        // FALL THROUGH
165      case GlobalValue::InternalLinkage:
166        SwitchToDataSection(DefaultDataSection, I);
167        break;
168      default:
169        assert(0 && "Unknown linkage type!");
170      }
171
172      EmitAlignment(Align, I);
173      O << name << ":\t\t\t\t" << CommentString << " " << I->getName()
174        << "\n";
175      if (HasDotTypeDotSizeDirective)
176        O << "\t.size " << name << ", " << Size << "\n";
177
178      EmitGlobalConstant(C);
179      O << '\n';
180    }
181  }
182
183  if (Subtarget->TargetType == X86Subtarget::isDarwin) {
184    SwitchToDataSection("", 0);
185
186    // Output stubs for dynamically-linked functions
187    unsigned j = 1;
188    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
189         i != e; ++i, ++j) {
190      SwitchToDataSection(".section __IMPORT,__jump_table,symbol_stubs,"
191                          "self_modifying_code+pure_instructions,5", 0);
192      O << "L" << *i << "$stub:\n";
193      O << "\t.indirect_symbol " << *i << "\n";
194      O << "\thlt ; hlt ; hlt ; hlt ; hlt\n";
195    }
196
197    O << "\n";
198
199    // Output stubs for external and common global variables.
200    if (GVStubs.begin() != GVStubs.end())
201      SwitchToDataSection(
202                    ".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0);
203    for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
204         i != e; ++i) {
205      O << "L" << *i << "$non_lazy_ptr:\n";
206      O << "\t.indirect_symbol " << *i << "\n";
207      O << "\t.long\t0\n";
208    }
209
210    // Emit initial debug information.
211    DW.EndModule();
212
213    // Funny Darwin hack: This flag tells the linker that no global symbols
214    // contain code that falls through to other global symbols (e.g. the obvious
215    // implementation of multiple entry points).  If this doesn't occur, the
216    // linker can safely perform dead code stripping.  Since LLVM never
217    // generates code that does this, it is always safe to set.
218    O << "\t.subsections_via_symbols\n";
219  }
220
221  AsmPrinter::doFinalization(M);
222  return false; // success
223}
224
225void X86SharedAsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
226  if (!Subtarget->TargetType == X86Subtarget::isDarwin) {
227    AsmPrinter::EmitConstantPool(MCP);
228    return;
229  }
230
231  const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
232  if (CP.empty()) return;
233
234  std::vector<MachineConstantPoolEntry> FloatCPs;
235  std::vector<MachineConstantPoolEntry> DoubleCPs;
236  std::vector<MachineConstantPoolEntry> OtherCPs;
237  //  const TargetData *TD = TM.getTargetData();
238  //  unsigned Align = MCP->getConstantPoolAlignment();
239  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
240    MachineConstantPoolEntry CPE = CP[i];
241    const Constant *CV = CPE.Val;
242    const Type *Ty = CV->getType();
243    if (Ty->getTypeID() == Type::FloatTyID)
244      FloatCPs.push_back(CPE);
245    else if (Ty->getTypeID() == Type::DoubleTyID)
246      DoubleCPs.push_back(CPE);
247    else
248      OtherCPs.push_back(CPE);
249  }
250  EmitConstantPool(MCP, FloatCPs,  "\t.literal4");
251  EmitConstantPool(MCP, DoubleCPs, "\t.literal8");
252  EmitConstantPool(MCP, OtherCPs,  ConstantPoolSection);
253}
254
255void
256X86SharedAsmPrinter::EmitConstantPool(MachineConstantPool *MCP,
257                                      std::vector<MachineConstantPoolEntry> &CP,
258                                      const char *Section) {
259  if (CP.empty()) return;
260
261  SwitchToDataSection(Section, 0);
262  EmitAlignment(MCP->getConstantPoolAlignment());
263  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
264    O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << '_' << i
265      << ":\t\t\t\t\t" << CommentString << " ";
266    WriteTypeSymbolic(O, CP[i].Val->getType(), 0) << '\n';
267    EmitGlobalConstant(CP[i].Val);
268    if (i != e-1) {
269      unsigned EntSize = TM.getTargetData()->getTypeSize(CP[i].Val->getType());
270      unsigned ValEnd = CP[i].Offset + EntSize;
271      // Emit inter-object padding for alignment.
272      EmitZeros(CP[i+1].Offset-ValEnd);
273    }
274  }
275}
276
277/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
278/// for a MachineFunction to the given output stream, using the given target
279/// machine description.
280///
281FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,
282                                             X86TargetMachine &tm){
283  switch (AsmWriterFlavor) {
284  default:
285    assert(0 && "Unknown asm flavor!");
286  case intel:
287    return new X86IntelAsmPrinter(o, tm);
288  case att:
289    return new X86ATTAsmPrinter(o, tm);
290  }
291}
292