| Chris Lattner | b974046 | 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 | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 18 | #include "X86MachineFunctionInfo.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 19 | #include "X86TargetMachine.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 20 | #include "X86TargetAsmInfo.h" | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 21 | #include "llvm/CallingConv.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 22 | #include "llvm/Module.h" | 
|  | 23 | #include "llvm/Support/Mangler.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 24 | #include "llvm/Target/TargetAsmInfo.h" | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 25 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | de02d77 | 2006-01-22 23:41:00 +0000 | [diff] [blame] | 26 | #include <iostream> | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 27 | using namespace llvm; | 
| Chris Lattner | b974046 | 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 | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 33 | if (Subtarget->isTargetDarwin()) { | 
| Jim Laskey | 5ba7c23 | 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 | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 38 |  | 
| Chris Lattner | 99946fb | 2005-11-21 07:51:23 +0000 | [diff] [blame] | 39 | SetupMachineFunction(MF); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 40 | O << "\n\n"; | 
|  | 41 |  | 
|  | 42 | // Print out constants referenced by the function | 
| Chris Lattner | 8a5f3c1 | 2005-11-21 08:32:23 +0000 | [diff] [blame] | 43 | EmitConstantPool(MF.getConstantPool()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 44 |  | 
|  | 45 | // Print out labels for the function. | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 46 | const Function *F = MF.getFunction(); | 
| Anton Korobeynikov | 3c5b3df | 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 | 5a76680 | 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 | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 60 | SwitchToTextSection(TAI->getTextSection(), F); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 61 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
|  | 62 | break; | 
| Anton Korobeynikov | d61d39e | 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 | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 66 | case Function::ExternalLinkage: | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 67 | SwitchToTextSection(TAI->getTextSection(), F); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 68 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 69 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 70 | break; | 
|  | 71 | case Function::WeakLinkage: | 
|  | 72 | case Function::LinkOnceLinkage: | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 73 | if (Subtarget->isTargetDarwin()) { | 
| Chris Lattner | 8488ba2 | 2006-05-09 04:59:56 +0000 | [diff] [blame] | 74 | SwitchToTextSection( | 
|  | 75 | ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F); | 
| Evan Cheng | 7714a59 | 2006-02-22 23:59:57 +0000 | [diff] [blame] | 76 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 77 | O << "\t.weak_definition\t" << CurrentFnName << "\n"; | 
| Anton Korobeynikov | 6f7072c | 2006-09-17 20:25:45 +0000 | [diff] [blame] | 78 | } else if (Subtarget->isTargetCygwin()) { | 
| Evan Cheng | 2554e3d | 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 | 5a76680 | 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 | 8488ba2 | 2006-05-09 04:59:56 +0000 | [diff] [blame] | 88 | SwitchToTextSection("", F); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 89 | O << "\t.weak " << CurrentFnName << "\n"; | 
|  | 90 | } | 
|  | 91 | break; | 
|  | 92 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 93 | O << CurrentFnName << ":\n"; | 
|  | 94 |  | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 95 | if (Subtarget->isTargetDarwin()) { | 
| Jim Laskey | c0d6518 | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 96 | // Emit pre-function debug information. | 
| Jim Laskey | a7b2bd5 | 2006-06-23 12:51:53 +0000 | [diff] [blame] | 97 | DW.BeginFunction(&MF); | 
| Jim Laskey | c0d6518 | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 98 | } | 
|  | 99 |  | 
| Chris Lattner | b974046 | 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 | b9d4f83 | 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 | b974046 | 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 | 00884b5 | 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 | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 121 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Nate Begeman | 83b492b | 2005-07-12 01:37:28 +0000 | [diff] [blame] | 122 | O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 123 |  | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 124 | if (Subtarget->isTargetDarwin()) { | 
| Evan Cheng | a4a4ceb | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 125 | // Emit post-function debug information. | 
| Jim Laskey | cf0166f | 2006-03-23 18:09:44 +0000 | [diff] [blame] | 126 | DW.EndFunction(); | 
| Evan Cheng | a4a4ceb | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 127 | } | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 128 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 129 | // We didn't modify anything. | 
|  | 130 | return false; | 
|  | 131 | } | 
|  | 132 |  | 
| Chris Lattner | d62a3bf | 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 | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 136 | const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
|  | 137 | switch (MO.getType()) { | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 138 | case MachineOperand::MO_Register: { | 
| Chris Lattner | b974046 | 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 | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 142 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | cfaffdd | 2006-05-31 22:34:26 +0000 | [diff] [blame] | 143 | if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { | 
| Evan Cheng | 11b0a5d | 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 | ddb6cc1 | 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 | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 150 | O << (char)tolower(*Name); | 
|  | 151 | return; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 152 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 153 |  | 
| Chris Lattner | fef7a2d | 2006-05-04 17:21:20 +0000 | [diff] [blame] | 154 | case MachineOperand::MO_Immediate: | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 155 | if (!Modifier || strcmp(Modifier, "debug") != 0) | 
|  | 156 | O << '$'; | 
| Evan Cheng | 70145f2 | 2006-05-26 08:04:31 +0000 | [diff] [blame] | 157 | O << MO.getImmedValue(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 158 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 159 | case MachineOperand::MO_MachineBasicBlock: | 
|  | 160 | printBasicBlockLabel(MO.getMachineBasicBlock()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 161 | return; | 
| Nate Begeman | 4ca2ea5 | 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 | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 165 | O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << "_" | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 166 | << MO.getJumpTableIndex(); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 167 | if (X86PICStyle == PICStyle::Stub && | 
| Nate Begeman | 7875650 | 2006-07-27 01:13:04 +0000 | [diff] [blame] | 168 | TM.getRelocationModel() == Reloc::PIC_) | 
|  | 169 | O << "-\"L" << getFunctionNumber() << "$pb\""; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 170 | if (Subtarget->is64Bit()) | 
|  | 171 | O << "(%rip)"; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 172 | return; | 
|  | 173 | } | 
| Evan Cheng | 75b8783 | 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 | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 177 | O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 178 | << MO.getConstantPoolIndex(); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 179 | if (X86PICStyle == PICStyle::Stub && | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 180 | TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | 75b8783 | 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 | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 187 |  | 
|  | 188 | if (Subtarget->is64Bit()) | 
|  | 189 | O << "(%rip)"; | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 190 | return; | 
|  | 191 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 192 | case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 193 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 194 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 195 | if (!isMemOp && !isCallOp) O << '$'; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 196 |  | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 197 | GlobalValue *GV = MO.getGlobal(); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 198 | std::string Name = Mang->getValueName(GV); | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 199 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 200 | bool isExt = (GV->isExternal() || GV->hasWeakLinkage() || | 
|  | 201 | GV->hasLinkOnceLinkage()); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 202 |  | 
|  | 203 | X86SharedAsmPrinter::decorateName(Name, (Function*)GV); | 
|  | 204 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 205 | if (X86PICStyle == PICStyle::Stub && | 
| Evan Cheng | 2554e3d | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 206 | TM.getRelocationModel() != Reloc::Static) { | 
| Evan Cheng | 5a76680 | 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 | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 209 | if (isExt) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 210 | // Dynamically-resolved functions need a stub for the function. | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 211 | if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 5a76680 | 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 | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 218 | } else { | 
|  | 219 | if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 220 | O << "__imp_"; | 
|  | 221 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 222 | O << Name; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 225 | if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | 1f342c2 | 2006-02-23 02:43:52 +0000 | [diff] [blame] | 226 | O << "-\"L" << getFunctionNumber() << "$pb\""; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 227 | } else { | 
|  | 228 | if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 229 | O << "__imp_"; | 
|  | 230 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 231 | O << Name; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 232 | } | 
|  | 233 |  | 
| Chris Lattner | b974046 | 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 | 11b0a5d | 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 | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 247 | return; | 
|  | 248 | } | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 249 | case MachineOperand::MO_ExternalSymbol: { | 
|  | 250 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 2554e3d | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 251 | if (isCallOp && | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 252 | X86PICStyle == PICStyle::Stub && | 
| Evan Cheng | 2554e3d | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 253 | TM.getRelocationModel() != Reloc::Static) { | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 254 | std::string Name(TAI->getGlobalPrefix()); | 
| Evan Cheng | 73136df | 2006-02-22 20:19:42 +0000 | [diff] [blame] | 255 | Name += MO.getSymbolName(); | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 256 | FnStubs.insert(Name); | 
|  | 257 | O << "L" << Name << "$stub"; | 
|  | 258 | return; | 
|  | 259 | } | 
| Evan Cheng | 73136df | 2006-02-22 20:19:42 +0000 | [diff] [blame] | 260 | if (!isCallOp) O << '$'; | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 261 | O << TAI->getGlobalPrefix() << MO.getSymbolName(); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 262 |  | 
|  | 263 | if (!isCallOp && | 
|  | 264 | Subtarget->is64Bit()) | 
|  | 265 | O << "(%rip)"; | 
|  | 266 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 267 | return; | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 268 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 269 | default: | 
|  | 270 | O << "<unknown operand type>"; return; | 
|  | 271 | } | 
|  | 272 | } | 
|  | 273 |  | 
| Nate Begeman | 6f8c1ac | 2005-11-30 18:54:35 +0000 | [diff] [blame] | 274 | void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { | 
| Nate Begeman | 0f38dc4 | 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 | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 289 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, | 
|  | 290 | const char *Modifier){ | 
| Chris Lattner | b974046 | 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 | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 304 | } | 
|  | 305 |  | 
| Evan Cheng | 6d46414 | 2006-08-29 22:14:48 +0000 | [diff] [blame] | 306 | if (DispSpec.isGlobalAddress() || | 
|  | 307 | DispSpec.isConstantPoolIndex() || | 
|  | 308 | DispSpec.isJumpTableIndex()) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 309 | printOperand(MI, Op+3, "mem"); | 
| Chris Lattner | b974046 | 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 | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 318 | if (BaseReg.getReg()) { | 
|  | 319 | printOperand(MI, Op, Modifier); | 
|  | 320 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 321 |  | 
|  | 322 | if (IndexReg.getReg()) { | 
|  | 323 | O << ","; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 324 | printOperand(MI, Op+2, Modifier); | 
| Chris Lattner | b974046 | 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 | 5588de9 | 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 | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 338 |  | 
| Evan Cheng | d369603 | 2006-04-28 23:19:39 +0000 | [diff] [blame] | 339 | bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, | 
| Evan Cheng | b244b80 | 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 | b244b80 | 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 | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 346 | Reg = getX86SubSuperRegister(Reg, MVT::i8); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 347 | break; | 
|  | 348 | case 'h': // Print QImode high register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 349 | Reg = getX86SubSuperRegister(Reg, MVT::i8, true); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 350 | break; | 
|  | 351 | case 'w': // Print HImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 352 | Reg = getX86SubSuperRegister(Reg, MVT::i16); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 353 | break; | 
|  | 354 | case 'k': // Print SImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 355 | Reg = getX86SubSuperRegister(Reg, MVT::i32); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 356 | break; | 
|  | 357 | } | 
|  | 358 |  | 
| Evan Cheng | ddb6cc1 | 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 | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 362 | return false; | 
|  | 363 | } | 
|  | 364 |  | 
| Evan Cheng | 68a44dc | 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 | b244b80 | 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 | d369603 | 2006-04-28 23:19:39 +0000 | [diff] [blame] | 380 | return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); | 
| Evan Cheng | 68a44dc | 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 | b974046 | 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 | fcdce6d | 2006-01-26 02:27:43 +0000 | [diff] [blame] | 403 |  | 
| Evan Cheng | ddb6cc1 | 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 | 11b0a5d | 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 | ddb6cc1 | 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 | 11b0a5d | 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 | 9733bde | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 422 | Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 423 | else | 
| Evan Cheng | 9733bde | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 424 | Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 425 | O << TAI->getCommentString() << " TRUNCATE "; | 
| Evan Cheng | 9733bde | 2006-05-08 08:01:26 +0000 | [diff] [blame] | 426 | if (Reg0 != Reg1) | 
|  | 427 | O << "\n\t"; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 428 | break; | 
|  | 429 | } | 
| Evan Cheng | 11b0a5d | 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 | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 433 | } | 
|  | 434 |  | 
| Chris Lattner | b974046 | 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 |  |