blob: e46f7a3c74f46e69c8145a2ebcb0259be9247f11 [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 Lattnerd5fb7902009-06-19 23:59:57 +000018#include "llvm/Support/raw_ostream.h"
Chris Lattnerfadc83c2009-06-19 00:47:59 +000019using namespace llvm;
20
Chris Lattnerd5fb7902009-06-19 23:59:57 +000021// Include the auto-generated portion of the assembly writer.
22#define MachineInstr MCInst
23#define NO_ASM_WRITER_BOILERPLATE
24#include "X86GenAsmWriter.inc"
25#undef MachineInstr
26
27void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
28 unsigned char value = MI->getOperand(Op).getImm();
29 assert(value <= 7 && "Invalid ssecc argument!");
30 switch (value) {
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 Lattnerf38c03af2009-06-20 00:49:26 +000051 //assert(Modifier == 0 && "Modifiers should not be used");
52
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;
73 }
74
75 O << "<<UNKNOWN OPERAND KIND>>";
76
77
78#if 0
79 const MachineOperand &MO = MI->getOperand(OpNo);
80 switch (MO.getType()) {
81 case MachineOperand::MO_Register: {
82 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
83 "Virtual registers should not make it this far!");
84 O << '%';
85 unsigned Reg = MO.getReg();
86 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
87 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
88 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
89 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
90 Reg = getX86SubSuperRegister(Reg, VT);
91 }
92 O << TRI->getAsmName(Reg);
93 return;
94 }
95
96 case MachineOperand::MO_Immediate:
97 if (!Modifier || (strcmp(Modifier, "debug") &&
98 strcmp(Modifier, "mem") &&
99 strcmp(Modifier, "call")))
100 O << '$';
101 O << MO.getImm();
102 return;
103 case MachineOperand::MO_MachineBasicBlock:
104 printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
105 return;
106 case MachineOperand::MO_JumpTableIndex: {
107 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
108 if (!isMemOp) O << '$';
109 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
110 << MO.getIndex();
111
112 if (TM.getRelocationModel() == Reloc::PIC_) {
113 if (Subtarget->isPICStyleStub())
114 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
115 << "$pb\"";
116 else if (Subtarget->isPICStyleGOT())
117 O << "@GOTOFF";
118 }
119
120 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
121 O << "(%rip)";
122 return;
123 }
124 case MachineOperand::MO_ConstantPoolIndex: {
125 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
126 if (!isMemOp) O << '$';
127 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
128 << MO.getIndex();
129
130 if (TM.getRelocationModel() == Reloc::PIC_) {
131 if (Subtarget->isPICStyleStub())
132 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
133 << "$pb\"";
134 else if (Subtarget->isPICStyleGOT())
135 O << "@GOTOFF";
136 }
137
138 printOffset(MO.getOffset());
139
140 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
141 O << "(%rip)";
142 return;
143 }
144 case MachineOperand::MO_GlobalAddress: {
145 bool isCallOp = Modifier && !strcmp(Modifier, "call");
146 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
147 bool needCloseParen = false;
148
149 const GlobalValue *GV = MO.getGlobal();
150 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
151 if (!GVar) {
152 // If GV is an alias then use the aliasee for determining
153 // thread-localness.
154 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
155 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
156 }
157
158 bool isThreadLocal = GVar && GVar->isThreadLocal();
159
160 std::string Name = Mang->getValueName(GV);
161 decorateName(Name, GV);
162
163 if (!isMemOp && !isCallOp)
164 O << '$';
165 else if (Name[0] == '$') {
166 // The name begins with a dollar-sign. In order to avoid having it look
167 // like an integer immediate to the assembler, enclose it in parens.
168 O << '(';
169 needCloseParen = true;
170 }
171
172 if (shouldPrintStub(TM, Subtarget)) {
173 // Link-once, declaration, or Weakly-linked global variables need
174 // non-lazily-resolved stubs
175 if (GV->isDeclaration() || GV->isWeakForLinker()) {
176 // Dynamically-resolved functions need a stub for the function.
177 if (isCallOp && isa<Function>(GV)) {
178 // Function stubs are no longer needed for Mac OS X 10.5 and up.
179 if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
180 O << Name;
181 } else {
182 FnStubs.insert(Name);
183 printSuffixedName(Name, "$stub");
184 }
185 } else if (GV->hasHiddenVisibility()) {
186 if (!GV->isDeclaration() && !GV->hasCommonLinkage())
187 // Definition is not definitely in the current translation unit.
188 O << Name;
189 else {
190 HiddenGVStubs.insert(Name);
191 printSuffixedName(Name, "$non_lazy_ptr");
192 }
193 } else {
194 GVStubs.insert(Name);
195 printSuffixedName(Name, "$non_lazy_ptr");
196 }
197 } else {
198 if (GV->hasDLLImportLinkage())
199 O << "__imp_";
200 O << Name;
201 }
202
203 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
204 O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
205 } else {
206 if (GV->hasDLLImportLinkage()) {
207 O << "__imp_";
208 }
209 O << Name;
210
211 if (isCallOp) {
212 if (shouldPrintPLT(TM, Subtarget)) {
213 // Assemble call via PLT for externally visible symbols
214 if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
215 !GV->hasLocalLinkage())
216 O << "@PLT";
217 }
218 if (Subtarget->isTargetCygMing() && GV->isDeclaration())
219 // Save function name for later type emission
220 FnStubs.insert(Name);
221 }
222 }
223
224 if (GV->hasExternalWeakLinkage())
225 ExtWeakSymbols.insert(GV);
226
227 printOffset(MO.getOffset());
228
229 if (isThreadLocal) {
230 TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
231 switch (model) {
232 case TLSModel::GeneralDynamic:
233 O << "@TLSGD";
234 break;
235 case TLSModel::LocalDynamic:
236 // O << "@TLSLD"; // local dynamic not implemented
237 O << "@TLSGD";
238 break;
239 case TLSModel::InitialExec:
240 if (Subtarget->is64Bit()) {
241 assert (!NotRIPRel);
242 O << "@GOTTPOFF(%rip)";
243 } else {
244 O << "@INDNTPOFF";
245 }
246 break;
247 case TLSModel::LocalExec:
248 if (Subtarget->is64Bit())
249 O << "@TPOFF";
250 else
251 O << "@NTPOFF";
252 break;
253 default:
254 assert (0 && "Unknown TLS model");
255 }
256 } else if (isMemOp) {
257 if (shouldPrintGOT(TM, Subtarget)) {
258 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
259 O << "@GOT";
260 else
261 O << "@GOTOFF";
262 } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
263 if (TM.getRelocationModel() != Reloc::Static) {
264 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
265 O << "@GOTPCREL";
266
267 if (needCloseParen) {
268 needCloseParen = false;
269 O << ')';
270 }
271 }
272
273 // Use rip when possible to reduce code size, except when
274 // index or base register are also part of the address. e.g.
275 // foo(%rip)(%rcx,%rax,4) is not legal
276 O << "(%rip)";
277 }
278 }
279
280 if (needCloseParen)
281 O << ')';
282
283 return;
284 }
285 case MachineOperand::MO_ExternalSymbol: {
286 bool isCallOp = Modifier && !strcmp(Modifier, "call");
287 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
288 bool needCloseParen = false;
289 std::string Name(TAI->getGlobalPrefix());
290 Name += MO.getSymbolName();
291 // Print function stub suffix unless it's Mac OS X 10.5 and up.
292 if (isCallOp && shouldPrintStub(TM, Subtarget) &&
293 !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
294 FnStubs.insert(Name);
295 printSuffixedName(Name, "$stub");
296 return;
297 }
298 if (!isMemOp && !isCallOp)
299 O << '$';
300 else if (Name[0] == '$') {
301 // The name begins with a dollar-sign. In order to avoid having it look
302 // like an integer immediate to the assembler, enclose it in parens.
303 O << '(';
304 needCloseParen = true;
305 }
306
307 O << Name;
308
309 if (shouldPrintPLT(TM, Subtarget)) {
310 std::string GOTName(TAI->getGlobalPrefix());
311 GOTName+="_GLOBAL_OFFSET_TABLE_";
312 if (Name == GOTName)
313 // HACK! Emit extra offset to PC during printing GOT offset to
314 // compensate for the size of popl instruction. The resulting code
315 // should look like:
316 // call .piclabel
317 // piclabel:
318 // popl %some_register
319 // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
320 O << " + [.-"
321 << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
322
323 if (isCallOp)
324 O << "@PLT";
325 }
326
327 if (needCloseParen)
328 O << ')';
329
330 if (!isCallOp && Subtarget->isPICStyleRIPRel())
331 O << "(%rip)";
332
333 return;
334 }
335 default:
336 O << "<unknown operand type>"; return;
337 }
338#endif
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000339}
340
341void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op,
342 const char *Modifier,
343 bool NotRIPRel) {
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000344 const MCOperand &BaseReg = MI->getOperand(Op);
345 const MCOperand &IndexReg = MI->getOperand(Op+2);
346 const MCOperand &DispSpec = MI->getOperand(Op+3);
347
348 NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
349 if (DispSpec.isImm()) {
350 int64_t DispVal = DispSpec.getImm();
351 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
352 O << DispVal;
353 } else {
354 abort();
355 //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
356 // DispSpec.isJTI() || DispSpec.isSymbol());
357 //printOperand(MI, Op+3, "mem", NotRIPRel);
358 }
359
360 if (IndexReg.getReg() || BaseReg.getReg()) {
361 unsigned ScaleVal = MI->getOperand(Op+1).getImm();
362 unsigned BaseRegOperand = 0, IndexRegOperand = 2;
363
364 // There are cases where we can end up with ESP/RSP in the indexreg slot.
365 // If this happens, swap the base/index register to support assemblers that
366 // don't work when the index is *SP.
367 // FIXME: REMOVE THIS.
368 if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) {
369 assert(ScaleVal == 1 && "Scale not supported for stack pointer!");
370 abort();
371 //std::swap(BaseReg, IndexReg);
372 //std::swap(BaseRegOperand, IndexRegOperand);
373 }
374
375 O << '(';
376 if (BaseReg.getReg())
377 printOperand(MI, Op+BaseRegOperand, Modifier);
378
379 if (IndexReg.getReg()) {
380 O << ',';
381 printOperand(MI, Op+IndexRegOperand, Modifier);
382 if (ScaleVal != 1)
383 O << ',' << ScaleVal;
384 }
385 O << ')';
386 }
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000387}
388
389void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op,
390 const char *Modifier, bool NotRIPRel){
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000391#if 0
392 assert(isMem(MI, Op) && "Invalid memory reference!");
393 MachineOperand Segment = MI->getOperand(Op+4);
394 if (Segment.getReg()) {
395 printOperand(MI, Op+4, Modifier);
396 O << ':';
397 }
398 printLeaMemReference(MI, Op, Modifier, NotRIPRel);
399#endif
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000400}