| Dan Gohman | e33c4b7 | 2007-06-25 15:11:25 +0000 | [diff] [blame] | 1 | //===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===// | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file contains a printer that converts from our internal representation | 
|  | 11 | // of machine-dependent LLVM code to AT&T format assembly | 
|  | 12 | // language. This printer is the output mechanism used by `llc'. | 
|  | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 16 | #define DEBUG_TYPE "asm-printer" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 17 | #include "X86ATTAsmPrinter.h" | 
| Cedric Venet | 404cd15 | 2008-08-24 12:30:46 +0000 | [diff] [blame] | 18 | #include "X86.h" | 
|  | 19 | #include "X86COFF.h" | 
|  | 20 | #include "X86MachineFunctionInfo.h" | 
|  | 21 | #include "X86TargetMachine.h" | 
|  | 22 | #include "X86TargetAsmInfo.h" | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 23 | #include "llvm/CallingConv.h" | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 24 | #include "llvm/DerivedTypes.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 25 | #include "llvm/Module.h" | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 26 | #include "llvm/Type.h" | 
|  | 27 | #include "llvm/ADT/Statistic.h" | 
|  | 28 | #include "llvm/ADT/StringExtras.h" | 
| Bill Wendling | 0f4c581 | 2009-02-18 23:12:06 +0000 | [diff] [blame^] | 29 | #include "llvm/CodeGen/DwarfWriter.h" | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 30 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 31 | #include "llvm/Support/Mangler.h" | 
| Owen Anderson | 9371964 | 2008-08-21 00:14:44 +0000 | [diff] [blame] | 32 | #include "llvm/Support/raw_ostream.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 33 | #include "llvm/Target/TargetAsmInfo.h" | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 34 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 35 | using namespace llvm; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 36 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 37 | STATISTIC(EmittedInsts, "Number of machine instrs printed"); | 
|  | 38 |  | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 39 | static std::string getPICLabelString(unsigned FnNum, | 
|  | 40 | const TargetAsmInfo *TAI, | 
|  | 41 | const X86Subtarget* Subtarget) { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 42 | std::string label; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 43 | if (Subtarget->isTargetDarwin()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 44 | label =  "\"L" + utostr_32(FnNum) + "$pb\""; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 45 | else if (Subtarget->isTargetELF()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 46 | label = ".Lllvm$" + utostr_32(FnNum) + "." "$piclabel"; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 47 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 48 | assert(0 && "Don't know how to print PIC label!\n"); | 
|  | 49 |  | 
|  | 50 | return label; | 
|  | 51 | } | 
|  | 52 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 53 | static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, | 
|  | 54 | const TargetData *TD) { | 
|  | 55 | X86MachineFunctionInfo Info; | 
|  | 56 | uint64_t Size = 0; | 
|  | 57 |  | 
|  | 58 | switch (F->getCallingConv()) { | 
|  | 59 | case CallingConv::X86_StdCall: | 
|  | 60 | Info.setDecorationStyle(StdCall); | 
|  | 61 | break; | 
|  | 62 | case CallingConv::X86_FastCall: | 
|  | 63 | Info.setDecorationStyle(FastCall); | 
|  | 64 | break; | 
|  | 65 | default: | 
|  | 66 | return Info; | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | unsigned argNum = 1; | 
|  | 70 | for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); | 
|  | 71 | AI != AE; ++AI, ++argNum) { | 
|  | 72 | const Type* Ty = AI->getType(); | 
|  | 73 |  | 
|  | 74 | // 'Dereference' type in case of byval parameter attribute | 
| Devang Patel | 4c758ea | 2008-09-25 21:00:45 +0000 | [diff] [blame] | 75 | if (F->paramHasAttr(argNum, Attribute::ByVal)) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 76 | Ty = cast<PointerType>(Ty)->getElementType(); | 
|  | 77 |  | 
|  | 78 | // Size should be aligned to DWORD boundary | 
| Duncan Sands | dc020f9 | 2009-01-12 20:38:59 +0000 | [diff] [blame] | 79 | Size += ((TD->getTypePaddedSize(Ty) + 3)/4)*4; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 80 | } | 
|  | 81 |  | 
|  | 82 | // We're not supporting tooooo huge arguments :) | 
|  | 83 | Info.setBytesToPopOnReturn((unsigned int)Size); | 
|  | 84 | return Info; | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | /// PrintUnmangledNameSafely - Print out the printable characters in the name. | 
|  | 88 | /// Don't print things like \n or \0. | 
| Owen Anderson | 9371964 | 2008-08-21 00:14:44 +0000 | [diff] [blame] | 89 | static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 90 | for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); | 
|  | 91 | Name != E; ++Name) | 
|  | 92 | if (isprint(*Name)) | 
|  | 93 | OS << *Name; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | /// decorateName - Query FunctionInfoMap and use this information for various | 
|  | 97 | /// name decoration. | 
|  | 98 | void X86ATTAsmPrinter::decorateName(std::string &Name, | 
|  | 99 | const GlobalValue *GV) { | 
|  | 100 | const Function *F = dyn_cast<Function>(GV); | 
|  | 101 | if (!F) return; | 
|  | 102 |  | 
|  | 103 | // We don't want to decorate non-stdcall or non-fastcall functions right now | 
|  | 104 | unsigned CC = F->getCallingConv(); | 
|  | 105 | if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) | 
|  | 106 | return; | 
|  | 107 |  | 
|  | 108 | // Decorate names only when we're targeting Cygwin/Mingw32 targets | 
|  | 109 | if (!Subtarget->isTargetCygMing()) | 
|  | 110 | return; | 
|  | 111 |  | 
|  | 112 | FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); | 
|  | 113 |  | 
|  | 114 | const X86MachineFunctionInfo *Info; | 
|  | 115 | if (info_item == FunctionInfoMap.end()) { | 
|  | 116 | // Calculate apropriate function info and populate map | 
|  | 117 | FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData()); | 
|  | 118 | Info = &FunctionInfoMap[F]; | 
|  | 119 | } else { | 
|  | 120 | Info = &info_item->second; | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | const FunctionType *FT = F->getFunctionType(); | 
|  | 124 | switch (Info->getDecorationStyle()) { | 
|  | 125 | case None: | 
|  | 126 | break; | 
|  | 127 | case StdCall: | 
|  | 128 | // "Pure" variadic functions do not receive @0 suffix. | 
|  | 129 | if (!FT->isVarArg() || (FT->getNumParams() == 0) || | 
|  | 130 | (FT->getNumParams() == 1 && F->hasStructRetAttr())) | 
|  | 131 | Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); | 
|  | 132 | break; | 
|  | 133 | case FastCall: | 
|  | 134 | // "Pure" variadic functions do not receive @0 suffix. | 
|  | 135 | if (!FT->isVarArg() || (FT->getNumParams() == 0) || | 
|  | 136 | (FT->getNumParams() == 1 && F->hasStructRetAttr())) | 
|  | 137 | Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); | 
|  | 138 |  | 
|  | 139 | if (Name[0] == '_') { | 
|  | 140 | Name[0] = '@'; | 
|  | 141 | } else { | 
|  | 142 | Name = '@' + Name; | 
|  | 143 | } | 
|  | 144 | break; | 
|  | 145 | default: | 
|  | 146 | assert(0 && "Unsupported DecorationStyle"); | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 150 | void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 151 | const Function *F = MF.getFunction(); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 152 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 153 | decorateName(CurrentFnName, F); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 154 |  | 
| Anton Korobeynikov | 076e905 | 2008-09-24 22:14:23 +0000 | [diff] [blame] | 155 | SwitchToSection(TAI->SectionForGlobal(F)); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 156 |  | 
| Devang Patel | 1b76f2c | 2008-10-01 23:18:38 +0000 | [diff] [blame] | 157 | unsigned FnAlign = 4; | 
| Devang Patel | ab379c9 | 2008-10-06 17:30:07 +0000 | [diff] [blame] | 158 | if (F->hasFnAttr(Attribute::OptimizeForSize)) | 
| Devang Patel | b9d5e02 | 2008-09-04 21:03:41 +0000 | [diff] [blame] | 159 | FnAlign = 1; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 160 | switch (F->getLinkage()) { | 
|  | 161 | default: assert(0 && "Unknown linkage type!"); | 
|  | 162 | case Function::InternalLinkage:  // Symbols default to internal. | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 163 | case Function::PrivateLinkage: | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 164 | EmitAlignment(FnAlign, F); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 165 | break; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 166 | case Function::DLLExportLinkage: | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 167 | case Function::ExternalLinkage: | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 168 | EmitAlignment(FnAlign, F); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 169 | O << "\t.globl\t" << CurrentFnName << '\n'; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 170 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 171 | case Function::LinkOnceLinkage: | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 172 | case Function::WeakLinkage: | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 173 | EmitAlignment(FnAlign, F); | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 174 | if (Subtarget->isTargetDarwin()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 175 | O << "\t.globl\t" << CurrentFnName << '\n'; | 
|  | 176 | O << TAI->getWeakDefDirective() << CurrentFnName << '\n'; | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 177 | } else if (Subtarget->isTargetCygMing()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 178 | O << "\t.globl\t" << CurrentFnName << "\n" | 
|  | 179 | "\t.linkonce discard\n"; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 180 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 181 | O << "\t.weak\t" << CurrentFnName << '\n'; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 182 | } | 
|  | 183 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 184 | } | 
| Anton Korobeynikov | ed47329 | 2008-08-08 18:25:07 +0000 | [diff] [blame] | 185 |  | 
|  | 186 | printVisibility(CurrentFnName, F->getVisibility()); | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 187 |  | 
|  | 188 | if (Subtarget->isTargetELF()) | 
| Dan Gohman | 204dece | 2007-07-30 15:08:02 +0000 | [diff] [blame] | 189 | O << "\t.type\t" << CurrentFnName << ",@function\n"; | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 190 | else if (Subtarget->isTargetCygMing()) { | 
|  | 191 | O << "\t.def\t " << CurrentFnName | 
|  | 192 | << ";\t.scl\t" << | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 193 | (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 194 | << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) | 
|  | 195 | << ";\t.endef\n"; | 
|  | 196 | } | 
|  | 197 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 198 | O << CurrentFnName << ":\n"; | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 199 | // Add some workaround for linkonce linkage on Cygwin\MinGW | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 200 | if (Subtarget->isTargetCygMing() && | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 201 | (F->getLinkage() == Function::LinkOnceLinkage || | 
|  | 202 | F->getLinkage() == Function::WeakLinkage)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 203 | O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 204 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 205 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 206 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 207 | /// method to print assembly for each instruction. | 
|  | 208 | /// | 
|  | 209 | bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
|  | 210 | const Function *F = MF.getFunction(); | 
| Bill Wendling | b6b0aa2 | 2009-02-06 21:45:08 +0000 | [diff] [blame] | 211 | this->MF = &MF; | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 212 | unsigned CC = F->getCallingConv(); | 
|  | 213 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 214 | SetupMachineFunction(MF); | 
|  | 215 | O << "\n\n"; | 
|  | 216 |  | 
|  | 217 | // Populate function information map.  Actually, We don't want to populate | 
|  | 218 | // non-stdcall or non-fastcall functions' information right now. | 
|  | 219 | if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) | 
|  | 220 | FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); | 
|  | 221 |  | 
|  | 222 | // Print out constants referenced by the function | 
|  | 223 | EmitConstantPool(MF.getConstantPool()); | 
|  | 224 |  | 
|  | 225 | if (F->hasDLLExportLinkage()) | 
|  | 226 | DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); | 
|  | 227 |  | 
|  | 228 | // Print the 'header' of function | 
|  | 229 | emitFunctionHeader(MF); | 
|  | 230 |  | 
|  | 231 | // Emit pre-function debug and/or EH information. | 
|  | 232 | if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling()) | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 233 | DW->BeginFunction(&MF); | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 234 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 235 | // Print out code for the function. | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 236 | bool hasAnyRealCode = false; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 237 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 238 | I != E; ++I) { | 
|  | 239 | // Print a label for the basic block. | 
| Dan Gohman | c731c97 | 2007-10-03 19:26:29 +0000 | [diff] [blame] | 240 | if (!I->pred_empty()) { | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 241 | printBasicBlockLabel(I, true, true); | 
| Nate Begeman | b9d4f83 | 2006-05-02 05:37:32 +0000 | [diff] [blame] | 242 | O << '\n'; | 
|  | 243 | } | 
| Bill Wendling | 1a17ef0 | 2008-01-26 09:03:52 +0000 | [diff] [blame] | 244 | for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); | 
|  | 245 | II != IE; ++II) { | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 246 | // Print the assembly for the instruction. | 
| Dan Gohman | fb19f94 | 2008-07-01 00:05:16 +0000 | [diff] [blame] | 247 | if (!II->isLabel()) | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 248 | hasAnyRealCode = true; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 249 | printMachineInstruction(II); | 
|  | 250 | } | 
|  | 251 | } | 
| Evan Cheng | 00884b5 | 2006-08-28 22:14:16 +0000 | [diff] [blame] | 252 |  | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 253 | if (Subtarget->isTargetDarwin() && !hasAnyRealCode) { | 
|  | 254 | // If the function is empty, then we need to emit *something*. Otherwise, | 
|  | 255 | // the function's label might be associated with something that it wasn't | 
|  | 256 | // meant to be associated with. We emit a noop in this situation. | 
|  | 257 | // We are assuming inline asms are code. | 
|  | 258 | O << "\tnop\n"; | 
|  | 259 | } | 
|  | 260 |  | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 261 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 262 | O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 263 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 264 | // Emit post-function debug information. | 
|  | 265 | if (TAI->doesSupportDebugInformation()) | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 266 | DW->EndFunction(&MF); | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 267 |  | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 268 | // Print out jump tables referenced by the function. | 
|  | 269 | EmitJumpTableInfo(MF.getJumpTableInfo(), MF); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 270 |  | 
| Dan Gohman | cb0df59 | 2008-11-07 19:49:17 +0000 | [diff] [blame] | 271 | O.flush(); | 
|  | 272 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 273 | // We didn't modify anything. | 
|  | 274 | return false; | 
|  | 275 | } | 
|  | 276 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 277 | static inline bool shouldPrintGOT(TargetMachine &TM, const X86Subtarget* ST) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 278 | return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_; | 
|  | 279 | } | 
|  | 280 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 281 | static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) { | 
|  | 282 | return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ && | 
|  | 283 | (ST->isPICStyleRIPRel() || ST->isPICStyleGOT()); | 
|  | 284 | } | 
|  | 285 |  | 
|  | 286 | static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 287 | return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static; | 
|  | 288 | } | 
|  | 289 |  | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 290 | void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 291 | const char *Modifier, bool NotRIPRel) { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 292 | const MachineOperand &MO = MI->getOperand(OpNo); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 293 | switch (MO.getType()) { | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 294 | case MachineOperand::MO_Register: { | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 295 | assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 296 | "Virtual registers should not make it this far!"); | 
|  | 297 | O << '%'; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 298 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | cfaffdd | 2006-05-31 22:34:26 +0000 | [diff] [blame] | 299 | if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 300 | MVT VT = (strcmp(Modifier+6,"64") == 0) ? | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 301 | MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : | 
|  | 302 | ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 303 | Reg = getX86SubSuperRegister(Reg, VT); | 
|  | 304 | } | 
| Evan Cheng | 90a92af | 2008-07-07 22:21:06 +0000 | [diff] [blame] | 305 | O << TRI->getAsmName(Reg); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 306 | return; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 307 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 308 |  | 
| Chris Lattner | fef7a2d | 2006-05-04 17:21:20 +0000 | [diff] [blame] | 309 | case MachineOperand::MO_Immediate: | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 310 | if (!Modifier || | 
|  | 311 | (strcmp(Modifier, "debug") && strcmp(Modifier, "mem"))) | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 312 | O << '$'; | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 313 | O << MO.getImm(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 314 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 315 | case MachineOperand::MO_MachineBasicBlock: | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 316 | printBasicBlockLabel(MO.getMBB()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 317 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 318 | case MachineOperand::MO_JumpTableIndex: { | 
|  | 319 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 320 | if (!isMemOp) O << '$'; | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 321 | O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 322 | << MO.getIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 323 |  | 
|  | 324 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 325 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 326 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 327 | << "$pb\""; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 328 | else if (Subtarget->isPICStyleGOT()) | 
|  | 329 | O << "@GOTOFF"; | 
|  | 330 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 331 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 332 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 333 | O << "(%rip)"; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 334 | return; | 
|  | 335 | } | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 336 | case MachineOperand::MO_ConstantPoolIndex: { | 
|  | 337 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 338 | if (!isMemOp) O << '$'; | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 339 | O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 340 | << MO.getIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 341 |  | 
|  | 342 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 343 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 344 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 345 | << "$pb\""; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 346 | else if (Subtarget->isPICStyleGOT()) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 347 | O << "@GOTOFF"; | 
|  | 348 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 349 |  | 
| Anton Korobeynikov | bff4b37 | 2008-11-22 16:15:34 +0000 | [diff] [blame] | 350 | printOffset(MO.getOffset()); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 351 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 352 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 353 | O << "(%rip)"; | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 354 | return; | 
|  | 355 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 356 | case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 357 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 358 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 359 | bool needCloseParen = false; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 360 |  | 
| Anton Korobeynikov | e8fa50f | 2008-03-11 22:38:53 +0000 | [diff] [blame] | 361 | const GlobalValue *GV = MO.getGlobal(); | 
|  | 362 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); | 
|  | 363 | if (!GVar) { | 
| Anton Korobeynikov | 2fa7518 | 2008-03-22 07:53:40 +0000 | [diff] [blame] | 364 | // If GV is an alias then use the aliasee for determining | 
|  | 365 | // thread-localness. | 
| Anton Korobeynikov | e8fa50f | 2008-03-11 22:38:53 +0000 | [diff] [blame] | 366 | if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) | 
| Anton Korobeynikov | 1a11404 | 2008-09-09 20:05:04 +0000 | [diff] [blame] | 367 | GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false)); | 
| Anton Korobeynikov | e8fa50f | 2008-03-11 22:38:53 +0000 | [diff] [blame] | 368 | } | 
|  | 369 |  | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 370 | bool isThreadLocal = GVar && GVar->isThreadLocal(); | 
|  | 371 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 372 | std::string Name = Mang->getValueName(GV); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 373 | decorateName(Name, GV); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 374 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 375 | if (!isMemOp && !isCallOp) | 
|  | 376 | O << '$'; | 
|  | 377 | else if (Name[0] == '$') { | 
|  | 378 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 379 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 380 | O << '('; | 
|  | 381 | needCloseParen = true; | 
|  | 382 | } | 
|  | 383 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 384 | if (shouldPrintStub(TM, Subtarget)) { | 
| Evan Cheng | 59ca6a8 | 2007-06-04 18:54:57 +0000 | [diff] [blame] | 385 | // Link-once, declaration, or Weakly-linked global variables need | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 386 | // non-lazily-resolved stubs | 
| Duncan Sands | 08d9117 | 2008-09-29 11:25:42 +0000 | [diff] [blame] | 387 | if (GV->isDeclaration() || GV->mayBeOverridden()) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 388 | // Dynamically-resolved functions need a stub for the function. | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 389 | if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 4730522 | 2008-09-20 00:13:45 +0000 | [diff] [blame] | 390 | // Function stubs are no longer needed for Mac OS X 10.5 and up. | 
|  | 391 | if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) { | 
|  | 392 | O << Name; | 
|  | 393 | } else { | 
|  | 394 | FnStubs.insert(Name); | 
|  | 395 | printSuffixedName(Name, "$stub"); | 
|  | 396 | } | 
| Evan Cheng | 2a03c7e | 2008-12-05 01:06:39 +0000 | [diff] [blame] | 397 | } else if (GV->hasHiddenVisibility()) { | 
|  | 398 | if (!GV->isDeclaration() && !GV->hasCommonLinkage()) | 
|  | 399 | // Definition is not definitely in the current translation unit. | 
|  | 400 | O << Name; | 
|  | 401 | else { | 
|  | 402 | HiddenGVStubs.insert(Name); | 
|  | 403 | printSuffixedName(Name, "$non_lazy_ptr"); | 
|  | 404 | } | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 405 | } else { | 
|  | 406 | GVStubs.insert(Name); | 
| Dale Johannesen | 5bf742f | 2008-05-19 21:38:18 +0000 | [diff] [blame] | 407 | printSuffixedName(Name, "$non_lazy_ptr"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 408 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 409 | } else { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 410 | if (GV->hasDLLImportLinkage()) | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 411 | O << "__imp_"; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 412 | O << Name; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 413 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 414 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 415 | if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 416 | O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget); | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 417 | } else { | 
|  | 418 | if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 419 | O << "__imp_"; | 
|  | 420 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 421 | O << Name; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 422 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 423 | if (isCallOp) { | 
|  | 424 | if (shouldPrintPLT(TM, Subtarget)) { | 
|  | 425 | // Assemble call via PLT for externally visible symbols | 
|  | 426 | if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 427 | !GV->hasLocalLinkage()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 428 | O << "@PLT"; | 
|  | 429 | } | 
| Reid Spencer | 5301e7c | 2007-01-30 20:08:39 +0000 | [diff] [blame] | 430 | if (Subtarget->isTargetCygMing() && GV->isDeclaration()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 431 | // Save function name for later type emission | 
|  | 432 | FnStubs.insert(Name); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 433 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 434 | } | 
| Anton Korobeynikov | 12c9494 | 2006-12-01 00:25:12 +0000 | [diff] [blame] | 435 |  | 
| Evan Cheng | 5b02034 | 2006-12-01 07:38:23 +0000 | [diff] [blame] | 436 | if (GV->hasExternalWeakLinkage()) | 
| Rafael Espindola | d7998d0 | 2006-12-18 03:37:18 +0000 | [diff] [blame] | 437 | ExtWeakSymbols.insert(GV); | 
| Anton Korobeynikov | 9205c85 | 2008-05-04 21:36:32 +0000 | [diff] [blame] | 438 |  | 
| Anton Korobeynikov | bff4b37 | 2008-11-22 16:15:34 +0000 | [diff] [blame] | 439 | printOffset(MO.getOffset()); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 440 |  | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 441 | if (isThreadLocal) { | 
| Anton Korobeynikov | 9205c85 | 2008-05-04 21:36:32 +0000 | [diff] [blame] | 442 | if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit()) | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 443 | O << "@TLSGD"; // general dynamic TLS model | 
|  | 444 | else | 
|  | 445 | if (GV->isDeclaration()) | 
|  | 446 | O << "@INDNTPOFF"; // initial exec TLS model | 
|  | 447 | else | 
|  | 448 | O << "@NTPOFF"; // local exec TLS model | 
|  | 449 | } else if (isMemOp) { | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 450 | if (shouldPrintGOT(TM, Subtarget)) { | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 451 | if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 452 | O << "@GOT"; | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 453 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 454 | O << "@GOTOFF"; | 
| Chris Lattner | 9329e78 | 2007-11-04 19:23:28 +0000 | [diff] [blame] | 455 | } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel && | 
|  | 456 | TM.getRelocationModel() != Reloc::Static) { | 
| Anton Korobeynikov | c7ffe0f | 2008-01-20 13:59:37 +0000 | [diff] [blame] | 457 | if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 458 | O << "@GOTPCREL"; | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 459 |  | 
|  | 460 | if (needCloseParen) { | 
|  | 461 | needCloseParen = false; | 
|  | 462 | O << ')'; | 
|  | 463 | } | 
|  | 464 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 465 | // Use rip when possible to reduce code size, except when | 
|  | 466 | // index or base register are also part of the address. e.g. | 
|  | 467 | // foo(%rip)(%rcx,%rax,4) is not legal | 
|  | 468 | O << "(%rip)"; | 
|  | 469 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 470 | } | 
|  | 471 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 472 | if (needCloseParen) | 
|  | 473 | O << ')'; | 
|  | 474 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 475 | return; | 
|  | 476 | } | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 477 | case MachineOperand::MO_ExternalSymbol: { | 
|  | 478 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 479 | bool needCloseParen = false; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 480 | std::string Name(TAI->getGlobalPrefix()); | 
|  | 481 | Name += MO.getSymbolName(); | 
| Evan Cheng | 4730522 | 2008-09-20 00:13:45 +0000 | [diff] [blame] | 482 | // Print function stub suffix unless it's Mac OS X 10.5 and up. | 
|  | 483 | if (isCallOp && shouldPrintStub(TM, Subtarget) && | 
|  | 484 | !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) { | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 485 | FnStubs.insert(Name); | 
| Dale Johannesen | 5bf742f | 2008-05-19 21:38:18 +0000 | [diff] [blame] | 486 | printSuffixedName(Name, "$stub"); | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 487 | return; | 
|  | 488 | } | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 489 | if (!isCallOp) | 
|  | 490 | O << '$'; | 
|  | 491 | else if (Name[0] == '$') { | 
|  | 492 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 493 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 494 | O << '('; | 
|  | 495 | needCloseParen = true; | 
|  | 496 | } | 
|  | 497 |  | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 498 | O << Name; | 
|  | 499 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 500 | if (shouldPrintPLT(TM, Subtarget)) { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 501 | std::string GOTName(TAI->getGlobalPrefix()); | 
|  | 502 | GOTName+="_GLOBAL_OFFSET_TABLE_"; | 
|  | 503 | if (Name == GOTName) | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 504 | // HACK! Emit extra offset to PC during printing GOT offset to | 
|  | 505 | // compensate for the size of popl instruction. The resulting code | 
|  | 506 | // should look like: | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 507 | //   call .piclabel | 
|  | 508 | // piclabel: | 
|  | 509 | //   popl %some_register | 
|  | 510 | //   addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 511 | O << " + [.-" | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 512 | << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']'; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 513 |  | 
|  | 514 | if (isCallOp) | 
|  | 515 | O << "@PLT"; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 516 | } | 
|  | 517 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 518 | if (needCloseParen) | 
|  | 519 | O << ')'; | 
|  | 520 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 521 | if (!isCallOp && Subtarget->isPICStyleRIPRel()) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 522 | O << "(%rip)"; | 
|  | 523 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 524 | return; | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 525 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 526 | default: | 
|  | 527 | O << "<unknown operand type>"; return; | 
|  | 528 | } | 
|  | 529 | } | 
|  | 530 |  | 
| Nate Begeman | 6f8c1ac | 2005-11-30 18:54:35 +0000 | [diff] [blame] | 531 | void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 532 | unsigned char value = MI->getOperand(Op).getImm(); | 
| Nate Begeman | 0f38dc4 | 2005-07-14 22:52:25 +0000 | [diff] [blame] | 533 | assert(value <= 7 && "Invalid ssecc argument!"); | 
|  | 534 | switch (value) { | 
|  | 535 | case 0: O << "eq"; break; | 
|  | 536 | case 1: O << "lt"; break; | 
|  | 537 | case 2: O << "le"; break; | 
|  | 538 | case 3: O << "unord"; break; | 
|  | 539 | case 4: O << "neq"; break; | 
|  | 540 | case 5: O << "nlt"; break; | 
|  | 541 | case 6: O << "nle"; break; | 
|  | 542 | case 7: O << "ord"; break; | 
|  | 543 | } | 
|  | 544 | } | 
|  | 545 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 546 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, | 
|  | 547 | const char *Modifier){ | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 548 | assert(isMem(MI, Op) && "Invalid memory reference!"); | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 549 | MachineOperand BaseReg  = MI->getOperand(Op); | 
|  | 550 | MachineOperand IndexReg = MI->getOperand(Op+2); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 551 | const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
|  | 552 |  | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 553 | bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg(); | 
| Dan Gohman | 0d1e9a8 | 2008-10-03 15:45:36 +0000 | [diff] [blame] | 554 | if (DispSpec.isGlobal() || | 
|  | 555 | DispSpec.isCPI() || | 
|  | 556 | DispSpec.isJTI()) { | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 557 | printOperand(MI, Op+3, "mem", NotRIPRel); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 558 | } else { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 559 | int DispVal = DispSpec.getImm(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 560 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) | 
|  | 561 | O << DispVal; | 
|  | 562 | } | 
|  | 563 |  | 
|  | 564 | if (IndexReg.getReg() || BaseReg.getReg()) { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 565 | unsigned ScaleVal = MI->getOperand(Op+1).getImm(); | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 566 | unsigned BaseRegOperand = 0, IndexRegOperand = 2; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 567 |  | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 568 | // There are cases where we can end up with ESP/RSP in the indexreg slot. | 
|  | 569 | // If this happens, swap the base/index register to support assemblers that | 
|  | 570 | // don't work when the index is *SP. | 
|  | 571 | if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { | 
|  | 572 | assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); | 
|  | 573 | std::swap(BaseReg, IndexReg); | 
|  | 574 | std::swap(BaseRegOperand, IndexRegOperand); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 575 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 576 |  | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 577 | O << '('; | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 578 | if (BaseReg.getReg()) | 
|  | 579 | printOperand(MI, Op+BaseRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 580 |  | 
|  | 581 | if (IndexReg.getReg()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 582 | O << ','; | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 583 | printOperand(MI, Op+IndexRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 584 | if (ScaleVal != 1) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 585 | O << ',' << ScaleVal; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 586 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 587 | O << ')'; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 588 | } | 
|  | 589 | } | 
|  | 590 |  | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 591 | void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid, | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 592 | const MachineBasicBlock *MBB) const { | 
|  | 593 | if (!TAI->getSetDirective()) | 
|  | 594 | return; | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 595 |  | 
|  | 596 | // We don't need .set machinery if we have GOT-style relocations | 
|  | 597 | if (Subtarget->isPICStyleGOT()) | 
|  | 598 | return; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 599 |  | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 600 | O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() | 
|  | 601 | << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 602 | printBasicBlockLabel(MBB, false, false, false); | 
| Evan Cheng | fb13fd6 | 2007-11-09 19:11:23 +0000 | [diff] [blame] | 603 | if (Subtarget->isPICStyleRIPRel()) | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 604 | O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() | 
| Evan Cheng | fb13fd6 | 2007-11-09 19:11:23 +0000 | [diff] [blame] | 605 | << '_' << uid << '\n'; | 
|  | 606 | else | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 607 | O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << '\n'; | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 608 | } | 
|  | 609 |  | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 610 | void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 611 | std::string label = getPICLabelString(getFunctionNumber(), TAI, Subtarget); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 612 | O << label << '\n' << label << ':'; | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 613 | } | 
|  | 614 |  | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 615 |  | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 616 | void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, | 
|  | 617 | const MachineBasicBlock *MBB, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 618 | unsigned uid) const | 
|  | 619 | { | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 620 | const char *JTEntryDirective = MJTI->getEntrySize() == 4 ? | 
|  | 621 | TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); | 
|  | 622 |  | 
|  | 623 | O << JTEntryDirective << ' '; | 
|  | 624 |  | 
|  | 625 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 626 | if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStub()) { | 
|  | 627 | O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 628 | << '_' << uid << "_set_" << MBB->getNumber(); | 
|  | 629 | } else if (Subtarget->isPICStyleGOT()) { | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 630 | printBasicBlockLabel(MBB, false, false, false); | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 631 | O << "@GOTOFF"; | 
|  | 632 | } else | 
|  | 633 | assert(0 && "Don't know how to print MBB label for this PIC mode"); | 
|  | 634 | } else | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 635 | printBasicBlockLabel(MBB, false, false, false); | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 636 | } | 
|  | 637 |  | 
| Anton Korobeynikov | 3c21b05 | 2008-06-28 11:10:06 +0000 | [diff] [blame] | 638 | bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 639 | const char Mode) { | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 640 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 641 | switch (Mode) { | 
|  | 642 | default: return true;  // Unknown mode. | 
|  | 643 | case 'b': // Print QImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 644 | Reg = getX86SubSuperRegister(Reg, MVT::i8); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 645 | break; | 
|  | 646 | case 'h': // Print QImode high register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 647 | Reg = getX86SubSuperRegister(Reg, MVT::i8, true); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 648 | break; | 
|  | 649 | case 'w': // Print HImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 650 | Reg = getX86SubSuperRegister(Reg, MVT::i16); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 651 | break; | 
|  | 652 | case 'k': // Print SImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 653 | Reg = getX86SubSuperRegister(Reg, MVT::i32); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 654 | break; | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 655 | case 'q': // Print DImode register | 
|  | 656 | Reg = getX86SubSuperRegister(Reg, MVT::i64); | 
|  | 657 | break; | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 658 | } | 
|  | 659 |  | 
| Evan Cheng | 90a92af | 2008-07-07 22:21:06 +0000 | [diff] [blame] | 660 | O << '%'<< TRI->getAsmName(Reg); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 661 | return false; | 
|  | 662 | } | 
|  | 663 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 664 | /// PrintAsmOperand - Print out an operand for an inline asm expression. | 
|  | 665 | /// | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 666 | bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 667 | unsigned AsmVariant, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 668 | const char *ExtraCode) { | 
|  | 669 | // Does this asm operand have a single letter operand modifier? | 
|  | 670 | if (ExtraCode && ExtraCode[0]) { | 
|  | 671 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 672 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 673 | switch (ExtraCode[0]) { | 
|  | 674 | default: return true;  // Unknown modifier. | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 675 | case 'c': // Don't print "$" before a global var name or constant. | 
| Chris Lattner | 60ce558 | 2006-10-31 20:12:30 +0000 | [diff] [blame] | 676 | printOperand(MI, OpNo, "mem"); | 
|  | 677 | return false; | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 678 | case 'b': // Print QImode register | 
|  | 679 | case 'h': // Print QImode high register | 
|  | 680 | case 'w': // Print HImode register | 
|  | 681 | case 'k': // Print SImode register | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 682 | case 'q': // Print DImode register | 
| Dan Gohman | 0d1e9a8 | 2008-10-03 15:45:36 +0000 | [diff] [blame] | 683 | if (MI->getOperand(OpNo).isReg()) | 
| Chris Lattner | 927f30d | 2007-03-25 02:01:03 +0000 | [diff] [blame] | 684 | return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); | 
|  | 685 | printOperand(MI, OpNo); | 
|  | 686 | return false; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 687 |  | 
| Chris Lattner | c8ddca7 | 2007-03-25 01:44:57 +0000 | [diff] [blame] | 688 | case 'P': // Don't print @PLT, but do print as memory. | 
|  | 689 | printOperand(MI, OpNo, "mem"); | 
|  | 690 | return false; | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 691 | } | 
|  | 692 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 693 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 694 | printOperand(MI, OpNo); | 
|  | 695 | return false; | 
|  | 696 | } | 
|  | 697 |  | 
| Anton Korobeynikov | 3c21b05 | 2008-06-28 11:10:06 +0000 | [diff] [blame] | 698 | bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 699 | unsigned OpNo, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 700 | unsigned AsmVariant, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 701 | const char *ExtraCode) { | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 702 | if (ExtraCode && ExtraCode[0]) { | 
|  | 703 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 704 |  | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 705 | switch (ExtraCode[0]) { | 
|  | 706 | default: return true;  // Unknown modifier. | 
|  | 707 | case 'b': // Print QImode register | 
|  | 708 | case 'h': // Print QImode high register | 
|  | 709 | case 'w': // Print HImode register | 
|  | 710 | case 'k': // Print SImode register | 
|  | 711 | case 'q': // Print SImode register | 
|  | 712 | // These only apply to registers, ignore on mem. | 
|  | 713 | break; | 
| Chris Lattner | 8329595 | 2009-01-23 22:33:40 +0000 | [diff] [blame] | 714 | case 'P': // Don't print @PLT, but do print as memory. | 
|  | 715 | printOperand(MI, OpNo, "mem"); | 
|  | 716 | return false; | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 717 | } | 
|  | 718 | } | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 719 | printMemReference(MI, OpNo); | 
|  | 720 | return false; | 
|  | 721 | } | 
|  | 722 |  | 
| Bill Wendling | b6b0aa2 | 2009-02-06 21:45:08 +0000 | [diff] [blame] | 723 | /// printMachineInstruction -- Print out a single X86 LLVM instruction MI in | 
|  | 724 | /// AT&T syntax to the current output stream. | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 725 | /// | 
|  | 726 | void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
|  | 727 | ++EmittedInsts; | 
| Evan Cheng | fcdce6d | 2006-01-26 02:27:43 +0000 | [diff] [blame] | 728 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 729 | // Call the autogenerated instruction printer routines. | 
|  | 730 | printInstruction(MI); | 
|  | 731 | } | 
|  | 732 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 733 | /// doInitialization | 
|  | 734 | bool X86ATTAsmPrinter::doInitialization(Module &M) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 735 |  | 
| Evan Cheng | 49c8e68 | 2008-07-09 06:36:53 +0000 | [diff] [blame] | 736 | bool Result = AsmPrinter::doInitialization(M); | 
|  | 737 |  | 
| Dale Johannesen | 605d386 | 2008-07-09 20:55:35 +0000 | [diff] [blame] | 738 | if (TAI->doesSupportDebugInformation()) { | 
|  | 739 | // Let PassManager know we need debug information and relay | 
|  | 740 | // the MachineModuleInfo address on to DwarfWriter. | 
|  | 741 | // AsmPrinter::doInitialization did this analysis. | 
| Duncan Sands | 5a913d6 | 2009-01-28 13:14:17 +0000 | [diff] [blame] | 742 | MMI = getAnalysisIfAvailable<MachineModuleInfo>(); | 
|  | 743 | DW = getAnalysisIfAvailable<DwarfWriter>(); | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 744 | DW->BeginModule(&M, MMI, O, this, TAI); | 
| Dale Johannesen | 605d386 | 2008-07-09 20:55:35 +0000 | [diff] [blame] | 745 | } | 
|  | 746 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 747 | // Darwin wants symbols to be quoted if they have complex names. | 
|  | 748 | if (Subtarget->isTargetDarwin()) | 
|  | 749 | Mang->setUseQuotes(true); | 
|  | 750 |  | 
|  | 751 | return Result; | 
|  | 752 | } | 
|  | 753 |  | 
|  | 754 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 755 | void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 756 | const TargetData *TD = TM.getTargetData(); | 
|  | 757 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 758 | if (!GVar->hasInitializer()) | 
|  | 759 | return;   // External global require no code | 
|  | 760 |  | 
|  | 761 | // Check to see if this is a special global used by LLVM, if so, emit it. | 
|  | 762 | if (EmitSpecialLLVMGlobal(GVar)) { | 
|  | 763 | if (Subtarget->isTargetDarwin() && | 
|  | 764 | TM.getRelocationModel() == Reloc::Static) { | 
|  | 765 | if (GVar->getName() == "llvm.global_ctors") | 
|  | 766 | O << ".reference .constructors_used\n"; | 
|  | 767 | else if (GVar->getName() == "llvm.global_dtors") | 
|  | 768 | O << ".reference .destructors_used\n"; | 
|  | 769 | } | 
|  | 770 | return; | 
|  | 771 | } | 
|  | 772 |  | 
|  | 773 | std::string name = Mang->getValueName(GVar); | 
|  | 774 | Constant *C = GVar->getInitializer(); | 
|  | 775 | const Type *Type = C->getType(); | 
| Duncan Sands | dc020f9 | 2009-01-12 20:38:59 +0000 | [diff] [blame] | 776 | unsigned Size = TD->getTypePaddedSize(Type); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 777 | unsigned Align = TD->getPreferredAlignmentLog(GVar); | 
|  | 778 |  | 
| Anton Korobeynikov | ed47329 | 2008-08-08 18:25:07 +0000 | [diff] [blame] | 779 | printVisibility(name, GVar->getVisibility()); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 780 |  | 
|  | 781 | if (Subtarget->isTargetELF()) | 
|  | 782 | O << "\t.type\t" << name << ",@object\n"; | 
|  | 783 |  | 
| Anton Korobeynikov | 076e905 | 2008-09-24 22:14:23 +0000 | [diff] [blame] | 784 | SwitchToSection(TAI->SectionForGlobal(GVar)); | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 785 |  | 
| Evan Cheng | a40d5e1 | 2009-02-18 02:19:52 +0000 | [diff] [blame] | 786 | if (C->isNullValue() && !GVar->hasSection() && | 
|  | 787 | !(Subtarget->isTargetDarwin() && | 
|  | 788 | TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) { | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 789 | // FIXME: This seems to be pretty darwin-specific | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 790 | if (GVar->hasExternalLinkage()) { | 
|  | 791 | if (const char *Directive = TAI->getZeroFillDirective()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 792 | O << "\t.globl " << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 793 | O << Directive << "__DATA, __common, " << name << ", " | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 794 | << Size << ", " << Align << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 795 | return; | 
|  | 796 | } | 
|  | 797 | } | 
|  | 798 |  | 
|  | 799 | if (!GVar->isThreadLocal() && | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 800 | (GVar->hasLocalLinkage() || GVar->mayBeOverridden())) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 801 | if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it. | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 802 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 803 | if (TAI->getLCOMMDirective() != NULL) { | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 804 | if (GVar->hasLocalLinkage()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 805 | O << TAI->getLCOMMDirective() << name << ',' << Size; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 806 | if (Subtarget->isTargetDarwin()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 807 | O << ',' << Align; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 808 | } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 809 | O << "\t.globl " << name << '\n' | 
|  | 810 | << TAI->getWeakDefDirective() << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 811 | EmitAlignment(Align, GVar); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 812 | O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 813 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 814 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 815 | EmitGlobalConstant(C); | 
|  | 816 | return; | 
|  | 817 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 818 | O << TAI->getCOMMDirective()  << name << ',' << Size; | 
| Anton Korobeynikov | 793108b | 2008-08-08 18:25:52 +0000 | [diff] [blame] | 819 | if (TAI->getCOMMDirectiveTakesAlignment()) | 
|  | 820 | O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 821 | } | 
|  | 822 | } else { | 
|  | 823 | if (!Subtarget->isTargetCygMing()) { | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 824 | if (GVar->hasLocalLinkage()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 825 | O << "\t.local\t" << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 826 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 827 | O << TAI->getCOMMDirective()  << name << ',' << Size; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 828 | if (TAI->getCOMMDirectiveTakesAlignment()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 829 | O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 830 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 831 | O << "\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 832 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 833 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 834 | return; | 
|  | 835 | } | 
|  | 836 | } | 
|  | 837 |  | 
|  | 838 | switch (GVar->getLinkage()) { | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 839 | case GlobalValue::CommonLinkage: | 
|  | 840 | case GlobalValue::LinkOnceLinkage: | 
|  | 841 | case GlobalValue::WeakLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 842 | if (Subtarget->isTargetDarwin()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 843 | O << "\t.globl " << name << '\n' | 
|  | 844 | << TAI->getWeakDefDirective() << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 845 | } else if (Subtarget->isTargetCygMing()) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 846 | O << "\t.globl\t" << name << "\n" | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 847 | "\t.linkonce same_size\n"; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 848 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 849 | O << "\t.weak\t" << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 850 | } | 
|  | 851 | break; | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 852 | case GlobalValue::DLLExportLinkage: | 
|  | 853 | case GlobalValue::AppendingLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 854 | // FIXME: appending linkage variables should go into a section of | 
|  | 855 | // their name or something.  For now, just emit them as external. | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 856 | case GlobalValue::ExternalLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 857 | // If external or appending, declare as a global symbol | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 858 | O << "\t.globl " << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 859 | // FALL THROUGH | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 860 | case GlobalValue::PrivateLinkage: | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 861 | case GlobalValue::InternalLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 862 | break; | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 863 | default: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 864 | assert(0 && "Unknown linkage type!"); | 
|  | 865 | } | 
|  | 866 |  | 
|  | 867 | EmitAlignment(Align, GVar); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 868 | O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 869 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 870 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 871 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 872 | O << "\t.size\t" << name << ", " << Size << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 873 |  | 
|  | 874 | // If the initializer is a extern weak symbol, remember to emit the weak | 
|  | 875 | // reference! | 
|  | 876 | if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) | 
|  | 877 | if (GV->hasExternalWeakLinkage()) | 
|  | 878 | ExtWeakSymbols.insert(GV); | 
|  | 879 |  | 
|  | 880 | EmitGlobalConstant(C); | 
|  | 881 | } | 
|  | 882 |  | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 883 | /// printGVStub - Print stub for a global value. | 
|  | 884 | /// | 
|  | 885 | void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) { | 
| Evan Cheng | 0a1e672 | 2008-07-08 16:40:43 +0000 | [diff] [blame] | 886 | printSuffixedName(GV, "$non_lazy_ptr", Prefix); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 887 | O << ":\n\t.indirect_symbol "; | 
|  | 888 | if (Prefix) O << Prefix; | 
|  | 889 | O << GV << "\n\t.long\t0\n"; | 
|  | 890 | } | 
|  | 891 |  | 
| Evan Cheng | 2a03c7e | 2008-12-05 01:06:39 +0000 | [diff] [blame] | 892 | /// printHiddenGVStub - Print stub for a hidden global value. | 
|  | 893 | /// | 
|  | 894 | void X86ATTAsmPrinter::printHiddenGVStub(const char *GV, const char *Prefix) { | 
|  | 895 | EmitAlignment(2); | 
|  | 896 | printSuffixedName(GV, "$non_lazy_ptr", Prefix); | 
|  | 897 | if (Prefix) O << Prefix; | 
|  | 898 | O << ":\n" << TAI->getData32bitsDirective() << GV << '\n'; | 
|  | 899 | } | 
|  | 900 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 901 |  | 
|  | 902 | bool X86ATTAsmPrinter::doFinalization(Module &M) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 903 | // Print out module-level global variables here. | 
|  | 904 | for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 905 | I != E; ++I) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 906 | printModuleLevelGV(I); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 907 |  | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 908 | if (I->hasDLLExportLinkage()) | 
|  | 909 | DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); | 
|  | 910 | } | 
|  | 911 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 912 | // Output linker support code for dllexported globals | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 913 | if (!DLLExportedGVs.empty()) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 914 | SwitchToDataSection(".section .drectve"); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 915 |  | 
|  | 916 | for (StringSet<>::iterator i = DLLExportedGVs.begin(), | 
|  | 917 | e = DLLExportedGVs.end(); | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 918 | i != e; ++i) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 919 | O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 920 |  | 
|  | 921 | if (!DLLExportedFns.empty()) { | 
|  | 922 | SwitchToDataSection(".section .drectve"); | 
|  | 923 | } | 
|  | 924 |  | 
|  | 925 | for (StringSet<>::iterator i = DLLExportedFns.begin(), | 
|  | 926 | e = DLLExportedFns.end(); | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 927 | i != e; ++i) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 928 | O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 929 |  | 
|  | 930 | if (Subtarget->isTargetDarwin()) { | 
|  | 931 | SwitchToDataSection(""); | 
|  | 932 |  | 
|  | 933 | // Output stubs for dynamically-linked functions | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 934 | for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); | 
| Evan Cheng | 2a03c7e | 2008-12-05 01:06:39 +0000 | [diff] [blame] | 935 | i != e; ++i) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 936 | SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs," | 
|  | 937 | "self_modifying_code+pure_instructions,5", 0); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 938 | const char *p = i->getKeyData(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 939 | printSuffixedName(p, "$stub"); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 940 | O << ":\n" | 
|  | 941 | "\t.indirect_symbol " << p << "\n" | 
|  | 942 | "\thlt ; hlt ; hlt ; hlt ; hlt\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 943 | } | 
|  | 944 |  | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 945 | O << '\n'; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 946 |  | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 947 | // Print global value stubs. | 
|  | 948 | bool InStubSection = false; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 949 | if (TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) { | 
|  | 950 | // Add the (possibly multiple) personalities to the set of global values. | 
|  | 951 | // Only referenced functions get into the Personalities list. | 
|  | 952 | const std::vector<Function *>& Personalities = MMI->getPersonalities(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 953 | for (std::vector<Function *>::const_iterator I = Personalities.begin(), | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 954 | E = Personalities.end(); I != E; ++I) { | 
|  | 955 | if (!*I) | 
|  | 956 | continue; | 
|  | 957 | if (!InStubSection) { | 
|  | 958 | SwitchToDataSection( | 
|  | 959 | "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); | 
|  | 960 | InStubSection = true; | 
|  | 961 | } | 
|  | 962 | printGVStub((*I)->getNameStart(), "_"); | 
|  | 963 | } | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 964 | } | 
|  | 965 |  | 
|  | 966 | // Output stubs for external and common global variables. | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 967 | if (!InStubSection && !GVStubs.empty()) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 968 | SwitchToDataSection( | 
|  | 969 | "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); | 
|  | 970 | for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 971 | i != e; ++i) | 
|  | 972 | printGVStub(i->getKeyData()); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 973 |  | 
| Evan Cheng | 2a03c7e | 2008-12-05 01:06:39 +0000 | [diff] [blame] | 974 | if (!HiddenGVStubs.empty()) { | 
|  | 975 | SwitchToSection(TAI->getDataSection()); | 
|  | 976 | for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end(); | 
|  | 977 | i != e; ++i) | 
|  | 978 | printHiddenGVStub(i->getKeyData()); | 
|  | 979 | } | 
|  | 980 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 981 | // Emit final debug information. | 
| Duncan Sands | 5a913d6 | 2009-01-28 13:14:17 +0000 | [diff] [blame] | 982 | DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 983 | DW->EndModule(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 984 |  | 
|  | 985 | // Funny Darwin hack: This flag tells the linker that no global symbols | 
|  | 986 | // contain code that falls through to other global symbols (e.g. the obvious | 
|  | 987 | // implementation of multiple entry points).  If this doesn't occur, the | 
|  | 988 | // linker can safely perform dead code stripping.  Since LLVM never | 
|  | 989 | // generates code that does this, it is always safe to set. | 
|  | 990 | O << "\t.subsections_via_symbols\n"; | 
|  | 991 | } else if (Subtarget->isTargetCygMing()) { | 
|  | 992 | // Emit type information for external functions | 
|  | 993 | for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); | 
|  | 994 | i != e; ++i) { | 
|  | 995 | O << "\t.def\t " << i->getKeyData() | 
|  | 996 | << ";\t.scl\t" << COFF::C_EXT | 
|  | 997 | << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) | 
|  | 998 | << ";\t.endef\n"; | 
|  | 999 | } | 
|  | 1000 |  | 
|  | 1001 | // Emit final debug information. | 
| Duncan Sands | 5a913d6 | 2009-01-28 13:14:17 +0000 | [diff] [blame] | 1002 | DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 1003 | DW->EndModule(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 1004 | } else if (Subtarget->isTargetELF()) { | 
|  | 1005 | // Emit final debug information. | 
| Duncan Sands | 5a913d6 | 2009-01-28 13:14:17 +0000 | [diff] [blame] | 1006 | DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); | 
| Devang Patel | f646668 | 2009-01-08 23:40:34 +0000 | [diff] [blame] | 1007 | DW->EndModule(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 1008 | } | 
|  | 1009 |  | 
|  | 1010 | return AsmPrinter::doFinalization(M); | 
|  | 1011 | } | 
|  | 1012 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 1013 | // Include the auto-generated portion of the assembly writer. | 
|  | 1014 | #include "X86GenAsmWriter.inc" |