2009-06-19 08:47:59 +08:00
|
|
|
//===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file includes code for rendering MCInst instances as AT&T-style
|
|
|
|
// assembly.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
|
|
#include "llvm/MC/MCInst.h"
|
|
|
|
#include "X86ATTAsmPrinter.h"
|
2009-06-20 15:03:18 +08:00
|
|
|
#include "llvm/Target/TargetAsmInfo.h"
|
2009-07-09 02:01:40 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-06-20 07:59:57 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-06-19 08:47:59 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2009-06-20 07:59:57 +08:00
|
|
|
// Include the auto-generated portion of the assembly writer.
|
|
|
|
#define MachineInstr MCInst
|
|
|
|
#define NO_ASM_WRITER_BOILERPLATE
|
|
|
|
#include "X86GenAsmWriter.inc"
|
|
|
|
#undef MachineInstr
|
|
|
|
|
|
|
|
void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
|
2009-06-20 15:03:18 +08:00
|
|
|
switch (MI->getOperand(Op).getImm()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Invalid ssecc argument!");
|
2009-06-20 08:49:26 +08:00
|
|
|
case 0: O << "eq"; break;
|
|
|
|
case 1: O << "lt"; break;
|
|
|
|
case 2: O << "le"; break;
|
|
|
|
case 3: O << "unord"; break;
|
|
|
|
case 4: O << "neq"; break;
|
|
|
|
case 5: O << "nlt"; break;
|
|
|
|
case 6: O << "nle"; break;
|
|
|
|
case 7: O << "ord"; break;
|
2009-06-20 07:59:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("This is only used for MOVPC32r,"
|
2009-07-14 20:22:58 +08:00
|
|
|
"should lower before asm printing!");
|
2009-06-20 07:59:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-21 03:34:09 +08:00
|
|
|
/// print_pcrel_imm - This is used to print an immediate value that ends up
|
|
|
|
/// being encoded as a pc-relative value. These print slightly differently, for
|
|
|
|
/// example, a $ is not emitted.
|
|
|
|
void X86ATTAsmPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
|
|
|
|
const MCOperand &Op = MI->getOperand(OpNo);
|
|
|
|
|
|
|
|
if (Op.isImm())
|
|
|
|
O << Op.getImm();
|
|
|
|
else if (Op.isMBBLabel())
|
|
|
|
// FIXME: Keep in sync with printBasicBlockLabel. printBasicBlockLabel
|
|
|
|
// should eventually call into this code, not the other way around.
|
|
|
|
O << TAI->getPrivateGlobalPrefix() << "BB" << Op.getMBBLabelFunction()
|
|
|
|
<< '_' << Op.getMBBLabelBlock();
|
|
|
|
else
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Unknown pcrel immediate operand");
|
2009-06-21 03:34:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-20 07:59:57 +08:00
|
|
|
void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
llvm-svn: 74372
2009-06-27 12:16:01 +08:00
|
|
|
const char *Modifier) {
|
2009-06-20 15:03:18 +08:00
|
|
|
assert(Modifier == 0 && "Modifiers should not be used");
|
2009-06-20 08:49:26 +08:00
|
|
|
|
|
|
|
const MCOperand &Op = MI->getOperand(OpNo);
|
|
|
|
if (Op.isReg()) {
|
|
|
|
O << '%';
|
|
|
|
unsigned Reg = Op.getReg();
|
|
|
|
#if 0
|
|
|
|
if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
|
|
|
|
MVT VT = (strcmp(Modifier+6,"64") == 0) ?
|
|
|
|
MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
|
|
|
|
((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
|
|
|
|
Reg = getX86SubSuperRegister(Reg, VT);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
O << TRI->getAsmName(Reg);
|
|
|
|
return;
|
|
|
|
} else if (Op.isImm()) {
|
2009-06-21 09:48:49 +08:00
|
|
|
//if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem")))
|
2009-06-20 08:49:26 +08:00
|
|
|
O << '$';
|
|
|
|
O << Op.getImm();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << "<<UNKNOWN OPERAND KIND>>";
|
2009-06-20 07:59:57 +08:00
|
|
|
}
|
|
|
|
|
2009-06-20 15:03:18 +08:00
|
|
|
void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
|
|
|
|
|
2009-06-20 08:49:26 +08:00
|
|
|
const MCOperand &BaseReg = MI->getOperand(Op);
|
|
|
|
const MCOperand &IndexReg = MI->getOperand(Op+2);
|
|
|
|
const MCOperand &DispSpec = MI->getOperand(Op+3);
|
|
|
|
|
|
|
|
if (DispSpec.isImm()) {
|
|
|
|
int64_t DispVal = DispSpec.getImm();
|
|
|
|
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
|
|
|
|
O << DispVal;
|
|
|
|
} else {
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("non-immediate displacement for LEA?");
|
2009-06-20 08:49:26 +08:00
|
|
|
//assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
|
|
|
|
// DispSpec.isJTI() || DispSpec.isSymbol());
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
llvm-svn: 74372
2009-06-27 12:16:01 +08:00
|
|
|
//printOperand(MI, Op+3, "mem");
|
2009-06-20 08:49:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IndexReg.getReg() || BaseReg.getReg()) {
|
|
|
|
// There are cases where we can end up with ESP/RSP in the indexreg slot.
|
|
|
|
// If this happens, swap the base/index register to support assemblers that
|
|
|
|
// don't work when the index is *SP.
|
|
|
|
// FIXME: REMOVE THIS.
|
2009-06-20 15:59:10 +08:00
|
|
|
assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP);
|
2009-06-20 08:49:26 +08:00
|
|
|
|
|
|
|
O << '(';
|
|
|
|
if (BaseReg.getReg())
|
2009-06-20 15:59:10 +08:00
|
|
|
printOperand(MI, Op);
|
2009-06-20 08:49:26 +08:00
|
|
|
|
|
|
|
if (IndexReg.getReg()) {
|
|
|
|
O << ',';
|
2009-06-20 15:59:10 +08:00
|
|
|
printOperand(MI, Op+2);
|
2009-06-20 16:13:12 +08:00
|
|
|
unsigned ScaleVal = MI->getOperand(Op+1).getImm();
|
|
|
|
if (ScaleVal != 1)
|
2009-06-20 08:49:26 +08:00
|
|
|
O << ',' << ScaleVal;
|
|
|
|
}
|
|
|
|
O << ')';
|
|
|
|
}
|
2009-06-20 07:59:57 +08:00
|
|
|
}
|
|
|
|
|
2009-06-20 15:03:18 +08:00
|
|
|
void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
|
2009-06-20 08:50:32 +08:00
|
|
|
const MCOperand &Segment = MI->getOperand(Op+4);
|
2009-06-20 08:49:26 +08:00
|
|
|
if (Segment.getReg()) {
|
2009-06-20 15:03:18 +08:00
|
|
|
printOperand(MI, Op+4);
|
2009-06-20 08:49:26 +08:00
|
|
|
O << ':';
|
|
|
|
}
|
2009-06-20 15:03:18 +08:00
|
|
|
printLeaMemReference(MI, Op);
|
2009-06-20 07:59:57 +08:00
|
|
|
}
|