blob: 301bcfe7e2b11f840b1afb0e3e319f565dc4c1af [file] [log] [blame]
Chris Lattnerb9740462005-07-01 22:44:09 +00001//===-- 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"
18#include "X86TargetMachine.h"
19#include "llvm/Module.h"
20#include "llvm/Support/Mangler.h"
Chris Lattnerde02d772006-01-22 23:41:00 +000021#include <iostream>
Chris Lattnerb9740462005-07-01 22:44:09 +000022using namespace llvm;
23using namespace x86;
24
25/// runOnMachineFunction - This uses the printMachineInstruction()
26/// method to print assembly for each instruction.
27///
28bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattner99946fb2005-11-21 07:51:23 +000029 SetupMachineFunction(MF);
Chris Lattnerb9740462005-07-01 22:44:09 +000030 O << "\n\n";
31
32 // Print out constants referenced by the function
Chris Lattner8a5f3c12005-11-21 08:32:23 +000033 EmitConstantPool(MF.getConstantPool());
Chris Lattnerb9740462005-07-01 22:44:09 +000034
35 // Print out labels for the function.
Evan Cheng5a766802006-02-07 08:38:37 +000036 const Function *F = MF.getFunction();
37 switch (F->getLinkage()) {
38 default: assert(0 && "Unknown linkage type!");
39 case Function::InternalLinkage: // Symbols default to internal.
40 SwitchSection(".text", F);
41 EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
42 break;
43 case Function::ExternalLinkage:
44 SwitchSection(".text", F);
45 EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
Chris Lattner9f62a2a2005-12-16 00:07:30 +000046 O << "\t.globl\t" << CurrentFnName << "\n";
Evan Cheng5a766802006-02-07 08:38:37 +000047 break;
48 case Function::WeakLinkage:
49 case Function::LinkOnceLinkage:
50 if (forDarwin) {
51 SwitchSection(".section __TEXT,__textcoal_nt,coalesced,pure_instructions",
52 F);
53 O << "\t.weak_definition\t" << CurrentFnName << "\n";
54 } else {
55 EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
56 O << "\t.section\t.llvm.linkonce.t." << CurrentFnName
57 << ",\"ax\",@progbits\n";
58 O << "\t.weak " << CurrentFnName << "\n";
59 }
60 break;
61 }
Chris Lattnerb9740462005-07-01 22:44:09 +000062 O << CurrentFnName << ":\n";
63
64 // Print out code for the function.
65 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
66 I != E; ++I) {
67 // Print a label for the basic block.
68 if (I->pred_begin() != I->pred_end())
Chris Lattnerd3656272005-11-21 07:43:59 +000069 O << PrivateGlobalPrefix << "BB" << CurrentFnName << "_" << I->getNumber()
70 << ":\t" << CommentString << " " << I->getBasicBlock()->getName()
71 << "\n";
Chris Lattnerb9740462005-07-01 22:44:09 +000072 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
73 II != E; ++II) {
74 // Print the assembly for the instruction.
75 O << "\t";
76 printMachineInstruction(II);
77 }
78 }
Chris Lattnerac6cb462005-11-21 23:06:54 +000079 if (HasDotTypeDotSizeDirective)
Nate Begeman83b492b2005-07-12 01:37:28 +000080 O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
Chris Lattnerb9740462005-07-01 22:44:09 +000081
82 // We didn't modify anything.
83 return false;
84}
85
Chris Lattnerd62a3bf2006-02-06 23:41:19 +000086void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
87 const char *Modifier) {
88 const MachineOperand &MO = MI->getOperand(OpNo);
Chris Lattnerb9740462005-07-01 22:44:09 +000089 const MRegisterInfo &RI = *TM.getRegisterInfo();
90 switch (MO.getType()) {
91 case MachineOperand::MO_VirtualRegister:
92 case MachineOperand::MO_MachineRegister:
93 assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
94 "Virtual registers should not make it this far!");
95 O << '%';
96 for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name)
97 O << (char)tolower(*Name);
98 return;
99
100 case MachineOperand::MO_SignExtendedImmed:
101 case MachineOperand::MO_UnextendedImmed:
102 O << '$' << (int)MO.getImmedValue();
103 return;
104 case MachineOperand::MO_MachineBasicBlock: {
105 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
Chris Lattnerd3656272005-11-21 07:43:59 +0000106 O << PrivateGlobalPrefix << "BB"
107 << Mang->getValueName(MBBOp->getParent()->getFunction())
Chris Lattnerb9740462005-07-01 22:44:09 +0000108 << "_" << MBBOp->getNumber () << "\t# "
109 << MBBOp->getBasicBlock ()->getName ();
110 return;
111 }
112 case MachineOperand::MO_PCRelativeDisp:
113 std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
114 abort ();
115 return;
116 case MachineOperand::MO_GlobalAddress: {
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000117 bool isCallOp = Modifier && !strcmp(Modifier, "call");
Evan Cheng5a766802006-02-07 08:38:37 +0000118 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
119 // Darwin block shameless ripped from PPCAsmPrinter.cpp
Nate Begemanb62a4c82005-07-08 00:23:26 +0000120 if (forDarwin) {
Evan Cheng5a766802006-02-07 08:38:37 +0000121 if (!isMemOp && !isCallOp) O << '$';
Nate Begemanb62a4c82005-07-08 00:23:26 +0000122 GlobalValue *GV = MO.getGlobal();
123 std::string Name = Mang->getValueName(GV);
Evan Cheng5a766802006-02-07 08:38:37 +0000124 // Link-once, External, or Weakly-linked global variables need
125 // non-lazily-resolved stubs
126 if (GV->isExternal() || GV->hasWeakLinkage() ||
127 GV->hasLinkOnceLinkage()) {
128 // Dynamically-resolved functions need a stub for the function.
129 if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
130 FnStubs.insert(Name);
131 O << "L" << Name << "$stub";
132 } else {
133 GVStubs.insert(Name);
134 O << "L" << Name << "$non_lazy_ptr";
135 }
Nate Begeman8dd96ec2005-07-12 18:34:58 +0000136 } else {
137 O << Mang->getValueName(GV);
Nate Begemanb62a4c82005-07-08 00:23:26 +0000138 }
Nate Begeman8dd96ec2005-07-12 18:34:58 +0000139 int Offset = MO.getOffset();
140 if (Offset > 0)
141 O << "+" << Offset;
142 else if (Offset < 0)
143 O << Offset;
Nate Begemanb62a4c82005-07-08 00:23:26 +0000144 return;
145 }
Evan Cheng5a766802006-02-07 08:38:37 +0000146 if (!isMemOp && !isCallOp) O << '$';
Chris Lattnerb9740462005-07-01 22:44:09 +0000147 O << Mang->getValueName(MO.getGlobal());
148 int Offset = MO.getOffset();
149 if (Offset > 0)
150 O << "+" << Offset;
151 else if (Offset < 0)
152 O << Offset;
153 return;
154 }
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000155 case MachineOperand::MO_ExternalSymbol: {
156 bool isCallOp = Modifier && !strcmp(Modifier, "call");
Evan Cheng5a766802006-02-07 08:38:37 +0000157 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
Nate Begemanb62a4c82005-07-08 00:23:26 +0000158 if (isCallOp && forDarwin) {
159 std::string Name(GlobalPrefix); Name += MO.getSymbolName();
160 FnStubs.insert(Name);
161 O << "L" << Name << "$stub";
162 return;
163 }
Evan Cheng5a766802006-02-07 08:38:37 +0000164 if (!isMemOp && !isCallOp) O << '$';
Chris Lattnerb9740462005-07-01 22:44:09 +0000165 O << GlobalPrefix << MO.getSymbolName();
166 return;
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000167 }
Chris Lattnerb9740462005-07-01 22:44:09 +0000168 default:
169 O << "<unknown operand type>"; return;
170 }
171}
172
Nate Begeman6f8c1ac2005-11-30 18:54:35 +0000173void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
Nate Begeman0f38dc42005-07-14 22:52:25 +0000174 unsigned char value = MI->getOperand(Op).getImmedValue();
175 assert(value <= 7 && "Invalid ssecc argument!");
176 switch (value) {
177 case 0: O << "eq"; break;
178 case 1: O << "lt"; break;
179 case 2: O << "le"; break;
180 case 3: O << "unord"; break;
181 case 4: O << "neq"; break;
182 case 5: O << "nlt"; break;
183 case 6: O << "nle"; break;
184 case 7: O << "ord"; break;
185 }
186}
187
Chris Lattnerb9740462005-07-01 22:44:09 +0000188void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
189 assert(isMem(MI, Op) && "Invalid memory reference!");
190
191 const MachineOperand &BaseReg = MI->getOperand(Op);
192 int ScaleVal = MI->getOperand(Op+1).getImmedValue();
193 const MachineOperand &IndexReg = MI->getOperand(Op+2);
194 const MachineOperand &DispSpec = MI->getOperand(Op+3);
195
196 if (BaseReg.isFrameIndex()) {
197 O << "[frame slot #" << BaseReg.getFrameIndex();
198 if (DispSpec.getImmedValue())
199 O << " + " << DispSpec.getImmedValue();
200 O << "]";
201 return;
202 } else if (BaseReg.isConstantPoolIndex()) {
Chris Lattner8a5f3c12005-11-21 08:32:23 +0000203 O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
Chris Lattnerb9740462005-07-01 22:44:09 +0000204 << BaseReg.getConstantPoolIndex();
205 if (DispSpec.getImmedValue())
206 O << "+" << DispSpec.getImmedValue();
207 if (IndexReg.getReg()) {
208 O << "(,";
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000209 printOperand(MI, Op+2);
Chris Lattnerb9740462005-07-01 22:44:09 +0000210 if (ScaleVal != 1)
211 O << "," << ScaleVal;
212 O << ")";
213 }
214 return;
215 }
216
217 if (DispSpec.isGlobalAddress()) {
Evan Cheng5a766802006-02-07 08:38:37 +0000218 printOperand(MI, Op+3, "mem");
Chris Lattnerb9740462005-07-01 22:44:09 +0000219 } else {
220 int DispVal = DispSpec.getImmedValue();
221 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
222 O << DispVal;
223 }
224
225 if (IndexReg.getReg() || BaseReg.getReg()) {
226 O << "(";
227 if (BaseReg.getReg())
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000228 printOperand(MI, Op);
Chris Lattnerb9740462005-07-01 22:44:09 +0000229
230 if (IndexReg.getReg()) {
231 O << ",";
Chris Lattnerd62a3bf2006-02-06 23:41:19 +0000232 printOperand(MI, Op+2);
Chris Lattnerb9740462005-07-01 22:44:09 +0000233 if (ScaleVal != 1)
234 O << "," << ScaleVal;
235 }
236
237 O << ")";
238 }
239}
240
241/// printMachineInstruction -- Print out a single X86 LLVM instruction
242/// MI in Intel syntax to the current output stream.
243///
244void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
245 ++EmittedInsts;
Evan Chengfcdce6d2006-01-26 02:27:43 +0000246 // This works around some Darwin assembler bugs.
247 if (forDarwin) {
248 switch (MI->getOpcode()) {
249 case X86::REP_MOVSB:
250 O << "rep/movsb (%esi),(%edi)\n";
251 return;
252 case X86::REP_MOVSD:
253 O << "rep/movsl (%esi),(%edi)\n";
254 return;
255 case X86::REP_MOVSW:
256 O << "rep/movsw (%esi),(%edi)\n";
257 return;
258 case X86::REP_STOSB:
259 O << "rep/stosb\n";
260 return;
261 case X86::REP_STOSD:
262 O << "rep/stosl\n";
263 return;
264 case X86::REP_STOSW:
265 O << "rep/stosw\n";
266 return;
267 default:
268 break;
269 }
270 }
271
Chris Lattnerb9740462005-07-01 22:44:09 +0000272 // Call the autogenerated instruction printer routines.
273 printInstruction(MI);
274}
275
276// Include the auto-generated portion of the assembly writer.
277#include "X86GenAsmWriter.inc"
278