diff options
author | Chris Lattner <sabre@nondot.org> | 2009-06-20 00:49:26 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-06-20 00:49:26 +0000 |
commit | f38c03af2a142db2777ce839026706969f3aeaa9 (patch) | |
tree | 507f434a1cca6488e8ba952ac3d64abc5d6a3feb /lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp | |
parent | bb5d44d7c496f9576e7b1fcfa3f51f544512d158 (diff) | |
download | external_llvm-f38c03af2a142db2777ce839026706969f3aeaa9.zip external_llvm-f38c03af2a142db2777ce839026706969f3aeaa9.tar.gz external_llvm-f38c03af2a142db2777ce839026706969f3aeaa9.tar.bz2 |
Start implementing translation of MachineInstr to MCInst. Next
step is to make tblgen generate something more appropriate for MCInst,
and generate calls to operand translation routines where needed.
This includes a bunch of #if 0 code which will slowly be refactored into
something sensible.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73810 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp')
-rw-r--r-- | lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp | 356 |
1 files changed, 348 insertions, 8 deletions
diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp index 934e45a..e46f7a3 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -28,14 +28,14 @@ void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) { unsigned char value = MI->getOperand(Op).getImm(); assert(value <= 7 && "Invalid ssecc argument!"); switch (value) { - 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; + 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; } } @@ -48,13 +48,353 @@ void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) { void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo, const char *Modifier, bool NotRIPRel) { + //assert(Modifier == 0 && "Modifiers should not be used"); + + 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()) { + //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem") && + // strcmp(Modifier, "call"))) + O << '$'; + O << Op.getImm(); + return; + } + + O << "<<UNKNOWN OPERAND KIND>>"; + + +#if 0 + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + case MachineOperand::MO_Register: { + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should not make it this far!"); + O << '%'; + unsigned Reg = MO.getReg(); + 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); + } + O << TRI->getAsmName(Reg); + return; + } + + case MachineOperand::MO_Immediate: + if (!Modifier || (strcmp(Modifier, "debug") && + strcmp(Modifier, "mem") && + strcmp(Modifier, "call"))) + 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 << '$'; + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' + << MO.getIndex(); + + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleStub()) + O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << "$pb\""; + else if (Subtarget->isPICStyleGOT()) + O << "@GOTOFF"; + } + + if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) + O << "(%rip)"; + return; + } + case MachineOperand::MO_ConstantPoolIndex: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + if (!isMemOp) O << '$'; + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << MO.getIndex(); + + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleStub()) + O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << "$pb\""; + else if (Subtarget->isPICStyleGOT()) + O << "@GOTOFF"; + } + + printOffset(MO.getOffset()); + + if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) + O << "(%rip)"; + return; + } + case MachineOperand::MO_GlobalAddress: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + bool needCloseParen = false; + + const GlobalValue *GV = MO.getGlobal(); + const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); + if (!GVar) { + // If GV is an alias then use the aliasee for determining + // thread-localness. + if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) + GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false)); + } + + bool isThreadLocal = GVar && GVar->isThreadLocal(); + + std::string Name = Mang->getValueName(GV); + decorateName(Name, GV); + + if (!isMemOp && !isCallOp) + O << '$'; + else 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 (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->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; + } + + if (!isCallOp && 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()) + ExtWeakSymbols.insert(GV); + + printOffset(MO.getOffset()); + + if (isThreadLocal) { + TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel()); + switch (model) { + case TLSModel::GeneralDynamic: + O << "@TLSGD"; + break; + case TLSModel::LocalDynamic: + // O << "@TLSLD"; // local dynamic not implemented + O << "@TLSGD"; + break; + case TLSModel::InitialExec: + if (Subtarget->is64Bit()) { + assert (!NotRIPRel); + O << "@GOTTPOFF(%rip)"; + } else { + O << "@INDNTPOFF"; + } + break; + case TLSModel::LocalExec: + if (Subtarget->is64Bit()) + O << "@TPOFF"; + else + O << "@NTPOFF"; + break; + default: + assert (0 && "Unknown TLS model"); + } + } else if (isMemOp) { + if (shouldPrintGOT(TM, Subtarget)) { + if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) + O << "@GOT"; + else + O << "@GOTOFF"; + } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) { + if (TM.getRelocationModel() != Reloc::Static) { + if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) + O << "@GOTPCREL"; + + if (needCloseParen) { + needCloseParen = false; + O << ')'; + } + } + + // Use rip when possible to reduce code size, except when + // index or base register are also part of the address. e.g. + // foo(%rip)(%rcx,%rax,4) is not legal + O << "(%rip)"; + } + } + + if (needCloseParen) + O << ')'; + + 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) + O << '$'; + else 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) << ']'; + + if (isCallOp) + O << "@PLT"; + } + + if (needCloseParen) + O << ')'; + + if (!isCallOp && Subtarget->isPICStyleRIPRel()) + O << "(%rip)"; + + return; + } + default: + O << "<unknown operand type>"; return; + } +#endif } void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op, const char *Modifier, bool NotRIPRel) { + const MCOperand &BaseReg = MI->getOperand(Op); + const MCOperand &IndexReg = MI->getOperand(Op+2); + const MCOperand &DispSpec = MI->getOperand(Op+3); + + NotRIPRel |= IndexReg.getReg() || BaseReg.getReg(); + if (DispSpec.isImm()) { + int64_t DispVal = DispSpec.getImm(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) + O << DispVal; + } else { + abort(); + //assert(DispSpec.isGlobal() || DispSpec.isCPI() || + // DispSpec.isJTI() || DispSpec.isSymbol()); + //printOperand(MI, Op+3, "mem", NotRIPRel); + } + + if (IndexReg.getReg() || BaseReg.getReg()) { + unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + unsigned BaseRegOperand = 0, IndexRegOperand = 2; + + // 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. + if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { + assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); + abort(); + //std::swap(BaseReg, IndexReg); + //std::swap(BaseRegOperand, IndexRegOperand); + } + + O << '('; + if (BaseReg.getReg()) + printOperand(MI, Op+BaseRegOperand, Modifier); + + if (IndexReg.getReg()) { + O << ','; + printOperand(MI, Op+IndexRegOperand, Modifier); + if (ScaleVal != 1) + O << ',' << ScaleVal; + } + O << ')'; + } } void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op, const char *Modifier, bool NotRIPRel){ +#if 0 + assert(isMem(MI, Op) && "Invalid memory reference!"); + MachineOperand Segment = MI->getOperand(Op+4); + if (Segment.getReg()) { + printOperand(MI, Op+4, Modifier); + O << ':'; + } + printLeaMemReference(MI, Op, Modifier, NotRIPRel); +#endif } |