X86AsmPrinter.cpp revision 69191f8f059aa8d5515c8c037b7ba31183e89778
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 "X86.h"
20#include "llvm/Module.h"
21#include "llvm/Type.h"
22#include "llvm/Assembly/Writer.h"
23#include "llvm/Support/Mangler.h"
24#include "llvm/Support/CommandLine.h"
25using namespace llvm;
26using namespace x86;
27
28Statistic<> llvm::x86::EmittedInsts("asm-printer",
29                                    "Number of machine instrs printed");
30
31enum AsmWriterFlavorTy { att, intel };
32cl::opt<AsmWriterFlavorTy>
33AsmWriterFlavor("x86-asm-syntax",
34                cl::desc("Choose style of code to emit from X86 backend:"),
35                cl::values(
36                           clEnumVal(att,   "  Emit AT&T-style assembly"),
37                           clEnumVal(intel, "  Emit Intel-style assembly"),
38                           clEnumValEnd),
39                cl::init(att));
40
41/// doInitialization
42bool X86SharedAsmPrinter::doInitialization(Module& M) {
43  bool leadingUnderscore = false;
44  forCygwin = false;
45  const std::string& TT = M.getTargetTriple();
46  if (TT.length() > 5) {
47    forCygwin = TT.find("cygwin") != std::string::npos ||
48                TT.find("mingw")  != std::string::npos;
49    forDarwin = TT.find("darwin") != std::string::npos;
50  } else if (TT.empty()) {
51#if defined(__CYGWIN__) || defined(__MINGW32__)
52    forCygwin = true;
53#elif defined(__APPLE__)
54    forDarwin = true;
55#elif defined(_WIN32)
56    leadingUnderscore = true;
57#else
58    leadingUnderscore = false;
59#endif
60  }
61
62  if (leadingUnderscore || forCygwin || forDarwin)
63    GlobalPrefix = "_";
64
65  if (forDarwin) {
66    AlignmentIsInBytes = false;
67    Data64bitsDirective = 0;       // we can't emit a 64-bit unit
68    ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
69    PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
70    ConstantPoolSection = "\t.const\n";
71  }
72
73  return AsmPrinter::doInitialization(M);
74}
75
76bool X86SharedAsmPrinter::doFinalization(Module &M) {
77  const TargetData &TD = TM.getTargetData();
78
79  // Print out module-level global variables here.
80  for (Module::const_global_iterator I = M.global_begin(),
81         E = M.global_end(); I != E; ++I)
82    if (I->hasInitializer()) {   // External global require no code
83      O << "\n\n";
84      std::string name = Mang->getValueName(I);
85      Constant *C = I->getInitializer();
86      unsigned Size = TD.getTypeSize(C->getType());
87      unsigned Align = TD.getTypeAlignmentShift(C->getType());
88
89      if (C->isNullValue() &&
90          (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
91           I->hasWeakLinkage() /* FIXME: Verify correct */)) {
92        SwitchSection(".data", I);
93        if (!forCygwin && !forDarwin && I->hasInternalLinkage())
94          O << "\t.local " << name << "\n";
95        if (forDarwin && I->hasInternalLinkage())
96          O << "\t.lcomm " << name << "," << Size << "," << Align;
97        else
98          O << "\t.comm " << name << "," << Size;
99        if (!forCygwin && !forDarwin)
100          O << "," << (1 << Align);
101        O << "\t\t# ";
102        WriteAsOperand(O, I, true, true, &M);
103        O << "\n";
104      } else {
105        switch (I->getLinkage()) {
106        default: assert(0 && "Unknown linkage type!");
107        case GlobalValue::LinkOnceLinkage:
108        case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
109          // Nonnull linkonce -> weak
110          O << "\t.weak " << name << "\n";
111          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
112          SwitchSection("", I);
113          break;
114        case GlobalValue::AppendingLinkage:
115          // FIXME: appending linkage variables should go into a section of
116          // their name or something.  For now, just emit them as external.
117        case GlobalValue::ExternalLinkage:
118          // If external or appending, declare as a global symbol
119          O << "\t.globl " << name << "\n";
120          // FALL THROUGH
121        case GlobalValue::InternalLinkage:
122          SwitchSection(C->isNullValue() ? ".bss" : ".data", I);
123          break;
124        }
125
126        EmitAlignment(Align);
127        if (!forCygwin && !forDarwin) {
128          O << "\t.type " << name << ",@object\n";
129          O << "\t.size " << name << "," << Size << "\n";
130        }
131        O << name << ":\t\t\t\t# ";
132        WriteAsOperand(O, I, true, true, &M);
133        O << " = ";
134        WriteAsOperand(O, C, false, false, &M);
135        O << "\n";
136        EmitGlobalConstant(C);
137      }
138    }
139
140  if (forDarwin) {
141    SwitchSection("", 0);
142    // Output stubs for external global variables
143    if (GVStubs.begin() != GVStubs.end())
144      O << "\t.non_lazy_symbol_pointer\n";
145    for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
146         i != e; ++i) {
147      O << "L" << *i << "$non_lazy_ptr:\n";
148      O << "\t.indirect_symbol " << *i << "\n";
149      O << "\t.long\t0\n";
150    }
151
152    // Output stubs for dynamically-linked functions
153    unsigned j = 1;
154    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
155         i != e; ++i, ++j) {
156      O << "\t.symbol_stub\n";
157      O << "L" << *i << "$stub:\n";
158      O << "\t.indirect_symbol " << *i << "\n";
159      O << "\tjmp\t*L" << j << "$lz\n";
160      O << "L" << *i << "$stub_binder:\n";
161      O << "\tpushl\t$L" << j << "$lz\n";
162      O << "\tjmp\tdyld_stub_binding_helper\n";
163      O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n";
164      O << "L" << j << "$lz:\n";
165      O << "\t.indirect_symbol " << *i << "\n";
166      O << "\t.long\tL" << *i << "$stub_binder\n";
167    }
168
169    O << "\n";
170
171    // Output stubs for link-once variables
172    if (LinkOnceStubs.begin() != LinkOnceStubs.end())
173      O << ".data\n.align 2\n";
174    for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
175         e = LinkOnceStubs.end(); i != e; ++i) {
176      O << "L" << *i << "$non_lazy_ptr:\n"
177        << "\t.long\t" << *i << '\n';
178    }
179  }
180
181  AsmPrinter::doFinalization(M);
182  return false; // success
183}
184
185/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
186/// for a MachineFunction to the given output stream, using the given target
187/// machine description.
188///
189FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
190  switch (AsmWriterFlavor) {
191  default:
192    assert(0 && "Unknown asm flavor!");
193  case intel:
194    return new X86IntelAsmPrinter(o, tm);
195  case att:
196    return new X86ATTAsmPrinter(o, tm);
197  }
198}
199