eliminate the "call" operand modifier from the asm descriptions, modeling

it as a pcrel immediate instead.  This gets pc-rel weirdness out of the
main printoperand codepath.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73829 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-06-20 19:34:09 +00:00
parent 434ca80b31
commit 7680e73341
7 changed files with 223 additions and 55 deletions

View File

@ -296,6 +296,136 @@ static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) {
return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static;
}
/// 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 MachineInstr *MI, unsigned OpNo) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: assert(0 && "Unknown pcrel immediate operand");
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
return;
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
bool needCloseParen = false;
if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
// like an integer immediate to the assembler, enclose it in parens.
O << '(';
needCloseParen = true;
}
if (shouldPrintStub(TM, Subtarget)) {
// Link-once, declaration, or Weakly-linked global variables need
// non-lazily-resolved stubs
if (GV->isDeclaration() || GV->isWeakForLinker()) {
// Dynamically-resolved functions need a stub for the function.
if (isa<Function>(GV)) {
// Function stubs are no longer needed for Mac OS X 10.5 and up.
if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
O << Name;
} else {
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
}
} else if (GV->hasHiddenVisibility()) {
if (!GV->isDeclaration() && !GV->hasCommonLinkage())
// Definition is not definitely in the current translation unit.
O << Name;
else {
HiddenGVStubs.insert(Name);
printSuffixedName(Name, "$non_lazy_ptr");
}
} else {
GVStubs.insert(Name);
printSuffixedName(Name, "$non_lazy_ptr");
}
} else {
if (GV->hasDLLImportLinkage())
O << "__imp_";
O << Name;
}
} else {
if (GV->hasDLLImportLinkage()) {
O << "__imp_";
}
O << Name;
if (shouldPrintPLT(TM, Subtarget)) {
// Assemble call via PLT for externally visible symbols
if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
!GV->hasLocalLinkage())
O << "@PLT";
}
if (Subtarget->isTargetCygMing() && GV->isDeclaration())
// Save function name for later type emission
FnStubs.insert(Name);
}
if (GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
printOffset(MO.getOffset());
if (needCloseParen)
O << ')';
return;
}
case MachineOperand::MO_ExternalSymbol: {
bool needCloseParen = false;
std::string Name(TAI->getGlobalPrefix());
Name += MO.getSymbolName();
// Print function stub suffix unless it's Mac OS X 10.5 and up.
if (shouldPrintStub(TM, Subtarget) &&
!(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
return;
}
if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
// like an integer immediate to the assembler, enclose it in parens.
O << '(';
needCloseParen = true;
}
O << Name;
if (shouldPrintPLT(TM, Subtarget)) {
std::string GOTName(TAI->getGlobalPrefix());
GOTName+="_GLOBAL_OFFSET_TABLE_";
if (Name == GOTName)
// HACK! Emit extra offset to PC during printing GOT offset to
// compensate for the size of popl instruction. The resulting code
// should look like:
// call .piclabel
// piclabel:
// popl %some_register
// addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
O << " + [.-"
<< getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
O << "@PLT";
}
if (needCloseParen)
O << ')';
return;
}
}
}
void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier, bool NotRIPRel) {
const MachineOperand &MO = MI->getOperand(OpNo);
@ -317,12 +447,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
case MachineOperand::MO_Immediate:
if (!Modifier || (strcmp(Modifier, "debug") &&
strcmp(Modifier, "mem") &&
strcmp(Modifier, "call")))
strcmp(Modifier, "mem")))
O << '$';
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
// FIXME: REMOVE
assert(0 && "labels should only be used as pc-relative values");
printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
return;
case MachineOperand::MO_JumpTableIndex: {
@ -364,7 +495,6 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
return;
}
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
bool needCloseParen = false;
@ -382,7 +512,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
if (!isMemOp && !isCallOp)
if (!isMemOp)
O << '$';
else if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
@ -396,15 +526,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
// non-lazily-resolved stubs
if (GV->isDeclaration() || GV->isWeakForLinker()) {
// Dynamically-resolved functions need a stub for the function.
if (isCallOp && isa<Function>(GV)) {
// Function stubs are no longer needed for Mac OS X 10.5 and up.
if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
O << Name;
} else {
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
}
} else if (GV->hasHiddenVisibility()) {
if (GV->hasHiddenVisibility()) {
if (!GV->isDeclaration() && !GV->hasCommonLinkage())
// Definition is not definitely in the current translation unit.
O << Name;
@ -422,25 +544,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
O << Name;
}
if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
if (TM.getRelocationModel() == Reloc::PIC_)
O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
} else {
if (GV->hasDLLImportLinkage()) {
O << "__imp_";
}
O << Name;
if (isCallOp) {
if (shouldPrintPLT(TM, Subtarget)) {
// Assemble call via PLT for externally visible symbols
if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
!GV->hasLocalLinkage())
O << "@PLT";
}
if (Subtarget->isTargetCygMing() && GV->isDeclaration())
// Save function name for later type emission
FnStubs.insert(Name);
}
}
if (GV->hasExternalWeakLinkage())
@ -505,19 +615,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
return;
}
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
bool needCloseParen = false;
std::string Name(TAI->getGlobalPrefix());
Name += MO.getSymbolName();
// Print function stub suffix unless it's Mac OS X 10.5 and up.
if (isCallOp && shouldPrintStub(TM, Subtarget) &&
!(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
return;
}
if (!isMemOp && !isCallOp)
if (!isMemOp)
O << '$';
else if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
@ -541,17 +645,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
// addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
O << " + [.-"
<< getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
if (isCallOp)
O << "@PLT";
}
if (needCloseParen)
O << ')';
if (!isCallOp && Subtarget->isPICStyleRIPRel())
if (Subtarget->isPICStyleRIPRel())
O << "(%rip)";
return;
}
default:

View File

@ -74,7 +74,8 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
void printLeaMemReference(const MCInst *MI, unsigned Op);
void printSSECC(const MCInst *MI, unsigned Op);
void printPICLabel(const MCInst *MI, unsigned Op);
void print_pcrel_imm(const MCInst *MI, unsigned OpNo);
void printi8mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
@ -117,6 +118,7 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
// These methods are used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier = 0, bool NotRIPRel = false);
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}

View File

@ -46,6 +46,24 @@ void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
}
/// 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
assert(0 && "Unknown pcrel immediate operand");
}
void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
const char *Modifier, bool NotRIPRel) {
assert(Modifier == 0 && "Modifiers should not be used");
@ -71,6 +89,7 @@ void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << Op.getImm();
return;
} else if (Op.isMBBLabel()) {
assert(0 && "labels should only be used as pc-relative values");
// FIXME: Keep in sync with printBasicBlockLabel. printBasicBlockLabel
// should eventually call into this code, not the other way around.
@ -109,9 +128,6 @@ void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << '$';
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
return;
case MachineOperand::MO_JumpTableIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp) O << '$';
@ -389,7 +405,6 @@ void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
}
void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
//assert(isMem(MI, Op) && "Invalid memory reference!");
const MCOperand &Segment = MI->getOperand(Op+4);
if (Segment.getReg()) {
printOperand(MI, Op+4);

View File

@ -224,6 +224,8 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
// FIXME: REMOVE
assert(0 && "labels should only be used as pc-relative values");
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_JumpTableIndex: {
@ -243,14 +245,13 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
return;
}
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
if (!isMemOp && !isCallOp) O << "OFFSET ";
if (!isMemOp) O << "OFFSET ";
if (GV->hasDLLImportLinkage()) {
// FIXME: This should be fixed with full support of stdcall & fastcall
// CC's
@ -261,8 +262,6 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
return;
}
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
if (!isCallOp) O << "OFFSET ";
O << TAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
@ -271,6 +270,39 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
}
}
void X86IntelAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo){
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: assert(0 && "Unknown pcrel immediate operand");
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_GlobalAddress: {
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
if (GV->hasDLLImportLinkage()) {
// FIXME: This should be fixed with full support of stdcall & fastcall
// CC's
O << "__imp_";
}
O << Name;
printOffset(MO.getOffset());
return;
}
case MachineOperand::MO_ExternalSymbol:
O << TAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
}
void X86IntelAsmPrinter::printLeaMemReference(const MachineInstr *MI,
unsigned Op,
const char *Modifier) {

View File

@ -52,6 +52,9 @@ struct VISIBILITY_HIDDEN X86IntelAsmPrinter : public AsmPrinter {
printOp(MO, Modifier);
}
}
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
O << "BYTE PTR ";

View File

@ -19,6 +19,14 @@
// 64-bits but only 32 bits are significant.
def i64i32imm : Operand<i64>;
// 64-bits but only 32 bits are significant, and those bits are treated as being
// pc relative.
def i64i32imm_pcrel : Operand<i64> {
let PrintMethod = "print_pcrel_imm";
}
// 64-bits but only 8 bits are significant.
def i64i8imm : Operand<i64>;
@ -115,8 +123,8 @@ let isCall = 1 in
// that the offset between an arbitrary immediate and the call will fit in
// the 32-bit pcrel field that we have.
def CALL64pcrel32 : Ii32<0xE8, RawFrm,
(outs), (ins i64i32imm:$dst, variable_ops),
"call\t${dst:call}", []>,
(outs), (ins i64i32imm_pcrel:$dst, variable_ops),
"call\t$dst", []>,
Requires<[In64BitMode]>;
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops),
"call\t{*}$dst", [(X86call GR64:$dst)]>;

View File

@ -163,6 +163,11 @@ def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;
// X86 Operand Definitions.
//
def i32imm_pcrel : Operand<i32> {
let PrintMethod = "print_pcrel_imm";
}
// *mem - Operand definitions for the funky X86 addressing mode operands.
//
class X86MemOperand<string printMethod> : Operand<iPTR> {
@ -206,8 +211,10 @@ def i16i8imm : Operand<i16>;
// 32-bits but only 8 bits are significant.
def i32i8imm : Operand<i32>;
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT>;
// Branch targets have OtherVT type and print as pc-relative values.
def brtarget : Operand<OtherVT> {
let PrintMethod = "print_pcrel_imm";
}
//===----------------------------------------------------------------------===//
// X86 Complex Pattern Definitions.
@ -561,8 +568,9 @@ let isCall = 1 in
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
Uses = [ESP] in {
def CALLpcrel32 : Ii32<0xE8, RawFrm, (outs), (ins i32imm:$dst,variable_ops),
"call\t${dst:call}", []>;
def CALLpcrel32 : Ii32<0xE8, RawFrm,
(outs), (ins i32imm_pcrel:$dst,variable_ops),
"call\t$dst", []>;
def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
"call\t{*}$dst", [(X86call GR32:$dst)]>;
def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops),
@ -587,7 +595,7 @@ def TCRETURNri : I<0, Pseudo, (outs), (ins GR32:$dst, i32imm:$offset, variable_o
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TAILJMPd : IBr<0xE9, (ins i32imm:$dst), "jmp\t${dst:call} # TAILCALL",
def TAILJMPd : IBr<0xE9, (ins i32imm_pcrel:$dst), "jmp\t$dst # TAILCALL",
[]>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TAILJMPr : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst # TAILCALL",