diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 2830a26..8c9c09e 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -566,6 +566,7 @@ public: /// is called and is successful, the created engine takes ownership of the /// memory manager. This option defaults to NULL. EngineBuilder &setMCJITMemoryManager(std::unique_ptr mcjmm); + EngineBuilder &setMCJITMemoryManager(std::shared_ptr mcjmm); EngineBuilder& setMemoryManager(std::unique_ptr MM); diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 9bf440e..4f0250c 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -29,6 +29,7 @@ class MCExpr; class MCInst; class MCInstPrinter; class raw_ostream; +class DebugLoc; /// \brief Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. @@ -160,6 +161,7 @@ class MCInst { unsigned Opcode = 0; SMLoc Loc; SmallVector Operands; + const DebugLoc *DbgLoc = nullptr; public: MCInst() = default; @@ -170,6 +172,9 @@ public: void setLoc(SMLoc loc) { Loc = loc; } SMLoc getLoc() const { return Loc; } + void setDebugLoc(const DebugLoc *Loc) { DbgLoc = Loc; } + const DebugLoc *getDebugLoc() const { return DbgLoc; } + const MCOperand &getOperand(unsigned i) const { return Operands[i]; } MCOperand &getOperand(unsigned i) { return Operands[i]; } unsigned getNumOperands() const { return Operands.size(); } diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 80f1f32..e5056cb 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -26,6 +26,7 @@ class MCInstrInfo { const unsigned *InstrNameIndices; // Array for name indices in InstrNameData const char *InstrNameData; // Instruction name string pool unsigned NumOpcodes; // Number of entries in the desc array + unsigned long HQEMUExitAddr; public: /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines. @@ -52,6 +53,9 @@ public: assert(Opcode < NumOpcodes && "Invalid opcode!"); return StringRef(&InstrNameData[InstrNameIndices[Opcode]]); } + + void setHQEMUExitAddr(unsigned long Addr) { HQEMUExitAddr = Addr; } + unsigned long getHQEMUExitAddr() const { return HQEMUExitAddr; } }; } // End llvm namespace diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index 3c439e6..536e776 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -169,6 +169,12 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF, MachineModuleInfo *mmi, MachineLoopInfo *mli, bool AfterPlacement) { if (!tii) return false; + if (MF.getFunction()->hasFnAttribute("hqemu")) { + switch (MF.getTarget().getTargetTriple().getArch()) { + case Triple::x86: case Triple::x86_64: break; + default: return false; + } + } TriedMerging.clear(); diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 2ee72f9..701c21b 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -496,6 +496,13 @@ EngineBuilder &EngineBuilder::setMCJITMemoryManager( return *this; } +EngineBuilder &EngineBuilder::setMCJITMemoryManager( + std::shared_ptr mcjmm) { + MemMgr = mcjmm; + Resolver = mcjmm; + return *this; +} + EngineBuilder& EngineBuilder::setMemoryManager(std::unique_ptr MM) { MemMgr = std::shared_ptr(std::move(MM)); diff --git a/lib/Target/AArch64/AArch64MCInstLower.cpp b/lib/Target/AArch64/AArch64MCInstLower.cpp index f82b9db..c42ac7f 100644 --- a/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -219,6 +219,9 @@ bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); + if (MI->getDebugLoc()) + OutMI.setDebugLoc(&MI->getDebugLoc()); + for (const MachineOperand &MO : MI->operands()) { MCOperand MCOp; if (lowerOperand(MO, MCOp)) diff --git a/lib/Target/AArch64/AArch64RegisterInfo.cpp b/lib/Target/AArch64/AArch64RegisterInfo.cpp index 9f7dcb3..0e56bb6 100644 --- a/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -130,6 +130,12 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { if (hasBasePointer(MF)) markSuperRegs(Reserved, AArch64::W19); + // Reserve registers for HQEMU. + if (MF.getFunction()->hasFnAttribute("hqemu")) { + markSuperRegs(Reserved, AArch64::W19); + markSuperRegs(Reserved, AArch64::W28); + } + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp index 33698d2..9735e88 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/IR/DebugLoc.h" #include #include @@ -180,6 +181,10 @@ public: unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const; + bool EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + private: uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; void verifyInstructionPredicates(const MCInst &MI, @@ -552,9 +557,85 @@ unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, return EncodedValue & ~(1u << 30); } +bool AArch64MCCodeEmitter:: +EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + /* NOTE: the following flags must be synchronized with those in file + * llvm-opc.h of the HQEMU source tree. */ + enum { + PATCH_HQEMU = 0x4182U, + PATCH_DUMMY, + PATCH_EXIT_TB, + PATCH_DIRECT_JUMP, + PATCH_TRACE_BLOCK_CHAINING, + PATCH_QMMU + }; + + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + case AArch64::BRK: + case AArch64::RET: + break; + default: return false; + } + + const DebugLoc *Loc = MI.getDebugLoc(); + if (!Loc) + return false; + + unsigned PatchType = Loc->getLine(); + if (PatchType < PATCH_HQEMU || PatchType > PATCH_QMMU) + return false; + + if (Opcode == AArch64::BRK) { + uint64_t Binary = 0; + MCOperand Operand = MCOperand::createImm(1); + MCInst Jump; + + Jump.setOpcode(AArch64::B); + Jump.addOperand(Operand); + Binary = getBinaryCodeForInstr(Jump, Fixups, STI); + support::endian::Writer(OS).write(Binary); + ++MCNumEmitted; + return true; + } + if (Opcode == AArch64::RET) { + uint64_t ExitAddr = MCII.getHQEMUExitAddr(); + uint32_t Binary[4]; + MCOperand Reg = MCOperand::createReg(AArch64::X1); + MCInst Jump, Mov; + + // mov w0, ExitAddr[15:0] + Binary[0] = (0x2 << 29) | 0x1; + Binary[0] |= (0x25 << 23); + Binary[0] |= ((ExitAddr & 0xFFFF) << 5); + + // movk w0, ExitAddr[31:16] + Binary[1] = (0x3 << 29) | 0x1; + Binary[1] |= (0x25 << 23); + Binary[1] |= (0x1 << 21); + Binary[1] |= ((ExitAddr & 0xFFFF0000) >> 11); + + Jump.setOpcode(AArch64::BR); + Jump.addOperand(Reg); + Binary[2] = getBinaryCodeForInstr(Jump, Fixups, STI); + + for (int i = 0; i < 3; ++i) { + support::endian::Writer(OS).write(Binary[i]); + ++MCNumEmitted; + } + return true; + } + return false; +} + void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + if (EmitHQEMUInstruction(MI, OS, Fixups, STI)) + return; + verifyInstructionPredicates(MI, computeAvailableFeatures(STI.getFeatureBits())); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index 92c8c22..befec89 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/IR/DebugLoc.h" #include #include @@ -109,9 +110,16 @@ public: SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + bool EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override { + if (EmitHQEMUInstruction(MI, OS, Fixups, STI)) + return; + verifyInstructionPredicates(MI, computeAvailableFeatures(STI.getFeatureBits())); @@ -386,5 +394,75 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, return MO.getImm(); } +bool PPCMCCodeEmitter:: +EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + /* NOTE: the following flags must be synchronized with those in file + * llvm-opc.h of the HQEMU source tree. */ + enum { + PATCH_HQEMU = 0x4182U, + PATCH_DUMMY, + PATCH_EXIT_TB, + PATCH_DIRECT_JUMP, + PATCH_TRACE_BLOCK_CHAINING, + PATCH_QMMU + }; + + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + case PPC::TRAP: + case PPC::BLR: + case PPC::BLR8: + break; + default: return false; + } + + const DebugLoc *Loc = MI.getDebugLoc(); + if (!Loc) + return false; + + unsigned PatchType = Loc->getLine(); + if (PatchType < PATCH_HQEMU || PatchType > PATCH_QMMU) + return false; + + if (Opcode == PPC::TRAP) { + uint64_t Bits = 0; + MCInst NopInst; + NopInst.setOpcode(PPC::NOP); + Bits = getBinaryCodeForInstr(NopInst, Fixups, STI); + for (unsigned i = 0; i != 5; ++i) { + if (IsLittleEndian) { + support::endian::Writer(OS).write(Bits); + } else { + support::endian::Writer(OS).write(Bits); + } + } + MCNumEmitted += 5; + return true; + } + if (Opcode == PPC::BLR || Opcode == PPC::BLR8) { + uint64_t Bits[2]; + MCInst Inst[2]; + Inst[0].setOpcode(PPC::MTCTR); + Inst[0].addOperand(MCOperand::createReg(PPC::R31)); + Inst[1].setOpcode(PPC::BCTR); + Bits[0] = getBinaryCodeForInstr(Inst[0], Fixups, STI); + Bits[1] = getBinaryCodeForInstr(Inst[1], Fixups, STI); + + if (IsLittleEndian) { + support::endian::Writer(OS).write(Bits[0]); + support::endian::Writer(OS).write(Bits[1]); + } else { + support::endian::Writer(OS).write(Bits[0]); + support::endian::Writer(OS).write(Bits[1]); + } + + MCNumEmitted += 2; + return true; + } + return false; +} + #define ENABLE_INSTR_PREDICATE_VERIFIER #include "PPCGenMCCodeEmitter.inc" diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index b3a3c73..05c8cac 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2422,10 +2422,11 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, EVT PtrVT = Op.getValueType(); ConstantPoolSDNode *CP = cast(Op); const Constant *C = CP->getConstVal(); + bool isHQEMU = DAG.getMachineFunction().getFunction()->hasFnAttribute("hqemu"); // 64-bit SVR4 ABI code is always position-independent. // The actual address of the GlobalValue is stored in the TOC. - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64() && !isHQEMU) { setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0); return getTOCEntry(DAG, SDLoc(CP), true, GA); @@ -2435,7 +2436,7 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, bool IsPIC = isPositionIndependent(); getLabelAccessInfo(IsPIC, Subtarget, MOHiFlag, MOLoFlag); - if (IsPIC && Subtarget.isSVR4ABI()) { + if (IsPIC && Subtarget.isSVR4ABI() && !isHQEMU) { SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), PPCII::MO_PIC_FLAG); return getTOCEntry(DAG, SDLoc(CP), false, GA); @@ -2500,10 +2501,11 @@ PPCTargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF, SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast(Op); + bool isHQEMU = DAG.getMachineFunction().getFunction()->hasFnAttribute("hqemu"); // 64-bit SVR4 ABI code is always position-independent. // The actual address of the GlobalValue is stored in the TOC. - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64() && !isHQEMU) { setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); return getTOCEntry(DAG, SDLoc(JT), true, GA); @@ -2513,7 +2515,7 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { bool IsPIC = isPositionIndependent(); getLabelAccessInfo(IsPIC, Subtarget, MOHiFlag, MOLoFlag); - if (IsPIC && Subtarget.isSVR4ABI()) { + if (IsPIC && Subtarget.isSVR4ABI() && !isHQEMU) { SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, PPCII::MO_PIC_FLAG); return getTOCEntry(DAG, SDLoc(GA), false, GA); @@ -2529,10 +2531,11 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, EVT PtrVT = Op.getValueType(); BlockAddressSDNode *BASDN = cast(Op); const BlockAddress *BA = BASDN->getBlockAddress(); + bool isHQEMU = DAG.getMachineFunction().getFunction()->hasFnAttribute("hqemu"); // 64-bit SVR4 ABI code is always position-independent. // The actual BlockAddress is stored in the TOC. - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64() && !isHQEMU) { setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); return getTOCEntry(DAG, SDLoc(BASDN), true, GA); @@ -2642,10 +2645,11 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, GlobalAddressSDNode *GSDN = cast(Op); SDLoc DL(GSDN); const GlobalValue *GV = GSDN->getGlobal(); + bool isHQEMU = DAG.getMachineFunction().getFunction()->hasFnAttribute("hqemu"); // 64-bit SVR4 ABI code is always position-independent. // The actual address of the GlobalValue is stored in the TOC. - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64() && !isHQEMU) { setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset()); return getTOCEntry(DAG, DL, true, GA); @@ -2655,7 +2659,7 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, bool IsPIC = isPositionIndependent(); getLabelAccessInfo(IsPIC, Subtarget, MOHiFlag, MOLoFlag, GV); - if (IsPIC && Subtarget.isSVR4ABI()) { + if (IsPIC && Subtarget.isSVR4ABI() && !isHQEMU) { SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset(), PPCII::MO_PIC_FLAG); diff --git a/lib/Target/PowerPC/PPCMCInstLower.cpp b/lib/Target/PowerPC/PPCMCInstLower.cpp index b310493..afc6c81 100644 --- a/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -141,7 +141,10 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP, bool isDarwin) { OutMI.setOpcode(MI->getOpcode()); - + + if (MI->getDebugLoc()) + OutMI.setDebugLoc(&MI->getDebugLoc()); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 9207165..286c2cb 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -269,6 +269,13 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { IE = PPC::VRRCRegClass.end(); I != IE; ++I) markSuperRegs(Reserved, *I); + // Reserve registers for HQEMU. + if (MF.getFunction()->hasFnAttribute("hqemu")) { + markSuperRegs(Reserved, PPC::R27); + if (TM.isPPC64()) + markSuperRegs(Reserved, PPC::R31); + } + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } @@ -882,6 +889,11 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (!MF.getFunction()->hasFnAttribute(Attribute::Naked)) { if (!(hasBasePointer(MF) && FrameIndex < 0)) Offset += MFI.getStackSize(); + } else { + if (MF.getFunction()->hasFnAttribute("hqemu") && FrameIndex >= 0) { + const PPCFrameLowering *TFI = getFrameLowering(MF); + Offset += TFI->determineFrameLayout(MF, false, false); + } } // If we can, encode the offset directly into the instruction. If this is a diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 10e2bbc..e6e6a66 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/IR/DebugLoc.h" #include #include #include @@ -150,6 +151,9 @@ public: const MCInst &MI, const MCInstrDesc &Desc, const MCSubtargetInfo &STI, raw_ostream &OS) const; + bool EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups) const; + uint8_t DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, int MemOperand, const MCInstrDesc &Desc) const; }; @@ -1152,6 +1156,52 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, return Ret; } +bool X86MCCodeEmitter:: +EmitHQEMUInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups) const { + /* NOTE: the following flags must be synchronized with those in file + * llvm-opc.h of the HQEMU source tree. */ + enum { + PATCH_HQEMU = 0x4182U, + PATCH_DUMMY, + PATCH_EXIT_TB, + PATCH_DIRECT_JUMP, + PATCH_TRACE_BLOCK_CHAINING, + PATCH_QMMU + }; + + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + case X86::TRAP: + case X86::RETQ: + break; + default: return false; + } + + unsigned CurByte = 0; + const DebugLoc *Loc = MI.getDebugLoc(); + if (!Loc) + return false; + + unsigned PatchType = Loc->getLine(); + if (PatchType < PATCH_HQEMU || PatchType > PATCH_QMMU) + return false; + + if (Opcode == X86::TRAP) { + for (unsigned i = 0; i != 8; ++i) + EmitByte(0x90, CurByte, OS); + return true; + } + if (Opcode == X86::RETQ) { + uintptr_t ExitAddr = MCII.getHQEMUExitAddr(); + EmitByte(0xE9, CurByte, OS); + EmitImmediate(MCOperand::createImm(ExitAddr), MI.getLoc(), 4, FK_PCRel_4, + CurByte, OS, Fixups); + return true; + } + return false; +} + void X86MCCodeEmitter:: encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, @@ -1160,6 +1210,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; + if (EmitHQEMUInstruction(MI, OS, Fixups)) + return; + // Pseudo instructions don't get encoded. if ((TSFlags & X86II::FormMask) == X86II::Pseudo) return; diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index f294e81..10a22ae 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -83,6 +83,10 @@ X86FrameLowering::needsFrameIndexResolution(const MachineFunction &MF) const { /// or if frame pointer elimination is disabled. bool X86FrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo &MFI = MF.getFrameInfo(); + // HQEMU does not use FramePtr for stack accesses, so return false when + // running in HQEMU mode. + if (MF.getFunction()->hasFnAttribute("hqemu")) + return false; return (MF.getTarget().Options.DisableFramePointerElim(MF) || TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index fd2837b..51d6e5b 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -389,6 +389,9 @@ X86MCInstLower::LowerMachineOperand(const MachineInstr *MI, void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); + if (MI->getDebugLoc()) + OutMI.setDebugLoc(&MI->getDebugLoc()); + for (const MachineOperand &MO : MI->operands()) if (auto MaybeMCOp = LowerMachineOperand(MI, MO)) OutMI.addOperand(MaybeMCOp.getValue()); diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 343da25..72550a0 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -573,6 +573,20 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { } } + // Reserve registers for HQEMU. + if (MF.getFunction()->hasFnAttribute("hqemu")) { + if (!Is64Bit) { + Reserved.set(X86::EBP); + Reserved.set(X86::BP); + Reserved.set(X86::BPL); + } else { + Reserved.set(X86::R14); + Reserved.set(X86::R14B); + Reserved.set(X86::R14D); + Reserved.set(X86::R14W); + } + } + assert(checkAllSuperRegsMarked(Reserved, {X86::SIL, X86::DIL, X86::BPL, X86::SPL})); return Reserved; diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 7461061..cb2e665 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -1531,7 +1531,8 @@ static bool markAliveBlocks(Function &F, Changed = true; break; } - if (CI->doesNotReturn()) { + // Do not delete instructions after llvm.trap in HQEMU mode. + if (!F.hasFnAttribute("hqemu") && CI->doesNotReturn()) { // If we found a call to a no-return function, insert an unreachable // instruction after it. Make sure there isn't *already* one there // though. diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 8784b97..c4cf1cc 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1250,6 +1250,10 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, bool Changed = false; do { + // Do not hoist llvm::trap and debug instructions in HQEMU mode. + if (BIParent->getParent()->hasFnAttribute("hqemu")) + if (isa(I1) || I1->hasMetadata()) + return Changed; // If we are hoisting the terminator instruction, don't move one (making a // broken BB), instead clone it, and remove BI. if (isa(I1)) @@ -5542,6 +5546,10 @@ bool SimplifyCFGOpt::SimplifyIndirectBr(IndirectBrInst *IBI) { BasicBlock *BB = IBI->getParent(); bool Changed = false; + // Do not delete indirectbrs of no successors in HQEMU mode. + if (BB->getParent()->hasFnAttribute("hqemu")) + return false; + // Eliminate redundant destinations. SmallPtrSet Succs; for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) {