From: Chris Lattner Date: Sat, 20 Jun 2009 19:34:09 +0000 (+0000) Subject: eliminate the "call" operand modifier from the asm descriptions, modeling X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=7680e733415e01a30183a73bfbe16f7829439db7;p=oota-llvm.git 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 --- diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index 05f3b6dce2f..559af1bdc16 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -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(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(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: diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h index 2f28cf56b3c..68a6bc80ceb 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h @@ -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); } diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp index 54de7e9dd20..64d523fb499 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -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); diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp index 5b1733e6816..73cafce7f88 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp @@ -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) { diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h index 9520d982f69..04f25955117 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h @@ -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 "; diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index f2821287e6f..0544d362c3d 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -19,6 +19,14 @@ // 64-bits but only 32 bits are significant. def i64i32imm : Operand; + +// 64-bits but only 32 bits are significant, and those bits are treated as being +// pc relative. +def i64i32imm_pcrel : Operand { + let PrintMethod = "print_pcrel_imm"; +} + + // 64-bits but only 8 bits are significant. def i64i8imm : Operand; @@ -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)]>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index b0e74336bdd..7ece204b888 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -163,6 +163,11 @@ def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; // X86 Operand Definitions. // +def i32imm_pcrel : Operand { + let PrintMethod = "print_pcrel_imm"; +} + + // *mem - Operand definitions for the funky X86 addressing mode operands. // class X86MemOperand : Operand { @@ -206,8 +211,10 @@ def i16i8imm : Operand; // 32-bits but only 8 bits are significant. def i32i8imm : Operand; -// Branch targets have OtherVT type. -def brtarget : Operand; +// Branch targets have OtherVT type and print as pc-relative values. +def brtarget : Operand { + 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",