1 //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file includes code for rendering MCInst instances as AT&T-style
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
16 #include "llvm/MC/MCInst.h"
17 #include "X86ATTAsmPrinter.h"
18 #include "llvm/Support/raw_ostream.h"
21 // Include the auto-generated portion of the assembly writer.
22 #define MachineInstr MCInst
23 #define NO_ASM_WRITER_BOILERPLATE
24 #include "X86GenAsmWriter.inc"
27 void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
28 unsigned char value = MI->getOperand(Op).getImm();
29 assert(value <= 7 && "Invalid ssecc argument!");
31 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;
43 void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
45 "This is only used for MOVPC32r, should lower before asm printing!");
49 void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
50 const char *Modifier, bool NotRIPRel) {
51 //assert(Modifier == 0 && "Modifiers should not be used");
53 const MCOperand &Op = MI->getOperand(OpNo);
56 unsigned Reg = Op.getReg();
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);
65 O << TRI->getAsmName(Reg);
67 } else if (Op.isImm()) {
68 //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem") &&
69 // strcmp(Modifier, "call")))
75 O << "<<UNKNOWN OPERAND KIND>>";
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!");
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);
92 O << TRI->getAsmName(Reg);
96 case MachineOperand::MO_Immediate:
97 if (!Modifier || (strcmp(Modifier, "debug") &&
98 strcmp(Modifier, "mem") &&
99 strcmp(Modifier, "call")))
103 case MachineOperand::MO_MachineBasicBlock:
104 printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
106 case MachineOperand::MO_JumpTableIndex: {
107 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
108 if (!isMemOp) O << '$';
109 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
112 if (TM.getRelocationModel() == Reloc::PIC_) {
113 if (Subtarget->isPICStyleStub())
114 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
116 else if (Subtarget->isPICStyleGOT())
120 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
124 case MachineOperand::MO_ConstantPoolIndex: {
125 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
126 if (!isMemOp) O << '$';
127 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
130 if (TM.getRelocationModel() == Reloc::PIC_) {
131 if (Subtarget->isPICStyleStub())
132 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
134 else if (Subtarget->isPICStyleGOT())
138 printOffset(MO.getOffset());
140 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
144 case MachineOperand::MO_GlobalAddress: {
145 bool isCallOp = Modifier && !strcmp(Modifier, "call");
146 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
147 bool needCloseParen = false;
149 const GlobalValue *GV = MO.getGlobal();
150 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
152 // If GV is an alias then use the aliasee for determining
154 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
155 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
158 bool isThreadLocal = GVar && GVar->isThreadLocal();
160 std::string Name = Mang->getValueName(GV);
161 decorateName(Name, GV);
163 if (!isMemOp && !isCallOp)
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.
169 needCloseParen = true;
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) {
182 FnStubs.insert(Name);
183 printSuffixedName(Name, "$stub");
185 } else if (GV->hasHiddenVisibility()) {
186 if (!GV->isDeclaration() && !GV->hasCommonLinkage())
187 // Definition is not definitely in the current translation unit.
190 HiddenGVStubs.insert(Name);
191 printSuffixedName(Name, "$non_lazy_ptr");
194 GVStubs.insert(Name);
195 printSuffixedName(Name, "$non_lazy_ptr");
198 if (GV->hasDLLImportLinkage())
203 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
204 O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
206 if (GV->hasDLLImportLinkage()) {
212 if (shouldPrintPLT(TM, Subtarget)) {
213 // Assemble call via PLT for externally visible symbols
214 if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
215 !GV->hasLocalLinkage())
218 if (Subtarget->isTargetCygMing() && GV->isDeclaration())
219 // Save function name for later type emission
220 FnStubs.insert(Name);
224 if (GV->hasExternalWeakLinkage())
225 ExtWeakSymbols.insert(GV);
227 printOffset(MO.getOffset());
230 TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
232 case TLSModel::GeneralDynamic:
235 case TLSModel::LocalDynamic:
236 // O << "@TLSLD"; // local dynamic not implemented
239 case TLSModel::InitialExec:
240 if (Subtarget->is64Bit()) {
242 O << "@GOTTPOFF(%rip)";
247 case TLSModel::LocalExec:
248 if (Subtarget->is64Bit())
254 assert (0 && "Unknown TLS model");
256 } else if (isMemOp) {
257 if (shouldPrintGOT(TM, Subtarget)) {
258 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
262 } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
263 if (TM.getRelocationModel() != Reloc::Static) {
264 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
267 if (needCloseParen) {
268 needCloseParen = false;
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
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");
298 if (!isMemOp && !isCallOp)
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.
304 needCloseParen = true;
309 if (shouldPrintPLT(TM, Subtarget)) {
310 std::string GOTName(TAI->getGlobalPrefix());
311 GOTName+="_GLOBAL_OFFSET_TABLE_";
313 // HACK! Emit extra offset to PC during printing GOT offset to
314 // compensate for the size of popl instruction. The resulting code
318 // popl %some_register
319 // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
321 << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
330 if (!isCallOp && Subtarget->isPICStyleRIPRel())
336 O << "<unknown operand type>"; return;
341 void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op,
342 const char *Modifier,
344 const MCOperand &BaseReg = MI->getOperand(Op);
345 const MCOperand &IndexReg = MI->getOperand(Op+2);
346 const MCOperand &DispSpec = MI->getOperand(Op+3);
348 NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
349 if (DispSpec.isImm()) {
350 int64_t DispVal = DispSpec.getImm();
351 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
355 //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
356 // DispSpec.isJTI() || DispSpec.isSymbol());
357 //printOperand(MI, Op+3, "mem", NotRIPRel);
360 if (IndexReg.getReg() || BaseReg.getReg()) {
361 unsigned ScaleVal = MI->getOperand(Op+1).getImm();
362 unsigned BaseRegOperand = 0, IndexRegOperand = 2;
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!");
371 //std::swap(BaseReg, IndexReg);
372 //std::swap(BaseRegOperand, IndexRegOperand);
376 if (BaseReg.getReg())
377 printOperand(MI, Op+BaseRegOperand, Modifier);
379 if (IndexReg.getReg()) {
381 printOperand(MI, Op+IndexRegOperand, Modifier);
383 O << ',' << ScaleVal;
389 void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op,
390 const char *Modifier, bool NotRIPRel){
391 //assert(isMem(MI, Op) && "Invalid memory reference!");
392 const MCOperand &Segment = MI->getOperand(Op+4);
393 if (Segment.getReg()) {
394 printOperand(MI, Op+4, Modifier);
397 printLeaMemReference(MI, Op, Modifier, NotRIPRel);