| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 1 | //===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to Intel 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 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 |  | 
 | 16 | #include "X86ATTAsmPrinter.h" | 
 | 17 | #include "X86.h" | 
| Anton Korobeynikov | f824868 | 2006-09-20 22:03:51 +0000 | [diff] [blame^] | 18 | #include "X86MachineFunctionInfo.h" | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 19 | #include "X86TargetMachine.h" | 
| Jim Laskey | a0f3d17 | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 20 | #include "X86TargetAsmInfo.h" | 
| Anton Korobeynikov | f824868 | 2006-09-20 22:03:51 +0000 | [diff] [blame^] | 21 | #include "llvm/CallingConv.h" | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 22 | #include "llvm/Module.h" | 
 | 23 | #include "llvm/Support/Mangler.h" | 
| Jim Laskey | a0f3d17 | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 24 | #include "llvm/Target/TargetAsmInfo.h" | 
| Evan Cheng | 7ccced6 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 25 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | 2c2c6c6 | 2006-01-22 23:41:00 +0000 | [diff] [blame] | 26 | #include <iostream> | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 27 | using namespace llvm; | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 28 |  | 
 | 29 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
 | 30 | /// method to print assembly for each instruction. | 
 | 31 | /// | 
 | 32 | bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
| Jim Laskey | ea34858 | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 33 |   if (Subtarget->isTargetDarwin()) { | 
| Jim Laskey | e29c2f5 | 2006-07-19 11:54:50 +0000 | [diff] [blame] | 34 |     // Let PassManager know we need debug information and relay | 
 | 35 |     // the MachineDebugInfo address on to DwarfWriter. | 
 | 36 |     DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>()); | 
 | 37 |   } | 
| Evan Cheng | 3c992d2 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 38 |  | 
| Chris Lattner | 8b8b951 | 2005-11-21 07:51:23 +0000 | [diff] [blame] | 39 |   SetupMachineFunction(MF); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 40 |   O << "\n\n"; | 
 | 41 |  | 
 | 42 |   // Print out constants referenced by the function | 
| Chris Lattner | d939f6c | 2005-11-21 08:32:23 +0000 | [diff] [blame] | 43 |   EmitConstantPool(MF.getConstantPool()); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 44 |  | 
 | 45 |   // Print out labels for the function. | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 46 |   const Function *F = MF.getFunction(); | 
| Anton Korobeynikov | f824868 | 2006-09-20 22:03:51 +0000 | [diff] [blame^] | 47 |   unsigned CC = F->getCallingConv(); | 
 | 48 |  | 
 | 49 |   // Populate function information map.  Actually, We don't want to populate | 
 | 50 |   // non-stdcall or non-fastcall functions' information right now. | 
 | 51 |   if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) { | 
 | 52 |     FunctionInfoMap[F] = *(MF.getInfo<X86FunctionInfo>()); | 
 | 53 |   } | 
 | 54 |  | 
 | 55 |   X86SharedAsmPrinter::decorateName(CurrentFnName, F); | 
 | 56 |  | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 57 |   switch (F->getLinkage()) { | 
 | 58 |   default: assert(0 && "Unknown linkage type!"); | 
 | 59 |   case Function::InternalLinkage:  // Symbols default to internal. | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 60 |     SwitchToTextSection(TAI->getTextSection(), F); | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 61 |     EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
 | 62 |     break; | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 63 |   case Function::DLLExportLinkage: | 
 | 64 |     DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); | 
 | 65 |     //FALLS THROUGH | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 66 |   case Function::ExternalLinkage: | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 67 |     SwitchToTextSection(TAI->getTextSection(), F); | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 68 |     EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 69 |     O << "\t.globl\t" << CurrentFnName << "\n";     | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 70 |     break; | 
 | 71 |   case Function::WeakLinkage: | 
 | 72 |   case Function::LinkOnceLinkage: | 
| Jim Laskey | ea34858 | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 73 |     if (Subtarget->isTargetDarwin()) { | 
| Chris Lattner | 4632d7a | 2006-05-09 04:59:56 +0000 | [diff] [blame] | 74 |       SwitchToTextSection( | 
 | 75 |                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F); | 
| Evan Cheng | f1616da | 2006-02-22 23:59:57 +0000 | [diff] [blame] | 76 |       O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 77 |       O << "\t.weak_definition\t" << CurrentFnName << "\n"; | 
| Anton Korobeynikov | bcb9770 | 2006-09-17 20:25:45 +0000 | [diff] [blame] | 78 |     } else if (Subtarget->isTargetCygwin()) { | 
| Evan Cheng | 932ad51 | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 79 |       EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
 | 80 |       O << "\t.section\t.llvm.linkonce.t." << CurrentFnName | 
 | 81 |         << ",\"ax\"\n"; | 
 | 82 |       SwitchToTextSection("", F); | 
 | 83 |       O << "\t.weak " << CurrentFnName << "\n"; | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 84 |     } else { | 
 | 85 |       EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
 | 86 |       O << "\t.section\t.llvm.linkonce.t." << CurrentFnName | 
 | 87 |         << ",\"ax\",@progbits\n"; | 
| Chris Lattner | 4632d7a | 2006-05-09 04:59:56 +0000 | [diff] [blame] | 88 |       SwitchToTextSection("", F); | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 89 |       O << "\t.weak " << CurrentFnName << "\n"; | 
 | 90 |     } | 
 | 91 |     break; | 
 | 92 |   } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 93 |   O << CurrentFnName << ":\n"; | 
 | 94 |  | 
| Jim Laskey | ea34858 | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 95 |   if (Subtarget->isTargetDarwin()) { | 
| Jim Laskey | 6b92b8e | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 96 |     // Emit pre-function debug information. | 
| Jim Laskey | 89d67fa | 2006-06-23 12:51:53 +0000 | [diff] [blame] | 97 |     DW.BeginFunction(&MF); | 
| Jim Laskey | 6b92b8e | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 98 |   } | 
 | 99 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 100 |   // Print out code for the function. | 
 | 101 |   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
 | 102 |        I != E; ++I) { | 
 | 103 |     // Print a label for the basic block. | 
| Nate Begeman | cdf38c4 | 2006-05-02 05:37:32 +0000 | [diff] [blame] | 104 |     if (I->pred_begin() != I->pred_end()) { | 
 | 105 |       printBasicBlockLabel(I, true); | 
 | 106 |       O << '\n'; | 
 | 107 |     } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 108 |     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
 | 109 |          II != E; ++II) { | 
 | 110 |       // Print the assembly for the instruction. | 
 | 111 |       O << "\t"; | 
 | 112 |       printMachineInstruction(II); | 
 | 113 |     } | 
 | 114 |   } | 
| Evan Cheng | 67afece | 2006-08-28 22:14:16 +0000 | [diff] [blame] | 115 |  | 
 | 116 |   // Print out jump tables referenced by the function | 
 | 117 |   // Mac OS X requires at least one non-local (e.g. L1) labels before local | 
 | 118 |   // lables that are used in jump table expressions (e.g. LBB1_1-LJT1_0). | 
 | 119 |   EmitJumpTableInfo(MF.getJumpTableInfo()); | 
 | 120 |    | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 121 |   if (TAI->hasDotTypeDotSizeDirective()) | 
| Nate Begeman | 73213f6 | 2005-07-12 01:37:28 +0000 | [diff] [blame] | 122 |     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 123 |  | 
| Jim Laskey | ea34858 | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 124 |   if (Subtarget->isTargetDarwin()) { | 
| Evan Cheng | d594881 | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 125 |     // Emit post-function debug information. | 
| Jim Laskey | 99db044 | 2006-03-23 18:09:44 +0000 | [diff] [blame] | 126 |     DW.EndFunction(); | 
| Evan Cheng | d594881 | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 127 |   } | 
| Evan Cheng | 3c992d2 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 128 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 129 |   // We didn't modify anything. | 
 | 130 |   return false; | 
 | 131 | } | 
 | 132 |  | 
| Chris Lattner | a3b8c57 | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 133 | void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, | 
 | 134 |                                     const char *Modifier) { | 
 | 135 |   const MachineOperand &MO = MI->getOperand(OpNo); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 136 |   const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
 | 137 |   switch (MO.getType()) { | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 138 |   case MachineOperand::MO_Register: { | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 139 |     assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && | 
 | 140 |            "Virtual registers should not make it this far!"); | 
 | 141 |     O << '%'; | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 142 |     unsigned Reg = MO.getReg(); | 
| Evan Cheng | cbe70e1 | 2006-05-31 22:34:26 +0000 | [diff] [blame] | 143 |     if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 144 |       MVT::ValueType VT = (strcmp(Modifier+6,"64") == 0) ? | 
 | 145 |         MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : | 
 | 146 |                     ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 147 |       Reg = getX86SubSuperRegister(Reg, VT); | 
 | 148 |     } | 
 | 149 |     for (const char *Name = RI.get(Reg).Name; *Name; ++Name) | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 150 |       O << (char)tolower(*Name); | 
 | 151 |     return; | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 152 |   } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 153 |  | 
| Chris Lattner | 63b3d71 | 2006-05-04 17:21:20 +0000 | [diff] [blame] | 154 |   case MachineOperand::MO_Immediate: | 
| Evan Cheng | 3c992d2 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 155 |     if (!Modifier || strcmp(Modifier, "debug") != 0) | 
 | 156 |       O << '$'; | 
| Evan Cheng | 138a24e | 2006-05-26 08:04:31 +0000 | [diff] [blame] | 157 |     O << MO.getImmedValue(); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 158 |     return; | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 159 |   case MachineOperand::MO_MachineBasicBlock: | 
 | 160 |     printBasicBlockLabel(MO.getMachineBasicBlock()); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 161 |     return; | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 162 |   case MachineOperand::MO_JumpTableIndex: { | 
 | 163 |     bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
 | 164 |     if (!isMemOp) O << '$'; | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 165 |     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << "_" | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 166 |       << MO.getJumpTableIndex(); | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 167 |     if (X86PICStyle == PICStyle::Stub && | 
| Nate Begeman | 2f1ae88 | 2006-07-27 01:13:04 +0000 | [diff] [blame] | 168 |         TM.getRelocationModel() == Reloc::PIC_) | 
 | 169 |       O << "-\"L" << getFunctionNumber() << "$pb\""; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 170 |     if (Subtarget->is64Bit()) | 
 | 171 |       O << "(%rip)"; | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 172 |     return; | 
 | 173 |   } | 
| Evan Cheng | a09bd81 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 174 |   case MachineOperand::MO_ConstantPoolIndex: { | 
 | 175 |     bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
 | 176 |     if (!isMemOp) O << '$'; | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 177 |     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" | 
| Evan Cheng | a09bd81 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 178 |       << MO.getConstantPoolIndex(); | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 179 |     if (X86PICStyle == PICStyle::Stub && | 
| Chris Lattner | 35d86fe | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 180 |         TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | a09bd81 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 181 |       O << "-\"L" << getFunctionNumber() << "$pb\""; | 
 | 182 |     int Offset = MO.getOffset(); | 
 | 183 |     if (Offset > 0) | 
 | 184 |       O << "+" << Offset; | 
 | 185 |     else if (Offset < 0) | 
 | 186 |       O << Offset; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 187 |  | 
 | 188 |     if (Subtarget->is64Bit()) | 
 | 189 |       O << "(%rip)"; | 
| Evan Cheng | a09bd81 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 190 |     return; | 
 | 191 |   } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 192 |   case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | a3b8c57 | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 193 |     bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 194 |     bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
| Evan Cheng | 7ccced6 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 195 |     if (!isMemOp && !isCallOp) O << '$'; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 196 |  | 
| Anton Korobeynikov | f824868 | 2006-09-20 22:03:51 +0000 | [diff] [blame^] | 197 |     GlobalValue *GV = MO.getGlobal(); | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 198 |     std::string Name = Mang->getValueName(GV); | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 199 |      | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 200 |     bool isExt = (GV->isExternal() || GV->hasWeakLinkage() || | 
 | 201 |                   GV->hasLinkOnceLinkage()); | 
| Anton Korobeynikov | f824868 | 2006-09-20 22:03:51 +0000 | [diff] [blame^] | 202 |      | 
 | 203 |     X86SharedAsmPrinter::decorateName(Name, (Function*)GV); | 
 | 204 |      | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 205 |     if (X86PICStyle == PICStyle::Stub && | 
| Evan Cheng | 932ad51 | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 206 |         TM.getRelocationModel() != Reloc::Static) { | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 207 |       // Link-once, External, or Weakly-linked global variables need | 
 | 208 |       // non-lazily-resolved stubs | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 209 |       if (isExt) { | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 210 |         // Dynamically-resolved functions need a stub for the function. | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 211 |         if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 212 |           FnStubs.insert(Name); | 
 | 213 |           O << "L" << Name << "$stub"; | 
 | 214 |         } else { | 
 | 215 |           GVStubs.insert(Name); | 
 | 216 |           O << "L" << Name << "$non_lazy_ptr"; | 
 | 217 |         } | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 218 |       } else { | 
 | 219 |         if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 220 |           O << "__imp_";           | 
 | 221 |         }  | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 222 |         O << Name; | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 223 |       } | 
 | 224 |        | 
| Chris Lattner | 35d86fe | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 225 |       if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | a0ea053 | 2006-02-23 02:43:52 +0000 | [diff] [blame] | 226 |         O << "-\"L" << getFunctionNumber() << "$pb\""; | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 227 |     } else { | 
 | 228 |       if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 229 |         O << "__imp_";           | 
 | 230 |       }        | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 231 |       O << Name; | 
| Anton Korobeynikov | b74ed07 | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 232 |     } | 
 | 233 |      | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 234 |     int Offset = MO.getOffset(); | 
 | 235 |     if (Offset > 0) | 
 | 236 |       O << "+" << Offset; | 
 | 237 |     else if (Offset < 0) | 
 | 238 |       O << Offset; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 239 |  | 
 | 240 |     if (!isCallOp && | 
 | 241 |         Subtarget->is64Bit()) { | 
 | 242 |       if (isExt && TM.getRelocationModel() != Reloc::Static) | 
 | 243 |         O << "@GOTPCREL"; | 
 | 244 |       O << "(%rip)"; | 
 | 245 |     } | 
 | 246 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 247 |     return; | 
 | 248 |   } | 
| Chris Lattner | a3b8c57 | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 249 |   case MachineOperand::MO_ExternalSymbol: { | 
 | 250 |     bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 932ad51 | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 251 |     if (isCallOp &&  | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 252 |         X86PICStyle == PICStyle::Stub && | 
| Evan Cheng | 932ad51 | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 253 |         TM.getRelocationModel() != Reloc::Static) { | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 254 |       std::string Name(TAI->getGlobalPrefix()); | 
| Evan Cheng | 4c1aa86 | 2006-02-22 20:19:42 +0000 | [diff] [blame] | 255 |       Name += MO.getSymbolName(); | 
| Nate Begeman | 72b286b | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 256 |       FnStubs.insert(Name); | 
 | 257 |       O << "L" << Name << "$stub"; | 
 | 258 |       return; | 
 | 259 |     } | 
| Evan Cheng | 4c1aa86 | 2006-02-22 20:19:42 +0000 | [diff] [blame] | 260 |     if (!isCallOp) O << '$'; | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 261 |     O << TAI->getGlobalPrefix() << MO.getSymbolName(); | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 262 |  | 
 | 263 |     if (!isCallOp && | 
 | 264 |         Subtarget->is64Bit()) | 
 | 265 |       O << "(%rip)"; | 
 | 266 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 267 |     return; | 
| Chris Lattner | a3b8c57 | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 268 |   } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 269 |   default: | 
 | 270 |     O << "<unknown operand type>"; return; | 
 | 271 |   } | 
 | 272 | } | 
 | 273 |  | 
| Nate Begeman | 391c5d2 | 2005-11-30 18:54:35 +0000 | [diff] [blame] | 274 | void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { | 
| Nate Begeman | 6c7cb29 | 2005-07-14 22:52:25 +0000 | [diff] [blame] | 275 |   unsigned char value = MI->getOperand(Op).getImmedValue(); | 
 | 276 |   assert(value <= 7 && "Invalid ssecc argument!"); | 
 | 277 |   switch (value) { | 
 | 278 |   case 0: O << "eq"; break; | 
 | 279 |   case 1: O << "lt"; break; | 
 | 280 |   case 2: O << "le"; break; | 
 | 281 |   case 3: O << "unord"; break; | 
 | 282 |   case 4: O << "neq"; break; | 
 | 283 |   case 5: O << "nlt"; break; | 
 | 284 |   case 6: O << "nle"; break; | 
 | 285 |   case 7: O << "ord"; break; | 
 | 286 |   } | 
 | 287 | } | 
 | 288 |  | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 289 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, | 
 | 290 |                                          const char *Modifier){ | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 291 |   assert(isMem(MI, Op) && "Invalid memory reference!"); | 
 | 292 |  | 
 | 293 |   const MachineOperand &BaseReg  = MI->getOperand(Op); | 
 | 294 |   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue(); | 
 | 295 |   const MachineOperand &IndexReg = MI->getOperand(Op+2); | 
 | 296 |   const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
 | 297 |  | 
 | 298 |   if (BaseReg.isFrameIndex()) { | 
 | 299 |     O << "[frame slot #" << BaseReg.getFrameIndex(); | 
 | 300 |     if (DispSpec.getImmedValue()) | 
 | 301 |       O << " + " << DispSpec.getImmedValue(); | 
 | 302 |     O << "]"; | 
 | 303 |     return; | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 304 |   } | 
 | 305 |  | 
| Evan Cheng | c9676de | 2006-08-29 22:14:48 +0000 | [diff] [blame] | 306 |   if (DispSpec.isGlobalAddress() || | 
 | 307 |       DispSpec.isConstantPoolIndex() || | 
 | 308 |       DispSpec.isJumpTableIndex()) { | 
| Evan Cheng | 2338c5c | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 309 |     printOperand(MI, Op+3, "mem"); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 310 |   } else { | 
 | 311 |     int DispVal = DispSpec.getImmedValue(); | 
 | 312 |     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) | 
 | 313 |       O << DispVal; | 
 | 314 |   } | 
 | 315 |  | 
 | 316 |   if (IndexReg.getReg() || BaseReg.getReg()) { | 
 | 317 |     O << "("; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 318 |     if (BaseReg.getReg()) { | 
 | 319 |       printOperand(MI, Op, Modifier); | 
 | 320 |     } | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 321 |  | 
 | 322 |     if (IndexReg.getReg()) { | 
 | 323 |       O << ","; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 324 |       printOperand(MI, Op+2, Modifier); | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 325 |       if (ScaleVal != 1) | 
 | 326 |         O << "," << ScaleVal; | 
 | 327 |     } | 
 | 328 |  | 
 | 329 |     O << ")"; | 
 | 330 |   } | 
 | 331 | } | 
 | 332 |  | 
| Evan Cheng | 7ccced6 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 333 | void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { | 
 | 334 |   O << "\"L" << getFunctionNumber() << "$pb\"\n"; | 
 | 335 |   O << "\"L" << getFunctionNumber() << "$pb\":"; | 
 | 336 | } | 
 | 337 |  | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 338 |  | 
| Evan Cheng | 55c25f2 | 2006-04-28 23:19:39 +0000 | [diff] [blame] | 339 | bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 340 |                                          const char Mode) { | 
 | 341 |   const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
 | 342 |   unsigned Reg = MO.getReg(); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 343 |   switch (Mode) { | 
 | 344 |   default: return true;  // Unknown mode. | 
 | 345 |   case 'b': // Print QImode register | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 346 |     Reg = getX86SubSuperRegister(Reg, MVT::i8); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 347 |     break; | 
 | 348 |   case 'h': // Print QImode high register | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 349 |     Reg = getX86SubSuperRegister(Reg, MVT::i8, true); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 350 |     break; | 
 | 351 |   case 'w': // Print HImode register | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 352 |     Reg = getX86SubSuperRegister(Reg, MVT::i16); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 353 |     break; | 
 | 354 |   case 'k': // Print SImode register | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 355 |     Reg = getX86SubSuperRegister(Reg, MVT::i32); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 356 |     break; | 
 | 357 |   } | 
 | 358 |  | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 359 |   O << '%'; | 
 | 360 |   for (const char *Name = RI.get(Reg).Name; *Name; ++Name) | 
 | 361 |     O << (char)tolower(*Name); | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 362 |   return false; | 
 | 363 | } | 
 | 364 |  | 
| Evan Cheng | 3d48a90 | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 365 | /// PrintAsmOperand - Print out an operand for an inline asm expression. | 
 | 366 | /// | 
 | 367 | bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
 | 368 |                                        unsigned AsmVariant,  | 
 | 369 |                                        const char *ExtraCode) { | 
 | 370 |   // Does this asm operand have a single letter operand modifier? | 
 | 371 |   if (ExtraCode && ExtraCode[0]) { | 
 | 372 |     if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
 | 373 |      | 
 | 374 |     switch (ExtraCode[0]) { | 
 | 375 |     default: return true;  // Unknown modifier. | 
| Evan Cheng | 62f2700 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 376 |     case 'b': // Print QImode register | 
 | 377 |     case 'h': // Print QImode high register | 
 | 378 |     case 'w': // Print HImode register | 
 | 379 |     case 'k': // Print SImode register | 
| Evan Cheng | 55c25f2 | 2006-04-28 23:19:39 +0000 | [diff] [blame] | 380 |       return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); | 
| Evan Cheng | 3d48a90 | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 381 |     } | 
 | 382 |   } | 
 | 383 |    | 
 | 384 |   printOperand(MI, OpNo); | 
 | 385 |   return false; | 
 | 386 | } | 
 | 387 |  | 
 | 388 | bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
 | 389 |                                              unsigned OpNo, | 
 | 390 |                                              unsigned AsmVariant,  | 
 | 391 |                                              const char *ExtraCode) { | 
 | 392 |   if (ExtraCode && ExtraCode[0]) | 
 | 393 |     return true; // Unknown modifier. | 
 | 394 |   printMemReference(MI, OpNo); | 
 | 395 |   return false; | 
 | 396 | } | 
 | 397 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 398 | /// printMachineInstruction -- Print out a single X86 LLVM instruction | 
 | 399 | /// MI in Intel syntax to the current output stream. | 
 | 400 | /// | 
 | 401 | void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
 | 402 |   ++EmittedInsts; | 
| Evan Cheng | 67caa39 | 2006-01-26 02:27:43 +0000 | [diff] [blame] | 403 |  | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 404 |   // See if a truncate instruction can be turned into a nop. | 
 | 405 |   switch (MI->getOpcode()) { | 
 | 406 |   default: break; | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 407 |   case X86::TRUNC_64to32: | 
 | 408 |   case X86::TRUNC_64to16: | 
 | 409 |   case X86::TRUNC_32to16: | 
 | 410 |   case X86::TRUNC_32to8: | 
 | 411 |   case X86::TRUNC_16to8: | 
 | 412 |   case X86::TRUNC_32_to8: | 
 | 413 |   case X86::TRUNC_16_to8: { | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 414 |     const MachineOperand &MO0 = MI->getOperand(0); | 
 | 415 |     const MachineOperand &MO1 = MI->getOperand(1); | 
 | 416 |     unsigned Reg0 = MO0.getReg(); | 
 | 417 |     unsigned Reg1 = MO1.getReg(); | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 418 |     unsigned Opc = MI->getOpcode(); | 
 | 419 |     if (Opc == X86::TRUNC_64to32) | 
 | 420 |       Reg1 = getX86SubSuperRegister(Reg1, MVT::i32); | 
 | 421 |     else if (Opc == X86::TRUNC_32to16 || Opc == X86::TRUNC_64to16) | 
| Evan Cheng | 403be7e | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 422 |       Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 423 |     else | 
| Evan Cheng | 403be7e | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 424 |       Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); | 
| Jim Laskey | 563321a | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 425 |     O << TAI->getCommentString() << " TRUNCATE "; | 
| Evan Cheng | 403be7e | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 426 |     if (Reg0 != Reg1) | 
 | 427 |       O << "\n\t"; | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 428 |     break; | 
 | 429 |   } | 
| Evan Cheng | 25ab690 | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 430 |   case X86::PsMOVZX64rr32: | 
 | 431 |     O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; | 
 | 432 |     break; | 
| Evan Cheng | 8f7f712 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 433 |   } | 
 | 434 |  | 
| Chris Lattner | b36cbd0 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 435 |   // Call the autogenerated instruction printer routines. | 
 | 436 |   printInstruction(MI); | 
 | 437 | } | 
 | 438 |  | 
 | 439 | // Include the auto-generated portion of the assembly writer. | 
 | 440 | #include "X86GenAsmWriter.inc" | 
 | 441 |  |