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