X86AsmPrinter.cpp revision d1239b7c69e3c8f36d21c30d5df923cfeb96583e
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 49 switch (Subtarget->TargetType) { 50 case X86Subtarget::isDarwin: 51 AlignmentIsInBytes = false; 52 GlobalPrefix = "_"; 53 Data64bitsDirective = 0; // we can't emit a 64-bit unit 54 ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. 55 PrivateGlobalPrefix = "L"; // Marker for constant pool idxs 56 ConstantPoolSection = "\t.const\n"; 57 LCOMMDirective = "\t.lcomm\t"; 58 COMMDirectiveTakesAlignment = false; 59 HasDotTypeDotSizeDirective = false; 60 forDarwin = true; 61 StaticCtorsSection = ".mod_init_func"; 62 StaticDtorsSection = ".mod_term_func"; 63 break; 64 case X86Subtarget::isCygwin: 65 GlobalPrefix = "_"; 66 COMMDirectiveTakesAlignment = false; 67 HasDotTypeDotSizeDirective = false; 68 break; 69 case X86Subtarget::isWindows: 70 GlobalPrefix = "_"; 71 HasDotTypeDotSizeDirective = false; 72 break; 73 default: break; 74 } 75 76 return AsmPrinter::doInitialization(M); 77} 78 79bool X86SharedAsmPrinter::doFinalization(Module &M) { 80 const TargetData &TD = TM.getTargetData(); 81 82 // Print out module-level global variables here. 83 for (Module::const_global_iterator I = M.global_begin(), 84 E = M.global_end(); I != E; ++I) { 85 if (!I->hasInitializer()) continue; // External global require no code 86 87 // Check to see if this is a special global used by LLVM, if so, emit it. 88 if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I)) 89 continue; 90 91 O << "\n\n"; 92 std::string name = Mang->getValueName(I); 93 Constant *C = I->getInitializer(); 94 unsigned Size = TD.getTypeSize(C->getType()); 95 unsigned Align = TD.getTypeAlignmentShift(C->getType()); 96 97 switch (I->getLinkage()) { 98 default: assert(0 && "Unknown linkage type!"); 99 case GlobalValue::LinkOnceLinkage: 100 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 101 if (C->isNullValue()) { 102 O << COMMDirective << name << "," << Size; 103 if (COMMDirectiveTakesAlignment) 104 O << "," << (1 << Align); 105 O << "\t\t" << CommentString << " " << I->getName() << "\n"; 106 continue; 107 } 108 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::InternalLinkage: 115 if (C->isNullValue()) { 116 if (LCOMMDirective) { 117 O << LCOMMDirective << name << "," << Size << "," << Align; 118 continue; 119 } else { 120 SwitchSection(".bss", I); 121 O << "\t.local " << name << "\n"; 122 O << COMMDirective << name << "," << Size; 123 if (COMMDirectiveTakesAlignment) 124 O << "," << (1 << Align); 125 O << "\t\t# "; 126 WriteAsOperand(O, I, true, true, &M); 127 O << "\n"; 128 continue; 129 } 130 } 131 SwitchSection(".data", I); 132 break; 133 case GlobalValue::AppendingLinkage: 134 // FIXME: appending linkage variables should go into a section of 135 // their name or something. For now, just emit them as external. 136 case GlobalValue::ExternalLinkage: 137 SwitchSection(C->isNullValue() ? ".bss" : ".data", I); 138 // If external or appending, declare as a global symbol 139 O << "\t.globl " << name << "\n"; 140 break; 141 } 142 143 EmitAlignment(Align); 144 if (HasDotTypeDotSizeDirective) { 145 O << "\t.type " << name << ",@object\n"; 146 O << "\t.size " << name << "," << Size << "\n"; 147 } 148 O << name << ":\t\t\t" << CommentString << ' ' << I->getName() << '\n'; 149 EmitGlobalConstant(C); 150 } 151 152 if (forDarwin) { 153 SwitchSection("", 0); 154 // Output stubs for external global variables 155 if (GVStubs.begin() != GVStubs.end()) 156 O << "\t.non_lazy_symbol_pointer\n"; 157 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 158 i != e; ++i) { 159 O << "L" << *i << "$non_lazy_ptr:\n"; 160 O << "\t.indirect_symbol " << *i << "\n"; 161 O << "\t.long\t0\n"; 162 } 163 164 // Output stubs for dynamically-linked functions 165 unsigned j = 1; 166 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 167 i != e; ++i, ++j) { 168 O << "\t.symbol_stub\n"; 169 O << "L" << *i << "$stub:\n"; 170 O << "\t.indirect_symbol " << *i << "\n"; 171 O << "\tjmp\t*L" << j << "$lz\n"; 172 O << "L" << *i << "$stub_binder:\n"; 173 O << "\tpushl\t$L" << j << "$lz\n"; 174 O << "\tjmp\tdyld_stub_binding_helper\n"; 175 O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n"; 176 O << "L" << j << "$lz:\n"; 177 O << "\t.indirect_symbol " << *i << "\n"; 178 O << "\t.long\tL" << *i << "$stub_binder\n"; 179 } 180 181 O << "\n"; 182 183 // Output stubs for link-once variables 184 if (LinkOnceStubs.begin() != LinkOnceStubs.end()) 185 O << ".data\n.align 2\n"; 186 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 187 e = LinkOnceStubs.end(); i != e; ++i) { 188 O << "L" << *i << "$non_lazy_ptr:\n" 189 << "\t.long\t" << *i << '\n'; 190 } 191 } 192 193 AsmPrinter::doFinalization(M); 194 return false; // success 195} 196 197/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code 198/// for a MachineFunction to the given output stream, using the given target 199/// machine description. 200/// 201FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ 202 switch (AsmWriterFlavor) { 203 default: 204 assert(0 && "Unknown asm flavor!"); 205 case intel: 206 return new X86IntelAsmPrinter(o, tm); 207 case att: 208 return new X86ATTAsmPrinter(o, tm); 209 } 210} 211