blob: fd31aaf93304fb357db30acad1b3b0dbc4bde288 [file] [log] [blame]
Chris Lattnerfadc83c2009-06-19 00:47:59 +00001//===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file includes code for rendering MCInst instances as AT&T-style
11// assembly.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "llvm/MC/MCInst.h"
17#include "X86ATTAsmPrinter.h"
Chris Lattnerc1243062009-06-20 07:03:18 +000018#include "llvm/Target/TargetAsmInfo.h"
Chris Lattnerd5fb7902009-06-19 23:59:57 +000019#include "llvm/Support/raw_ostream.h"
Chris Lattnerfadc83c2009-06-19 00:47:59 +000020using namespace llvm;
21
Chris Lattnerd5fb7902009-06-19 23:59:57 +000022// Include the auto-generated portion of the assembly writer.
23#define MachineInstr MCInst
24#define NO_ASM_WRITER_BOILERPLATE
25#include "X86GenAsmWriter.inc"
26#undef MachineInstr
27
28void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
Chris Lattnerc1243062009-06-20 07:03:18 +000029 switch (MI->getOperand(Op).getImm()) {
30 default: assert(0 && "Invalid ssecc argument!");
Chris Lattnerf38c03af2009-06-20 00:49:26 +000031 case 0: O << "eq"; break;
32 case 1: O << "lt"; break;
33 case 2: O << "le"; break;
34 case 3: O << "unord"; break;
35 case 4: O << "neq"; break;
36 case 5: O << "nlt"; break;
37 case 6: O << "nle"; break;
38 case 7: O << "ord"; break;
Chris Lattnerd5fb7902009-06-19 23:59:57 +000039 }
40}
41
42
43void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
44 assert(0 &&
45 "This is only used for MOVPC32r, should lower before asm printing!");
46}
47
48
49void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
50 const char *Modifier, bool NotRIPRel) {
Chris Lattnerc1243062009-06-20 07:03:18 +000051 assert(Modifier == 0 && "Modifiers should not be used");
Chris Lattnerf38c03af2009-06-20 00:49:26 +000052
53 const MCOperand &Op = MI->getOperand(OpNo);
54 if (Op.isReg()) {
55 O << '%';
56 unsigned Reg = Op.getReg();
57#if 0
58 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
59 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
60 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
61 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
62 Reg = getX86SubSuperRegister(Reg, VT);
63 }
64#endif
65 O << TRI->getAsmName(Reg);
66 return;
67 } else if (Op.isImm()) {
68 //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem") &&
69 // strcmp(Modifier, "call")))
70 O << '$';
71 O << Op.getImm();
72 return;
Chris Lattnerc1243062009-06-20 07:03:18 +000073 } else if (Op.isMBBLabel()) {
74 // FIXME: Keep in sync with printBasicBlockLabel. printBasicBlockLabel
75 // should eventually call into this code, not the other way around.
76
77 O << TAI->getPrivateGlobalPrefix() << "BB" << Op.getMBBLabelFunction()
78 << '_' << Op.getMBBLabelBlock();
79
80 // FIXME: with verbose asm print llvm bb name, add to operand.
81 return;
Chris Lattnerf38c03af2009-06-20 00:49:26 +000082 }
83
84 O << "<<UNKNOWN OPERAND KIND>>";
85
86
87#if 0
88 const MachineOperand &MO = MI->getOperand(OpNo);
89 switch (MO.getType()) {
90 case MachineOperand::MO_Register: {
91 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
92 "Virtual registers should not make it this far!");
93 O << '%';
94 unsigned Reg = MO.getReg();
95 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
96 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
97 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
98 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
99 Reg = getX86SubSuperRegister(Reg, VT);
100 }
101 O << TRI->getAsmName(Reg);
102 return;
103 }
104
105 case MachineOperand::MO_Immediate:
106 if (!Modifier || (strcmp(Modifier, "debug") &&
107 strcmp(Modifier, "mem") &&
108 strcmp(Modifier, "call")))
109 O << '$';
110 O << MO.getImm();
111 return;
112 case MachineOperand::MO_MachineBasicBlock:
113 printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
114 return;
115 case MachineOperand::MO_JumpTableIndex: {
116 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
117 if (!isMemOp) O << '$';
118 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
119 << MO.getIndex();
120
121 if (TM.getRelocationModel() == Reloc::PIC_) {
122 if (Subtarget->isPICStyleStub())
123 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
124 << "$pb\"";
125 else if (Subtarget->isPICStyleGOT())
126 O << "@GOTOFF";
127 }
128
129 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
130 O << "(%rip)";
131 return;
132 }
133 case MachineOperand::MO_ConstantPoolIndex: {
134 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
135 if (!isMemOp) O << '$';
136 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
137 << MO.getIndex();
138
139 if (TM.getRelocationModel() == Reloc::PIC_) {
140 if (Subtarget->isPICStyleStub())
141 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
142 << "$pb\"";
143 else if (Subtarget->isPICStyleGOT())
144 O << "@GOTOFF";
145 }
146
147 printOffset(MO.getOffset());
148
149 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
150 O << "(%rip)";
151 return;
152 }
153 case MachineOperand::MO_GlobalAddress: {
154 bool isCallOp = Modifier && !strcmp(Modifier, "call");
155 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
156 bool needCloseParen = false;
157
158 const GlobalValue *GV = MO.getGlobal();
159 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
160 if (!GVar) {
161 // If GV is an alias then use the aliasee for determining
162 // thread-localness.
163 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
164 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
165 }
166
167 bool isThreadLocal = GVar && GVar->isThreadLocal();
168
169 std::string Name = Mang->getValueName(GV);
170 decorateName(Name, GV);
171
172 if (!isMemOp && !isCallOp)
173 O << '$';
174 else if (Name[0] == '$') {
175 // The name begins with a dollar-sign. In order to avoid having it look
176 // like an integer immediate to the assembler, enclose it in parens.
177 O << '(';
178 needCloseParen = true;
179 }
180
181 if (shouldPrintStub(TM, Subtarget)) {
182 // Link-once, declaration, or Weakly-linked global variables need
183 // non-lazily-resolved stubs
184 if (GV->isDeclaration() || GV->isWeakForLinker()) {
185 // Dynamically-resolved functions need a stub for the function.
186 if (isCallOp && isa<Function>(GV)) {
187 // Function stubs are no longer needed for Mac OS X 10.5 and up.
188 if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
189 O << Name;
190 } else {
191 FnStubs.insert(Name);
192 printSuffixedName(Name, "$stub");
193 }
194 } else if (GV->hasHiddenVisibility()) {
195 if (!GV->isDeclaration() && !GV->hasCommonLinkage())
196 // Definition is not definitely in the current translation unit.
197 O << Name;
198 else {
199 HiddenGVStubs.insert(Name);
200 printSuffixedName(Name, "$non_lazy_ptr");
201 }
202 } else {
203 GVStubs.insert(Name);
204 printSuffixedName(Name, "$non_lazy_ptr");
205 }
206 } else {
207 if (GV->hasDLLImportLinkage())
208 O << "__imp_";
209 O << Name;
210 }
211
212 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
213 O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
214 } else {
215 if (GV->hasDLLImportLinkage()) {
216 O << "__imp_";
217 }
218 O << Name;
219
220 if (isCallOp) {
221 if (shouldPrintPLT(TM, Subtarget)) {
222 // Assemble call via PLT for externally visible symbols
223 if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
224 !GV->hasLocalLinkage())
225 O << "@PLT";
226 }
227 if (Subtarget->isTargetCygMing() && GV->isDeclaration())
228 // Save function name for later type emission
229 FnStubs.insert(Name);
230 }
231 }
232
233 if (GV->hasExternalWeakLinkage())
234 ExtWeakSymbols.insert(GV);
235
236 printOffset(MO.getOffset());
237
238 if (isThreadLocal) {
239 TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
240 switch (model) {
241 case TLSModel::GeneralDynamic:
242 O << "@TLSGD";
243 break;
244 case TLSModel::LocalDynamic:
245 // O << "@TLSLD"; // local dynamic not implemented
246 O << "@TLSGD";
247 break;
248 case TLSModel::InitialExec:
249 if (Subtarget->is64Bit()) {
250 assert (!NotRIPRel);
251 O << "@GOTTPOFF(%rip)";
252 } else {
253 O << "@INDNTPOFF";
254 }
255 break;
256 case TLSModel::LocalExec:
257 if (Subtarget->is64Bit())
258 O << "@TPOFF";
259 else
260 O << "@NTPOFF";
261 break;
262 default:
263 assert (0 && "Unknown TLS model");
264 }
265 } else if (isMemOp) {
266 if (shouldPrintGOT(TM, Subtarget)) {
267 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
268 O << "@GOT";
269 else
270 O << "@GOTOFF";
271 } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
272 if (TM.getRelocationModel() != Reloc::Static) {
273 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
274 O << "@GOTPCREL";
275
276 if (needCloseParen) {
277 needCloseParen = false;
278 O << ')';
279 }
280 }
281
282 // Use rip when possible to reduce code size, except when
283 // index or base register are also part of the address. e.g.
284 // foo(%rip)(%rcx,%rax,4) is not legal
285 O << "(%rip)";
286 }
287 }
288
289 if (needCloseParen)
290 O << ')';
291
292 return;
293 }
294 case MachineOperand::MO_ExternalSymbol: {
295 bool isCallOp = Modifier && !strcmp(Modifier, "call");
296 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
297 bool needCloseParen = false;
298 std::string Name(TAI->getGlobalPrefix());
299 Name += MO.getSymbolName();
300 // Print function stub suffix unless it's Mac OS X 10.5 and up.
301 if (isCallOp && shouldPrintStub(TM, Subtarget) &&
302 !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
303 FnStubs.insert(Name);
304 printSuffixedName(Name, "$stub");
305 return;
306 }
307 if (!isMemOp && !isCallOp)
308 O << '$';
309 else if (Name[0] == '$') {
310 // The name begins with a dollar-sign. In order to avoid having it look
311 // like an integer immediate to the assembler, enclose it in parens.
312 O << '(';
313 needCloseParen = true;
314 }
315
316 O << Name;
317
318 if (shouldPrintPLT(TM, Subtarget)) {
319 std::string GOTName(TAI->getGlobalPrefix());
320 GOTName+="_GLOBAL_OFFSET_TABLE_";
321 if (Name == GOTName)
322 // HACK! Emit extra offset to PC during printing GOT offset to
323 // compensate for the size of popl instruction. The resulting code
324 // should look like:
325 // call .piclabel
326 // piclabel:
327 // popl %some_register
328 // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
329 O << " + [.-"
330 << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
331
332 if (isCallOp)
333 O << "@PLT";
334 }
335
336 if (needCloseParen)
337 O << ')';
338
339 if (!isCallOp && Subtarget->isPICStyleRIPRel())
340 O << "(%rip)";
341
342 return;
343 }
344 default:
345 O << "<unknown operand type>"; return;
346 }
347#endif
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000348}
349
Chris Lattnerc1243062009-06-20 07:03:18 +0000350void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000351 bool NotRIPRel = false;
352
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000353 const MCOperand &BaseReg = MI->getOperand(Op);
354 const MCOperand &IndexReg = MI->getOperand(Op+2);
355 const MCOperand &DispSpec = MI->getOperand(Op+3);
356
357 NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
358 if (DispSpec.isImm()) {
359 int64_t DispVal = DispSpec.getImm();
360 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
361 O << DispVal;
362 } else {
363 abort();
364 //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
365 // DispSpec.isJTI() || DispSpec.isSymbol());
366 //printOperand(MI, Op+3, "mem", NotRIPRel);
367 }
368
369 if (IndexReg.getReg() || BaseReg.getReg()) {
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000370 // There are cases where we can end up with ESP/RSP in the indexreg slot.
371 // If this happens, swap the base/index register to support assemblers that
372 // don't work when the index is *SP.
373 // FIXME: REMOVE THIS.
Chris Lattnerdc479f62009-06-20 07:59:10 +0000374 assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000375
376 O << '(';
377 if (BaseReg.getReg())
Chris Lattnerdc479f62009-06-20 07:59:10 +0000378 printOperand(MI, Op);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000379
380 if (IndexReg.getReg()) {
381 O << ',';
Chris Lattnerdc479f62009-06-20 07:59:10 +0000382 printOperand(MI, Op+2);
383 if (MI->getOperand(Op+1).getImm() != 1)
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000384 O << ',' << ScaleVal;
385 }
386 O << ')';
387 }
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000388}
389
Chris Lattnerc1243062009-06-20 07:03:18 +0000390void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerad48be02009-06-20 00:50:32 +0000391 //assert(isMem(MI, Op) && "Invalid memory reference!");
392 const MCOperand &Segment = MI->getOperand(Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000393 if (Segment.getReg()) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000394 printOperand(MI, Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000395 O << ':';
396 }
Chris Lattnerc1243062009-06-20 07:03:18 +0000397 printLeaMemReference(MI, Op);
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000398}