From 9e80202352dd49bdd9e67b8b906d86f058431505 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 11 May 2019 15:12:49 -0500 Subject: Initial import of abandoned HQEMU version 2.5.2 --- src/patch/llvm/llvm-3.5.patch | 864 ++++++++++++++++++++++++++++++++++++++++++ src/patch/llvm/llvm-3.8.patch | 247 ++++++++++++ src/patch/llvm/llvm-3.9.patch | 404 ++++++++++++++++++++ src/patch/llvm/llvm-5.0.patch | 652 +++++++++++++++++++++++++++++++ src/patch/llvm/llvm-6.0.patch | 652 +++++++++++++++++++++++++++++++ 5 files changed, 2819 insertions(+) create mode 100644 src/patch/llvm/llvm-3.5.patch create mode 100644 src/patch/llvm/llvm-3.8.patch create mode 100644 src/patch/llvm/llvm-3.9.patch create mode 100644 src/patch/llvm/llvm-5.0.patch create mode 100644 src/patch/llvm/llvm-6.0.patch (limited to 'src/patch/llvm') diff --git a/src/patch/llvm/llvm-3.5.patch b/src/patch/llvm/llvm-3.5.patch new file mode 100644 index 0000000..8ade786 --- /dev/null +++ b/src/patch/llvm/llvm-3.5.patch @@ -0,0 +1,864 @@ +diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h +index 6918280..8883165 100644 +--- a/include/llvm/MC/MCInst.h ++++ b/include/llvm/MC/MCInst.h +@@ -20,6 +20,7 @@ + #include "llvm/ADT/StringRef.h" + #include "llvm/Support/DataTypes.h" + #include "llvm/Support/SMLoc.h" ++#include "llvm/IR/DebugLoc.h" + + namespace llvm { + class raw_ostream; +@@ -151,6 +152,7 @@ class MCInst { + unsigned Opcode; + SMLoc Loc; + SmallVector Operands; ++ DebugLoc DbgLoc; + public: + MCInst() : Opcode(0) {} + +@@ -160,6 +162,9 @@ public: + void setLoc(SMLoc loc) { Loc = loc; } + SMLoc getLoc() const { return Loc; } + ++ void setDebugLoc(DebugLoc &Loc) { DbgLoc = Loc; } ++ 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/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h +index 5dda8bd..0bbd7fb 100644 +--- a/include/llvm/Target/TargetRegisterInfo.h ++++ b/include/llvm/Target/TargetRegisterInfo.h +@@ -238,6 +238,8 @@ protected: + virtual ~TargetRegisterInfo(); + public: + ++ std::vector HQEMUReservedRegs; ++ + // Register numbers can represent physical registers, virtual registers, and + // sometimes stack slots. The unsigned values are divided into these ranges: + // +@@ -452,6 +454,10 @@ public: + /// used by register scavenger to determine what registers are free. + virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + ++ /// Get/Set extra reserved register(s) by HQEMU. ++ virtual void getHQEMUReservedRegs(BitVector &Reserved) const { } ++ virtual void setHQEMUReservedRegs(std::string RegName) { } ++ + /// getMatchingSuperReg - Return a super-register of the specified register + /// Reg so its sub-register of index SubIdx is Reg. + unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, +diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp +index 2ba1f86..f727dd6 100644 +--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp ++++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp +@@ -365,7 +365,10 @@ namespace { + + } + ~JITEmitter() { ++#if 0 ++ // HQEMU has the ownership of the memory manager. Do not delete it. + delete MemMgr; ++#endif + } + + JITResolver &getJITResolver() { return Resolver; } +diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h +index 100e9a2..fc9fcfc 100644 +--- a/lib/ExecutionEngine/MCJIT/MCJIT.h ++++ b/lib/ExecutionEngine/MCJIT/MCJIT.h +@@ -77,7 +77,11 @@ public: + + private: + MCJIT *ParentEngine; ++#if 0 + std::unique_ptr ClientMM; ++#endif ++ // HQEMU has the ownership of the memory manager. Do not delete it. ++ RTDyldMemoryManager *ClientMM; + }; + + // About Module states: added->loaded->finalized. +diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp +index 32b5f4a..bb873a9 100644 +--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp ++++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp +@@ -149,9 +149,39 @@ getReservedRegs(const MachineFunction &MF) const { + for (MCSubRegIterator SI(*I, this); SI.isValid(); ++SI) + if (Reserved.test(*SI)) Reserved.set(*I); + ++ getHQEMUReservedRegs(Reserved); + return Reserved; + } + ++void ARMBaseRegisterInfo::getHQEMUReservedRegs(BitVector &Reserved) const { ++ for (unsigned i = 0, e = HQEMUReservedRegs.size(); i != e; ++i) ++ Reserved.set(HQEMUReservedRegs[i]); ++} ++ ++void ARMBaseRegisterInfo::setHQEMUReservedRegs(std::string RegName) { ++#define RESERVE(x) \ ++ do { \ ++ HQEMUReservedRegs.push_back(ARM::R ## x); \ ++ return; \ ++ } while(0) ++ ++ if (RegName == "r0") RESERVE(0); ++ if (RegName == "r1") RESERVE(1); ++ if (RegName == "r2") RESERVE(2); ++ if (RegName == "r3") RESERVE(3); ++ if (RegName == "r4") RESERVE(4); ++ if (RegName == "r5") RESERVE(5); ++ if (RegName == "r6") RESERVE(6); ++ if (RegName == "r7") RESERVE(7); ++ if (RegName == "r8") RESERVE(8); ++ if (RegName == "r9") RESERVE(9); ++ if (RegName == "r10") RESERVE(10); ++ if (RegName == "r11") RESERVE(11); ++ if (RegName == "r12") RESERVE(12); ++ ++#undef RESERVE ++} ++ + const TargetRegisterClass* + ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) + const { +diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h +index 833d3f2..fdcc6be 100644 +--- a/lib/Target/ARM/ARMBaseRegisterInfo.h ++++ b/lib/Target/ARM/ARMBaseRegisterInfo.h +@@ -117,6 +117,9 @@ public: + + BitVector getReservedRegs(const MachineFunction &MF) const override; + ++ void getHQEMUReservedRegs(BitVector &Reserved) const; ++ void setHQEMUReservedRegs(std::string RegName); ++ + const TargetRegisterClass * + getPointerRegClass(const MachineFunction &MF, + unsigned Kind = 0) const override; +diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +index 075db11..8b469c5 100644 +--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp ++++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +@@ -164,6 +164,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; + }; + + } // end anonymous namespace +@@ -1151,6 +1154,50 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, + } + } + ++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; ++ DebugLoc Loc = MI.getDebugLoc(); ++ if (Loc.isUnknown()) ++ 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) { ++ for (unsigned i = 0; i != 5; ++i) ++ EmitByte(0x90, CurByte, OS); ++ return true; ++ } ++ return false; ++} ++ + void X86MCCodeEmitter:: + EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, +@@ -1159,6 +1206,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/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp +index a3ae7ee..1555712 100644 +--- a/lib/Target/X86/X86CodeEmitter.cpp ++++ b/lib/Target/X86/X86CodeEmitter.cpp +@@ -105,6 +105,8 @@ namespace { + void emitMemModRMByte(const MachineInstr &MI, + unsigned Op, unsigned RegOpcodeField, + intptr_t PCAdj = 0); ++ void emitQMMU(MachineInstr &MI, const MCInstrDesc *Desc); ++ bool emitHQEMUInstruction(MachineInstr &MI, const MCInstrDesc *Desc); + + unsigned getX86RegNum(unsigned RegNo) const { + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); +@@ -113,6 +115,13 @@ namespace { + + unsigned char getVEXRegisterEncoding(const MachineInstr &MI, + unsigned OpNum) const; ++ unsigned char getWriteMaskRegisterEncoding(const MachineInstr &MI, ++ unsigned OpNum) const { ++ assert(X86::K0 != MI.getOperand(OpNum).getReg() && ++ "Invalid mask register as write-mask!"); ++ unsigned MaskRegNum = getX86RegNum(MI.getOperand(OpNum).getReg()); ++ return MaskRegNum; ++ } + }; + + template +@@ -748,9 +757,11 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + const MCInstrDesc *Desc) const { + unsigned char Encoding = (TSFlags & X86II::EncodingMask) >> + X86II::EncodingShift; ++ bool HasEVEX_K = ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); + bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; + bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3; + bool HasMemOp4 = (TSFlags >> X86II::VEXShift) & X86II::MemOp4; ++ bool HasEVEX_RC = (TSFlags >> X86II::VEXShift) & X86II::EVEX_RC; + + // VEX_R: opcode externsion equivalent to REX.R in + // 1's complement (inverted) form +@@ -759,6 +770,7 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // 0: Same as REX_R=1 (64 bit mode only) + // + unsigned char VEX_R = 0x1; ++ unsigned char EVEX_R2 = 0x1; + + // VEX_X: equivalent to REX.X, only used when a + // register is used for index in SIB Byte. +@@ -793,6 +805,7 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // VEX_4V (VEX vvvv field): a register specifier + // (in 1's complement form) or 1111 if unused. + unsigned char VEX_4V = 0xf; ++ unsigned char EVEX_V2 = 0x1; + + // VEX_L (Vector Length): + // +@@ -800,6 +813,7 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // 1: 256-bit vector + // + unsigned char VEX_L = 0; ++ unsigned char EVEX_L2 = 0; + + // VEX_PP: opcode extension providing equivalent + // functionality of a SIMD prefix +@@ -811,11 +825,36 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // + unsigned char VEX_PP = 0; + ++ // EVEX_U ++ unsigned char EVEX_U = 1; // Always '1' so far ++ ++ // EVEX_z ++ unsigned char EVEX_z = 0; ++ ++ // EVEX_b ++ unsigned char EVEX_b = 0; ++ ++ // EVEX_rc ++ unsigned char EVEX_rc = 0; ++ ++ // EVEX_aaa ++ unsigned char EVEX_aaa = 0; ++ ++ bool EncodeRC = false; ++ + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_W) + VEX_W = 1; + + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_L) + VEX_L = 1; ++ if (((TSFlags >> X86II::VEXShift) & X86II::EVEX_L2)) ++ EVEX_L2 = 1; ++ ++ if (HasEVEX_K && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_Z)) ++ EVEX_z = 1; ++ ++ if (((TSFlags >> X86II::VEXShift) & X86II::EVEX_B)) ++ EVEX_b = 1; + + switch (TSFlags & X86II::OpPrefixMask) { + default: break; // VEX_PP already correct +@@ -836,15 +875,7 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + + // Classify VEX_B, VEX_4V, VEX_R, VEX_X + unsigned NumOps = Desc->getNumOperands(); +- unsigned CurOp = 0; +- if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) == 0) +- ++CurOp; +- else if (NumOps > 3 && Desc->getOperandConstraint(2, MCOI::TIED_TO) == 0) { +- assert(Desc->getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1); +- // Special case for GATHER with 2 TIED_TO operands +- // Skip the first 2 operands: dst, mask_wb +- CurOp += 2; +- } ++ unsigned CurOp = X86II::getOperandBias(*Desc); + + switch (TSFlags & X86II::FormMask) { + default: llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!"); +@@ -860,14 +891,28 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + VEX_B = 0x0; + if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrIndexReg).getReg())) + VEX_X = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(X86::AddrIndexReg).getReg())) ++ EVEX_V2 = 0x0; + + CurOp = X86::AddrNumOperands; +- if (HasVEX_4V) +- VEX_4V = getVEXRegisterEncoding(MI, CurOp++); ++ ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); ++ ++ if (HasVEX_4V) { ++ VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; ++ CurOp++; ++ } + + const MachineOperand &MO = MI.getOperand(CurOp); +- if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg())) +- VEX_R = 0x0; ++ if (MO.isReg()) { ++ if (X86II::isX86_64ExtendedReg(MO.getReg())) ++ VEX_R = 0x0; ++ if (X86II::is32ExtendedReg(MO.getReg())) ++ EVEX_R2 = 0x0; ++ } + break; + } + case X86II::MRMSrcMem: +@@ -882,10 +927,17 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_R = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_R2 = 0x0; + CurOp++; + ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); ++ + if (HasVEX_4V) { + VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; + CurOp++; + } + +@@ -896,6 +948,10 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + MI.getOperand(MemOperand+X86::AddrIndexReg).getReg())) + VEX_X = 0x0; + ++ if (X86II::is32ExtendedReg( ++ MI.getOperand(MemOperand+X86::AddrIndexReg).getReg())) ++ EVEX_V2 = 0x0; ++ + if (HasVEX_4VOp3) + VEX_4V = getVEXRegisterEncoding(MI, CurOp+X86::AddrNumOperands); + break; +@@ -906,8 +962,15 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // MRM[0-9]m instructions forms: + // MemAddr + // src1(VEX_4V), MemAddr +- if (HasVEX_4V) +- VEX_4V = getVEXRegisterEncoding(MI, CurOp++); ++ if (HasVEX_4V) { ++ VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; ++ CurOp++; ++ } ++ ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + + if (X86II::isX86_64ExtendedReg( + MI.getOperand(MemOperand+X86::AddrBaseReg).getReg())) +@@ -925,19 +988,38 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_R = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_R2 = 0x0; + CurOp++; + +- if (HasVEX_4V) +- VEX_4V = getVEXRegisterEncoding(MI, CurOp++); ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); ++ ++ if (HasVEX_4V) { ++ VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; ++ CurOp++; ++ } + + if (HasMemOp4) // Skip second register source (encoded in I8IMM) + CurOp++; + + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_B = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ VEX_X = 0x0; + CurOp++; + if (HasVEX_4VOp3) + VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (EVEX_b) { ++ if (HasEVEX_RC) { ++ unsigned RcOperand = NumOps-1; ++ assert(RcOperand >= CurOp); ++ EVEX_rc = MI.getOperand(RcOperand).getImm() & 0x3; ++ } ++ EncodeRC = true; ++ } + break; + case X86II::MRMDestReg: + // MRMDestReg instructions forms: +@@ -946,13 +1028,26 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + // dst(ModR/M), src1(VEX_4V), src2(ModR/M) + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_B = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ VEX_X = 0x0; + CurOp++; + +- if (HasVEX_4V) +- VEX_4V = getVEXRegisterEncoding(MI, CurOp++); ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); ++ ++ if (HasVEX_4V) { ++ VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; ++ CurOp++; ++ } + + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_R = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_R2 = 0x0; ++ if (EVEX_b) ++ EncodeRC = true; + break; + case X86II::MRM0r: case X86II::MRM1r: + case X86II::MRM2r: case X86II::MRM3r: +@@ -960,45 +1055,190 @@ void Emitter::emitVEXOpcodePrefix(uint64_t TSFlags, + case X86II::MRM6r: case X86II::MRM7r: + // MRM0r-MRM7r instructions forms: + // dst(VEX_4V), src(ModR/M), imm8 +- VEX_4V = getVEXRegisterEncoding(MI, CurOp); +- CurOp++; ++ if (HasVEX_4V) { ++ VEX_4V = getVEXRegisterEncoding(MI, CurOp); ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ EVEX_V2 = 0x0; ++ CurOp++; ++ } ++ if (HasEVEX_K) ++ EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) + VEX_B = 0x0; ++ if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) ++ VEX_X = 0x0; + break; + } + +- // Emit segment override opcode prefix as needed. +- emitSegmentOverridePrefix(TSFlags, MemOperand, MI); ++ if (Encoding == X86II::VEX || Encoding == X86II::XOP) { ++ // Emit segment override opcode prefix as needed. ++ emitSegmentOverridePrefix(TSFlags, MemOperand, MI); ++ ++ // VEX opcode prefix can have 2 or 3 bytes ++ // ++ // 3 bytes: ++ // +-----+ +--------------+ +-------------------+ ++ // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp | ++ // +-----+ +--------------+ +-------------------+ ++ // 2 bytes: ++ // +-----+ +-------------------+ ++ // | C5h | | R | vvvv | L | pp | ++ // +-----+ +-------------------+ ++ // ++ // XOP uses a similar prefix: ++ // +-----+ +--------------+ +-------------------+ ++ // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp | ++ // +-----+ +--------------+ +-------------------+ ++ unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); ++ ++ // Can this use the 2 byte VEX prefix? ++ if (Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { ++ MCE.emitByte(0xC5); ++ MCE.emitByte(LastByte | (VEX_R << 7)); ++ return; ++ } ++ ++ // 3 byte VEX prefix ++ MCE.emitByte(Encoding == X86II::XOP ? 0x8F : 0xC4); ++ MCE.emitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M); ++ MCE.emitByte(LastByte | (VEX_W << 7)); ++ } else { ++ assert(Encoding == X86II::EVEX && "unknown encoding!"); ++ // EVEX opcode prefix can have 4 bytes ++ // ++ // +-----+ +--------------+ +-------------------+ +------------------------+ ++ // | 62h | | RXBR' | 00mm | | W | vvvv | U | pp | | z | L'L | b | v' | aaa | ++ // +-----+ +--------------+ +-------------------+ +------------------------+ ++ assert((VEX_5M & 0x3) == VEX_5M ++ && "More than 2 significant bits in VEX.m-mmmm fields for EVEX!"); ++ ++ VEX_5M &= 0x3; ++ ++ MCE.emitByte(0x62); ++ MCE.emitByte((VEX_R << 7) | ++ (VEX_X << 6) | ++ (VEX_B << 5) | ++ (EVEX_R2 << 4) | ++ VEX_5M); ++ MCE.emitByte((VEX_W << 7) | ++ (VEX_4V << 3) | ++ (EVEX_U << 2) | ++ VEX_PP); ++ if (EncodeRC) ++ MCE.emitByte((EVEX_z << 7) | ++ (EVEX_rc << 5) | ++ (EVEX_b << 4) | ++ (EVEX_V2 << 3) | ++ EVEX_aaa); ++ else ++ MCE.emitByte((EVEX_z << 7) | ++ (EVEX_L2 << 6) | ++ (VEX_L << 5) | ++ (EVEX_b << 4) | ++ (EVEX_V2 << 3) | ++ EVEX_aaa); ++ } ++} + +- // VEX opcode prefix can have 2 or 3 bytes +- // +- // 3 bytes: +- // +-----+ +--------------+ +-------------------+ +- // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp | +- // +-----+ +--------------+ +-------------------+ +- // 2 bytes: +- // +-----+ +-------------------+ +- // | C5h | | R | vvvv | L | pp | +- // +-----+ +-------------------+ +- // +- // XOP uses a similar prefix: +- // +-----+ +--------------+ +-------------------+ +- // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp | +- // +-----+ +--------------+ +-------------------+ +- unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); +- +- // Can this use the 2 byte VEX prefix? +- if (Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { +- MCE.emitByte(0xC5); +- MCE.emitByte(LastByte | (VEX_R << 7)); +- return; ++template ++void Emitter::emitQMMU(MachineInstr &MI, ++ const MCInstrDesc *Desc) { ++ // QMMU stub is as follows: ++ // jmp QMMUExit ++ // nop ++ // jmp QMMUMiss ++ MachineBasicBlock *MBB = MI.getParent(); ++ if (MBB->succ_size() != 2) ++ llvm_unreachable("Unhandled QMMU stub!"); ++ ++ MachineBasicBlock* QMMUExit = *MBB->succ_begin(); ++ MachineBasicBlock* QMMUMiss = *(++MBB->succ_begin()); ++ MachineInstr *MRI = &*QMMUMiss->rbegin(); ++ if (MRI->getDesc().getOpcode() != X86::TRAP) { ++ MachineBasicBlock *tmp = QMMUExit; ++ QMMUExit = QMMUMiss; ++ QMMUMiss = tmp; + } + +- // 3 byte VEX prefix +- MCE.emitByte(Encoding == X86II::XOP ? 0x8F : 0xC4); +- MCE.emitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M); +- MCE.emitByte(LastByte | (VEX_W << 7)); ++ MRI = &*QMMUMiss->rbegin(); ++ if (MRI->getDesc().getOpcode() != X86::TRAP) ++ llvm_unreachable("Unknown QMMU CFG!"); ++ ++ MCE.emitByte(0xE9); ++ emitPCRelativeBlockAddress(QMMUExit); ++ MCE.emitByte(0x90); ++ if (QMMUMiss != ++MachineFunction::iterator(MBB)) { ++ MCE.emitByte(0xE9); ++ emitPCRelativeBlockAddress(QMMUMiss); ++ } ++} ++ ++template ++bool Emitter::emitHQEMUInstruction(MachineInstr &MI, ++ const MCInstrDesc *Desc) ++{ ++ /* 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 = Desc->Opcode; ++ ++ switch (Opcode) { ++ case X86::TRAP: ++ case X86::RETQ: ++ case X86::JMP32r: ++ case X86::JMP64r: ++ break; ++ default: return false; ++ } ++ ++ LLVMContext &Ctx = MI.getParent()->getParent()->getFunction()->getContext(); ++ MDNode *M = MI.getDebugLoc().getScope(Ctx); ++ if (!M || !isa(M->getOperand(1))) ++ return false; ++ ++ uint64_t flag = cast(M->getOperand(1))->getZExtValue(); ++ if (flag < PATCH_HQEMU || flag > PATCH_QMMU) ++ return false; ++ ++ if (Opcode == X86::TRAP) { ++ if (flag == PATCH_QMMU) ++ return true; ++ ++ unsigned NumNOP = 3 - MCE.getCurrentPCValue() % 4; ++ for (unsigned i = 0; i != NumNOP; ++i) ++ MCE.emitByte(0x90); ++ ++ uintptr_t *ChainPoint = (uintptr_t *)cast(M->getOperand(2))->getZExtValue(); ++ *ChainPoint = (uintptr_t) MCE.getCurrentPCValue(); ++ MCE.emitByte(0xE9); ++ emitConstant(0, 4); ++ return true; ++ } ++ ++ if (Opcode == X86::RETQ) { ++ uintptr_t ExitAddr = (uintptr_t)cast(M->getOperand(2))->getZExtValue(); ++ uintptr_t Disp = ExitAddr - ((uintptr_t) MCE.getCurrentPCValue() + 5); ++ MCE.emitByte(0xE9); ++ emitConstant(Disp, 4); ++ return true; ++ } ++ ++ if (Opcode == X86::JMP32r || Opcode == X86::JMP64r) { ++ if (flag == PATCH_QMMU) { ++ emitQMMU(MI, Desc); ++ return true; ++ } ++ } ++ return false; + } + + template +@@ -1032,6 +1272,11 @@ void Emitter::emitInstruction(MachineInstr &MI, + + unsigned Opcode = Desc->Opcode; + ++ if (emitHQEMUInstruction(MI, Desc)) { ++ MCE.processDebugLoc(MI.getDebugLoc(), false); ++ return; ++ } ++ + // If this is a two-address instruction, skip one of the register operands. + unsigned NumOps = Desc->getNumOperands(); + unsigned CurOp = 0; +diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp +index 2bd70a9..7e83c66 100644 +--- a/lib/Target/X86/X86MCInstLower.cpp ++++ b/lib/Target/X86/X86MCInstLower.cpp +@@ -345,6 +345,10 @@ static unsigned getRetOpcode(const X86Subtarget &Subtarget) + void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + ++ DebugLoc Loc = MI->getDebugLoc(); ++ if (!Loc.isUnknown()) ++ OutMI.setDebugLoc(Loc); ++ + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + +diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp +index e8a7e84..a0b425e 100644 +--- a/lib/Target/X86/X86RegisterInfo.cpp ++++ b/lib/Target/X86/X86RegisterInfo.cpp +@@ -395,9 +395,65 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + } + } + ++ getHQEMUReservedRegs(Reserved); + return Reserved; + } + ++void X86RegisterInfo::getHQEMUReservedRegs(BitVector &Reserved) const { ++ for (unsigned i = 0, e = HQEMUReservedRegs.size(); i != e; ++i) ++ Reserved.set(HQEMUReservedRegs[i]); ++} ++ ++void X86RegisterInfo::setHQEMUReservedRegs(std::string RegName) { ++#define RESERVE1(x) \ ++ do { \ ++ HQEMUReservedRegs.push_back(X86::x ## L); \ ++ HQEMUReservedRegs.push_back(X86::x ## H); \ ++ HQEMUReservedRegs.push_back(X86::x ## X);\ ++ HQEMUReservedRegs.push_back(X86::E ## x ## X);\ ++ HQEMUReservedRegs.push_back(X86::R ## x ## X);\ ++ return; \ ++ } while(0) ++ ++#define RESERVE2(x) \ ++ do { \ ++ HQEMUReservedRegs.push_back(X86::R ## x); \ ++ HQEMUReservedRegs.push_back(X86::R ## x ## B);\ ++ HQEMUReservedRegs.push_back(X86::R ## x ## D);\ ++ HQEMUReservedRegs.push_back(X86::R ## x ## W);\ ++ return; \ ++ } while(0) ++ ++ if (RegName == "ebp") { ++ // 32-bit registers ++ HQEMUReservedRegs.push_back(X86::EBP); ++ // 16-bit registers ++ HQEMUReservedRegs.push_back(X86::BP); ++#if defined(__x86_64__) ++ // X86-64 only ++ HQEMUReservedRegs.push_back(X86::BPL); ++#endif ++ return; ++ } ++#if defined(__x86_64__) ++ if (RegName == "rax") RESERVE1(A); ++ if (RegName == "rbx") RESERVE1(B); ++ if (RegName == "rcx") RESERVE1(C); ++ if (RegName == "rdx") RESERVE1(D); ++ if (RegName == "r8") RESERVE2(8); ++ if (RegName == "r9") RESERVE2(9); ++ if (RegName == "r10") RESERVE2(10); ++ if (RegName == "r11") RESERVE2(11); ++ if (RegName == "r12") RESERVE2(12); ++ if (RegName == "r13") RESERVE2(13); ++ if (RegName == "r14") RESERVE2(14); ++ if (RegName == "r15") RESERVE2(15); ++#endif ++ ++#undef RESERVE1 ++#undef RESERVE2 ++} ++ + //===----------------------------------------------------------------------===// + // Stack Frame Processing methods + //===----------------------------------------------------------------------===// +diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h +index 74efd1f..d709505 100644 +--- a/lib/Target/X86/X86RegisterInfo.h ++++ b/lib/Target/X86/X86RegisterInfo.h +@@ -107,6 +107,9 @@ public: + /// register scavenger to determine what registers are free. + BitVector getReservedRegs(const MachineFunction &MF) const override; + ++ void getHQEMUReservedRegs(BitVector &Reserved) const override; ++ void setHQEMUReservedRegs(std::string RegName) override; ++ + bool hasBasePointer(const MachineFunction &MF) const; + + bool canRealignStack(const MachineFunction &MF) const; +diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp +index a5e443f..cd4f57a 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -1188,12 +1188,15 @@ static bool markAliveBlocks(BasicBlock *BB, + // 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. ++#if 0 ++ // HQEMU: do not delete instructions after llvm.trap. + ++BBI; + if (!isa(BBI)) { + // Don't insert a call to llvm.trap right before the unreachable. + changeToUnreachable(BBI, false); + Changed = true; + } ++#endif + break; + } + } +diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp +index 1c62559..8375529 100644 +--- a/lib/Transforms/Utils/SimplifyCFG.cpp ++++ b/lib/Transforms/Utils/SimplifyCFG.cpp +@@ -1028,6 +1028,11 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, const DataLayout *DL) { + + bool Changed = false; + do { ++ // HQEMU: skip hoisting instructions from llvm.trap to the terminator ++ // instruction. ++ 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)) +@@ -3968,6 +3973,10 @@ bool SimplifyCFGOpt::SimplifyIndirectBr(IndirectBrInst *IBI) { + BasicBlock *BB = IBI->getParent(); + bool Changed = false; + ++ // HQEMU: LLVM tries to remove the indirectbr with no successors. ++ // Disable it because we use indirectbr to implement IBTC. ++ return false; ++ + // Eliminate redundant destinations. + SmallPtrSet Succs; + for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) { diff --git a/src/patch/llvm/llvm-3.8.patch b/src/patch/llvm/llvm-3.8.patch new file mode 100644 index 0000000..a2f8968 --- /dev/null +++ b/src/patch/llvm/llvm-3.8.patch @@ -0,0 +1,247 @@ +diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h +index a730260..5102344 100644 +--- a/include/llvm/ExecutionEngine/ExecutionEngine.h ++++ b/include/llvm/ExecutionEngine/ExecutionEngine.h +@@ -550,6 +550,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 4688b5f..e3124bf 100644 +--- a/include/llvm/MC/MCInst.h ++++ b/include/llvm/MC/MCInst.h +@@ -27,6 +27,7 @@ class MCAsmInfo; + class MCInstPrinter; + class MCExpr; + class MCInst; ++class DebugLoc; + + /// \brief Instances of this class represent operands of the MCInst class. + /// This is a simple discriminated union. +@@ -151,9 +152,10 @@ class MCInst { + unsigned Opcode; + SMLoc Loc; + SmallVector Operands; ++ const DebugLoc *DbgLoc; + + public: +- MCInst() : Opcode(0) {} ++ MCInst() : Opcode(0), DbgLoc(nullptr) {} + + void setOpcode(unsigned Op) { Opcode = Op; } + unsigned getOpcode() const { return Opcode; } +@@ -161,6 +163,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 70c8658..69a6427 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 &InstrNameData[InstrNameIndices[Opcode]]; + } ++ ++ void setHQEMUExitAddr(unsigned long Addr) { HQEMUExitAddr = Addr; } ++ unsigned long getHQEMUExitAddr() const { return HQEMUExitAddr; } + }; + + } // End llvm namespace +diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp +index 41c8da4..ffca9ea 100644 +--- a/lib/ExecutionEngine/ExecutionEngine.cpp ++++ b/lib/ExecutionEngine/ExecutionEngine.cpp +@@ -497,6 +497,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/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +index dfab6ec..8a9752f 100644 +--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp ++++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +@@ -23,6 +23,7 @@ + #include "llvm/MC/MCSubtargetInfo.h" + #include "llvm/MC/MCSymbol.h" + #include "llvm/Support/raw_ostream.h" ++#include "llvm/IR/DebugLoc.h" + + using namespace llvm; + +@@ -164,6 +165,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; + }; + + } // end anonymous namespace +@@ -1158,6 +1162,52 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, + } + } + ++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, +@@ -1166,6 +1216,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/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp +index e1ca558..c3acaec 100644 +--- a/lib/Target/X86/X86MCInstLower.cpp ++++ b/lib/Target/X86/X86MCInstLower.cpp +@@ -437,6 +437,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 274b566..dbb4fec 100644 +--- a/lib/Target/X86/X86RegisterInfo.cpp ++++ b/lib/Target/X86/X86RegisterInfo.cpp +@@ -473,6 +473,19 @@ 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); ++ } ++ } + return Reserved; + } + +diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp +index abc9b65..39241c2 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -1302,7 +1302,8 @@ static bool markAliveBlocks(Function &F, + } + + if (CallInst *CI = dyn_cast(BBI)) { +- if (CI->doesNotReturn()) { ++ // HQEMU: do not delete instructions after llvm.trap. ++ 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 e484b69..6ac6033 100644 +--- a/lib/Transforms/Utils/SimplifyCFG.cpp ++++ b/lib/Transforms/Utils/SimplifyCFG.cpp +@@ -1120,6 +1120,9 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, + + bool Changed = false; + do { ++ 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)) +@@ -4898,6 +4901,9 @@ bool SimplifyCFGOpt::SimplifyIndirectBr(IndirectBrInst *IBI) { + BasicBlock *BB = IBI->getParent(); + bool Changed = false; + ++ if (BB->getParent()->hasFnAttribute("hqemu")) ++ return false; ++ + // Eliminate redundant destinations. + SmallPtrSet Succs; + for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) { diff --git a/src/patch/llvm/llvm-3.9.patch b/src/patch/llvm/llvm-3.9.patch new file mode 100644 index 0000000..38fa566 --- /dev/null +++ b/src/patch/llvm/llvm-3.9.patch @@ -0,0 +1,404 @@ +diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h +index ab13028..810f403 100644 +--- a/include/llvm/ExecutionEngine/ExecutionEngine.h ++++ b/include/llvm/ExecutionEngine/ExecutionEngine.h +@@ -550,6 +550,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 4688b5f..e3124bf 100644 +--- a/include/llvm/MC/MCInst.h ++++ b/include/llvm/MC/MCInst.h +@@ -27,6 +27,7 @@ class MCAsmInfo; + class MCInstPrinter; + class MCExpr; + class MCInst; ++class DebugLoc; + + /// \brief Instances of this class represent operands of the MCInst class. + /// This is a simple discriminated union. +@@ -151,9 +152,10 @@ class MCInst { + unsigned Opcode; + SMLoc Loc; + SmallVector Operands; ++ const DebugLoc *DbgLoc; + + public: +- MCInst() : Opcode(0) {} ++ MCInst() : Opcode(0), DbgLoc(nullptr) {} + + void setOpcode(unsigned Op) { Opcode = Op; } + unsigned getOpcode() const { return Opcode; } +@@ -161,6 +163,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 70c8658..69a6427 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 &InstrNameData[InstrNameIndices[Opcode]]; + } ++ ++ void setHQEMUExitAddr(unsigned long Addr) { HQEMUExitAddr = Addr; } ++ unsigned long getHQEMUExitAddr() const { return HQEMUExitAddr; } + }; + + } // End llvm namespace +diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp +index a8e68bf..a4f1d99 100644 +--- a/lib/ExecutionEngine/ExecutionEngine.cpp ++++ b/lib/ExecutionEngine/ExecutionEngine.cpp +@@ -492,6 +492,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 2b4cdf1..0e09232 100644 +--- a/lib/Target/AArch64/AArch64MCInstLower.cpp ++++ b/lib/Target/AArch64/AArch64MCInstLower.cpp +@@ -207,6 +207,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 af867da..1755863 100644 +--- a/lib/Target/AArch64/AArch64RegisterInfo.cpp ++++ b/lib/Target/AArch64/AArch64RegisterInfo.cpp +@@ -138,6 +138,14 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + Reserved.set(AArch64::W19); + } + ++ // Reserve registers for HQEMU. ++ if (MF.getFunction()->hasFnAttribute("hqemu")) { ++ Reserved.set(AArch64::X19); ++ Reserved.set(AArch64::W19); ++ Reserved.set(AArch64::X28); ++ Reserved.set(AArch64::W28); ++ } ++ + return Reserved; + } + +diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +index 7b9ff8f..7d724cb 100644 +--- a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp ++++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +@@ -24,6 +24,7 @@ + #include "llvm/MC/MCSubtargetInfo.h" + #include "llvm/Support/EndianStream.h" + #include "llvm/Support/raw_ostream.h" ++#include "llvm/IR/DebugLoc.h" + using namespace llvm; + + #define DEBUG_TYPE "mccodeemitter" +@@ -35,11 +36,13 @@ namespace { + + class AArch64MCCodeEmitter : public MCCodeEmitter { + MCContext &Ctx; ++ const MCInstrInfo &MCII; + + AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT + public: +- AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : Ctx(ctx) {} ++ AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) ++ : Ctx(ctx), MCII(mcii) {} + + ~AArch64MCCodeEmitter() override {} + +@@ -170,6 +173,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; + }; + + } // end anonymous namespace +@@ -536,9 +543,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; ++ + if (MI.getOpcode() == AArch64::TLSDESCCALL) { + // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the + // following (BLR) instruction. It doesn't emit any code itself so it +diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +index 96c2e81..504b3eb 100644 +--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp ++++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +@@ -23,6 +23,7 @@ + #include "llvm/MC/MCSubtargetInfo.h" + #include "llvm/MC/MCSymbol.h" + #include "llvm/Support/raw_ostream.h" ++#include "llvm/IR/DebugLoc.h" + + using namespace llvm; + +@@ -142,6 +143,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; + }; +@@ -1110,6 +1114,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, +@@ -1118,6 +1168,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/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp +index 906e342..8f7db6b 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 8675063..e1d0e19 100644 +--- a/lib/Target/X86/X86RegisterInfo.cpp ++++ b/lib/Target/X86/X86RegisterInfo.cpp +@@ -503,6 +503,19 @@ 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); ++ } ++ } + return Reserved; + } + +diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp +index f1838d8..3d4d3b9 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -1413,7 +1413,8 @@ static bool markAliveBlocks(Function &F, + Changed = true; + break; + } +- if (CI->doesNotReturn()) { ++ // HQEMU: do not delete instructions after llvm.trap. ++ 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 0504646..92291c3 100644 +--- a/lib/Transforms/Utils/SimplifyCFG.cpp ++++ b/lib/Transforms/Utils/SimplifyCFG.cpp +@@ -1201,6 +1201,9 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, + + bool Changed = false; + do { ++ 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)) +@@ -5088,6 +5091,9 @@ bool SimplifyCFGOpt::SimplifyIndirectBr(IndirectBrInst *IBI) { + BasicBlock *BB = IBI->getParent(); + bool Changed = false; + ++ if (BB->getParent()->hasFnAttribute("hqemu")) ++ return false; ++ + // Eliminate redundant destinations. + SmallPtrSet Succs; + for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) { diff --git a/src/patch/llvm/llvm-5.0.patch b/src/patch/llvm/llvm-5.0.patch new file mode 100644 index 0000000..bb89779 --- /dev/null +++ b/src/patch/llvm/llvm-5.0.patch @@ -0,0 +1,652 @@ +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) { diff --git a/src/patch/llvm/llvm-6.0.patch b/src/patch/llvm/llvm-6.0.patch new file mode 100644 index 0000000..12fde6d --- /dev/null +++ b/src/patch/llvm/llvm-6.0.patch @@ -0,0 +1,652 @@ +diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h +index 77c23b4..85fa6d4 100644 +--- a/include/llvm/ExecutionEngine/ExecutionEngine.h ++++ b/include/llvm/ExecutionEngine/ExecutionEngine.h +@@ -567,6 +567,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 db28fd0..574b66e 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; + // These flags could be used to pass some info from one target subcomponent + // to another, for example, from disassembler to asm printer. The values of + // the flags have any sense on target level only (e.g. prefixes on x86). +@@ -177,6 +179,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 7f358a6..5ef804f 100644 +--- a/lib/CodeGen/BranchFolding.cpp ++++ b/lib/CodeGen/BranchFolding.cpp +@@ -175,6 +175,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 c598857..c7ecd12 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 65dae03..09e5858 100644 +--- a/lib/Target/AArch64/AArch64MCInstLower.cpp ++++ b/lib/Target/AArch64/AArch64MCInstLower.cpp +@@ -239,6 +239,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 88dd297..4b2ccd8 100644 +--- a/lib/Target/AArch64/AArch64RegisterInfo.cpp ++++ b/lib/Target/AArch64/AArch64RegisterInfo.cpp +@@ -132,6 +132,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 f0e8b11..a96a36d 100644 +--- a/lib/Target/PowerPC/PPCISelLowering.cpp ++++ b/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -2442,10 +2442,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); +@@ -2455,7 +2456,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); +@@ -2518,10 +2519,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); +@@ -2531,7 +2533,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); +@@ -2547,10 +2549,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); +@@ -2660,10 +2663,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); +@@ -2673,7 +2677,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 1e40711..496238a 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) { + MCOperand MCOp; + if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP, +diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp +index 6b62a82..cc5a73b 100644 +--- a/lib/Target/PowerPC/PPCRegisterInfo.cpp ++++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp +@@ -279,6 +279,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; + } +@@ -904,6 +911,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 4ddc1f0..c564e71 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; + }; +@@ -1158,6 +1162,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, +@@ -1167,6 +1217,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, + uint64_t TSFlags = Desc.TSFlags; + unsigned Flags = MI.getFlags(); + ++ 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 11808f8..bd10b86 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 730ba74..c1b3ef6 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 bc31e95..893ff41 100644 +--- a/lib/Target/X86/X86RegisterInfo.cpp ++++ b/lib/Target/X86/X86RegisterInfo.cpp +@@ -570,6 +570,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 acccf7a..f2ab12d 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -1587,7 +1587,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 7c19578..30f3481 100644 +--- a/lib/Transforms/Utils/SimplifyCFG.cpp ++++ b/lib/Transforms/Utils/SimplifyCFG.cpp +@@ -1271,6 +1271,10 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, + + bool Changed = false; + do { ++ // Do not hoist llvm::trap and debug instructions in HQEMU mode. ++ if (BI->getParent()->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)) +@@ -5600,6 +5604,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) { -- cgit v1.1