1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00
Beef/IDEHelper/Backend/BeMCContext.h

1512 lines
36 KiB
C
Raw Normal View History

2019-08-23 11:56:54 -07:00
#pragma once
#include "../Beef/BfCommon.h"
#include "../Compiler/BfUtil.h"
#include "BeefySysLib/util/BumpAllocator.h"
#include "BeefySysLib/util/Array.h"
#include "BeefySysLib/util/HashSet.h"
#include "BeModule.h"
#include "BeefySysLib/MemStream.h"
#include "../X64.h"
NS_BF_BEGIN
class BeMCAddInst
{
public:
};
struct BeVTrackingBits
{
2019-08-23 11:56:54 -07:00
// Memory is allocated by BeVTrackingContext
bool IsSet(int idx);
void Set(int idx);
void Clear(int idx);
2019-08-23 11:56:54 -07:00
};
struct BeVTrackingValue
{
public:
BeVTrackingBits* mEntry;
2019-08-23 11:56:54 -07:00
int mNumEntries;
BeVTrackingValue(int maxSize)
{
mNumEntries = (maxSize + 31) / 32;
mEntry = (BeVTrackingBits*)(new int32[mNumEntries]);
memset(mEntry, 0, mNumEntries * 4);
}
~BeVTrackingValue()
{
delete[](int32*)mEntry;
}
2019-08-23 11:56:54 -07:00
void Clear()
{
memset(mEntry, 0, mNumEntries * 4);
}
};
class BeVTrackingList
{
public:
int mSize;
int mNumChanges;
int mEntries[1];
struct Iterator
{
public:
BeVTrackingList* mList;
int mIdx;
2019-08-23 11:56:54 -07:00
public:
Iterator(BeVTrackingList* list)
{
2019-08-23 11:56:54 -07:00
mList = list;
mIdx = 0;
2019-08-23 11:56:54 -07:00
}
Iterator& operator++()
{
mIdx++;
return *this;
}
bool operator!=(const Iterator& itr) const
{
return itr.mIdx != mIdx;
}
bool operator==(const Iterator& itr) const
{
return itr.mIdx == mIdx;
}
int operator*()
{
return mList->mEntries[mIdx];
}
};
/*struct DiffIterator
{
public:
BeVTrackingList* mList0;
BeVTrackingList* mList1;
int mIdx0;
int mIdx1;
DiffIterator(BeVTrackingList* list0, BeVTrackingList* list1)
{
mList0 = list0;
mList1 = list1;
mIdx0 = 0;
mIdx1 = 0;
}
DiffIterator& operator++()
{
}
};*/
Iterator begin()
{
return Iterator(this);
}
Iterator end()
{
auto itr = Iterator(this);
itr.mIdx = mSize;
return itr;
}
int GetChange(int idx)
{
return mEntries[mSize + idx];
}
bool ContainsChange(int value)
{
for (int i = 0; i < mNumChanges; i++)
if (mEntries[mSize + i] == value)
return true;
return false;
}
};
class BeMCBlock;
class BeMCPhi;
struct BeMemSetInfo
{
public:
int32 mSize;
int8 mAlign;
2019-08-23 11:56:54 -07:00
uint8 mValue;
};
struct BeMemCpyInfo
{
public:
int32 mSize;
int8 mAlign;
2019-08-23 11:56:54 -07:00
};
struct BeVRegPair
{
// Negative means "addr of", positive means "value of"
int32 mVRegIdx0;
int32 mVRegIdx1;
};
struct BeCmpResult
{
2019-08-23 11:56:54 -07:00
BeCmpKind mCmpKind;
int mResultVRegIdx;
2024-10-16 13:25:17 -04:00
bool mInverted;
2019-08-23 11:56:54 -07:00
BeCmpResult()
{
mCmpKind = BeCmpKind_None;
mResultVRegIdx = -1;
2024-10-16 13:25:17 -04:00
mInverted = false;
2019-08-23 11:56:54 -07:00
}
};
struct BeNotResult;
enum BeMCOperandKind
{
BeMCOperandKind_None,
BeMCOperandKind_NativeReg,
2019-08-23 11:56:54 -07:00
BeMCOperandKind_VReg,
BeMCOperandKind_VRegAddr,
BeMCOperandKind_VRegLoad,
BeMCOperandKind_Symbol,
BeMCOperandKind_SymbolAddr,
BeMCOperandKind_Immediate_i8,
BeMCOperandKind_Immediate_i16,
BeMCOperandKind_Immediate_i32,
BeMCOperandKind_Immediate_i64,
2020-08-23 05:42:42 -07:00
BeMCOperandKind_Immediate_HomeSize,
2019-08-23 11:56:54 -07:00
BeMCOperandKind_Immediate_Null,
BeMCOperandKind_Immediate_f32,
BeMCOperandKind_Immediate_f64,
BeMCOperandKind_Immediate_f32_Packed128,
BeMCOperandKind_Immediate_f64_Packed128,
2022-07-27 12:26:36 -04:00
BeMCOperandKind_Immediate_int32x4,
2019-08-23 11:56:54 -07:00
BeMCOperandKind_ConstAgg,
BeMCOperandKind_Block,
BeMCOperandKind_Label,
2019-08-23 11:56:54 -07:00
BeMCOperandKind_CmpKind,
BeMCOperandKind_CmpResult,
BeMCOperandKind_NotResult,
BeMCOperandKind_MemSetInfo,
BeMCOperandKind_MemCpyInfo,
BeMCOperandKind_VRegPair,
BeMCOperandKind_Phi,
BeMCOperandKind_PreserveFlag
};
enum BeMCPreserveFlag
{
BeMCPreserveFlag_None,
BeMCPreserveFlag_NoRestore
};
class BeMCOperand
{
public:
2019-08-23 11:56:54 -07:00
enum EncodeFlag
{
EncodeFlag_Addr = 0x80000000,
EncodeFlag_Symbol = 0x40000000,
EncodeFlag_IdxMask = 0x0FFFFFFF
};
BeMCOperandKind mKind;
2019-08-23 11:56:54 -07:00
union
{
X64CPURegister mReg;
int mVRegIdx;
int mFrameObjNum;
int64 mImmediate;
BeType* mType;
2020-03-21 07:10:59 -07:00
float mImmF32;
double mImmF64;
2019-08-23 11:56:54 -07:00
BeMCBlock* mBlock;
BeMCPhi* mPhi;
BeNotResult* mNotResult;
BeConstant* mConstant;
int mLabelIdx;
int mSymbolIdx;
BeCmpKind mCmpKind;
2019-08-23 11:56:54 -07:00
int mCmpResultIdx;
BeMemSetInfo mMemSetInfo;
BeMemCpyInfo mMemCpyInfo;
BeVRegPair mVRegPair;
2019-08-23 11:56:54 -07:00
BeMCPreserveFlag mPreserveFlag;
};
2019-08-23 11:56:54 -07:00
public:
BeMCOperand()
{
mKind = BeMCOperandKind_None;
2019-08-23 11:56:54 -07:00
}
operator bool() const
{
return mKind != BeMCOperandKind_None;
}
2019-08-23 11:56:54 -07:00
bool IsVReg() const
{
return (mKind == BeMCOperandKind_VReg);
}
bool IsVRegAny() const
{
return (mKind == BeMCOperandKind_VReg) || (mKind == BeMCOperandKind_VRegAddr) || (mKind == BeMCOperandKind_VRegLoad);
}
2019-08-23 11:56:54 -07:00
bool MayBeMemory()
{
return (mKind >= BeMCOperandKind_VReg) && (mKind <= BeMCOperandKind_SymbolAddr);
}
bool IsImmediate() const
{
return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_f64_Packed128));
}
bool IsImmediateInt() const
{
2020-08-23 05:42:42 -07:00
return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_HomeSize));
2019-08-23 11:56:54 -07:00
}
bool IsImmediateFloat() const
{
2020-08-23 05:42:42 -07:00
return ((mKind >= BeMCOperandKind_Immediate_f32) && (mKind <= BeMCOperandKind_Immediate_int32x4));
2019-08-23 11:56:54 -07:00
}
bool IsNativeReg() const
{
return mKind == BeMCOperandKind_NativeReg;
}
bool IsSymbol() const
{
return (mKind == BeMCOperandKind_Symbol) || (mKind == BeMCOperandKind_SymbolAddr);
}
2019-08-23 11:56:54 -07:00
bool operator==(const BeMCOperand& other) const
{
if (mKind != other.mKind)
return false;
// Either intptr or int
if (mKind == BeMCOperandKind_CmpKind)
return mCmpKind == other.mCmpKind;
2020-03-21 07:10:59 -07:00
if (mKind == BeMCOperandKind_Immediate_f32)
return mImmF32 == other.mImmF32;
if (mKind == BeMCOperandKind_Immediate_f64)
return mImmF64 == other.mImmF64;
2019-08-23 11:56:54 -07:00
if ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Block))
return mImmediate == other.mImmediate;
if (mKind == BeMCOperandKind_Immediate_Null)
return mType == other.mType;
return mVRegIdx == other.mVRegIdx;
}
bool operator!=(const BeMCOperand& other) const
{
return !(*this == other);
}
bool IsZero() const
{
if (mKind == BeMCOperandKind_None)
return true;
if ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_i64) && (mImmediate == 0))
return true;
if (mKind == BeMCOperandKind_Immediate_Null)
return true;
return false;
}
2020-03-21 07:10:59 -07:00
int64 GetImmediateInt() const
2019-08-23 11:56:54 -07:00
{
if ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_i64))
return mImmediate;
return 0;
}
2020-03-21 07:10:59 -07:00
double GetImmediateDouble() const
{
if (mKind == BeMCOperandKind_Immediate_f32)
return mImmF32;
if (mKind == BeMCOperandKind_Immediate_f64)
return mImmF64;
return 0;
}
2019-08-23 11:56:54 -07:00
static BeMCOperand FromEncoded(int vregIdx)
{
BeMCOperand operand;
operand.mVRegIdx = vregIdx & EncodeFlag_IdxMask;
if ((vregIdx & EncodeFlag_Addr) != 0)
{
if ((vregIdx & EncodeFlag_Symbol) != 0)
operand.mKind = BeMCOperandKind_SymbolAddr;
else
operand.mKind = BeMCOperandKind_VRegAddr;
}
else
{
if ((vregIdx & EncodeFlag_Symbol) != 0)
operand.mKind = BeMCOperandKind_Symbol;
else
operand.mKind = BeMCOperandKind_VReg;
}
2019-08-23 11:56:54 -07:00
return operand;
}
2019-08-23 11:56:54 -07:00
static BeMCOperand ToLoad(const BeMCOperand& operand)
{
BeMCOperand loadedOperand = operand;
if (loadedOperand.mKind == BeMCOperandKind_VReg)
loadedOperand.mKind = BeMCOperandKind_VRegLoad;
else if (loadedOperand.mKind == BeMCOperandKind_VRegAddr)
loadedOperand.mKind = BeMCOperandKind_VReg;
else if (loadedOperand.mKind == BeMCOperandKind_SymbolAddr)
loadedOperand.mKind = BeMCOperandKind_Symbol;
else
BF_FATAL("Bad");
return loadedOperand;
}
static BeMCOperand FromVReg(int vregIdx)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_VReg;
operand.mVRegIdx = vregIdx;
return operand;
}
static BeMCOperand FromVRegAddr(int vregIdx)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_VRegAddr;
operand.mVRegIdx = vregIdx;
return operand;
}
static BeMCOperand FromLabel(int labelIdx)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_Label;
operand.mLabelIdx = labelIdx;
return operand;
}
static BeMCOperand FromCmpKind(BeCmpKind cmpKind)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_CmpKind;
operand.mCmpKind = cmpKind;
return operand;
}
static BeMCOperand FromReg(X64CPURegister reg)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_NativeReg;
operand.mReg = reg;
return operand;
}
static BeMCOperand FromImmediate(int64 immediate)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_Immediate_i64;
operand.mImmediate = immediate;
return operand;
}
static BeMCOperand FromBlock(BeMCBlock* block)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_Block;
operand.mBlock = block;
return operand;
}
static BeMCOperand FromSymbol(int symIdx)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_Symbol;
operand.mSymbolIdx = symIdx;
return operand;
}
2019-08-23 11:56:54 -07:00
static BeMCOperand FromSymbolAddr(int symIdx)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_SymbolAddr;
operand.mSymbolIdx = symIdx;
return operand;
}
2019-08-23 11:56:54 -07:00
static BeMCOperand FromPreserveFlag(BeMCPreserveFlag preserveFlag)
{
BeMCOperand operand;
operand.mKind = BeMCOperandKind_PreserveFlag;
operand.mPreserveFlag = preserveFlag;
return operand;
}
};
struct BeNotResult
{
BeValue* mValue;
};
enum BeMCInstKind
{
// Psuedo instructions, must be legalized
BeMCInstKind_None,
BeMCInstKind_Def,
BeMCInstKind_DefLoad,
BeMCInstKind_DefPhi,
BeMCInstKind_DbgDecl,
BeMCInstKind_LifetimeExtend,
BeMCInstKind_LifetimeStart,
BeMCInstKind_LifetimeEnd,
BeMCInstKind_LifetimeSoftEnd,
2019-08-23 11:56:54 -07:00
BeMCInstKind_ValueScopeSoftEnd,
BeMCInstKind_ValueScopeHardEnd,
BeMCInstKind_Label,
2019-08-23 11:56:54 -07:00
BeMCInstKind_CmpToBool,
BeMCInstKind_MemSet,
BeMCInstKind_MemCpy,
BeMCInstKind_FastCheckStack,
BeMCInstKind_TLSSetup,
BeMCInstKind_PreserveVolatiles,
BeMCInstKind_RestoreVolatiles,
BeMCInstKind_Unwind_PushReg,
BeMCInstKind_Unwind_SaveXMM,
BeMCInstKind_Unwind_Alloc,
BeMCInstKind_Unwind_SetBP,
2019-08-23 11:56:54 -07:00
BeMCInstKind_Rem,
BeMCInstKind_IRem,
2019-08-23 11:56:54 -07:00
// Legal instructions
BeMCInstKind_Nop,
BeMCInstKind_Unreachable,
BeMCInstKind_EnsureInstructionAt,
BeMCInstKind_DbgBreak,
BeMCInstKind_MFence,
BeMCInstKind_Mov,
2019-08-23 11:56:54 -07:00
BeMCInstKind_MovRaw,
BeMCInstKind_MovSX,
2019-08-23 11:56:54 -07:00
BeMCInstKind_XChg,
BeMCInstKind_XAdd,
BeMCInstKind_CmpXChg,
BeMCInstKind_Load,
BeMCInstKind_Store,
BeMCInstKind_Push,
BeMCInstKind_Pop,
BeMCInstKind_Neg,
BeMCInstKind_Not,
BeMCInstKind_Add,
2019-08-23 11:56:54 -07:00
BeMCInstKind_Sub,
BeMCInstKind_Mul,
BeMCInstKind_IMul,
BeMCInstKind_Div,
BeMCInstKind_IDiv,
BeMCInstKind_Cmp,
2019-08-23 11:56:54 -07:00
BeMCInstKind_And,
BeMCInstKind_Or,
BeMCInstKind_Xor,
BeMCInstKind_Shl,
BeMCInstKind_Shr,
BeMCInstKind_Sar,
BeMCInstKind_Test,
BeMCInstKind_CondBr,
BeMCInstKind_Br,
BeMCInstKind_Ret,
BeMCInstKind_Call,
BeMCInstKind_COUNT
};
struct BeVTrackingBits;
struct BeMCVRegArray
{
int mSize;
int mVRegIndices[1];
};
struct BeVRegLastUseRecord
{
int mVRegIdx;
BeVRegLastUseRecord* mNext;
};
2019-08-23 11:56:54 -07:00
class BeMCInst
{
public:
BeMCInstKind mKind;
2022-01-11 10:36:22 -05:00
bool mDisableShortForm;
2019-08-23 11:56:54 -07:00
BeMCOperand mResult;
BeMCOperand mArg0;
BeMCOperand mArg1;
BeVTrackingList* mLiveness;
BeVTrackingList* mVRegsInitialized;
BeVRegLastUseRecord* mVRegLastUseRecord;
2019-08-23 11:56:54 -07:00
BeDbgLoc* mDbgLoc;
2019-08-23 11:56:54 -07:00
bool IsDef()
{
return (mKind == BeMCInstKind_Def) || (mKind == BeMCInstKind_DefLoad);
}
bool IsAssignment()
{
return (IsMov()) || (mKind == BeMCInstKind_Load);
}
bool IsMov()
{
return (mKind >= BeMCInstKind_Mov) && (mKind <= BeMCInstKind_MovSX);
}
bool IsMul()
{
return (mKind == BeMCInstKind_Mul) || (mKind == BeMCInstKind_IMul);
}
bool IsCommutable()
{
return (mKind == BeMCInstKind_Add) || (mKind == BeMCInstKind_Mul) || (mKind == BeMCInstKind_IMul);
}
bool IsShift()
{
return (mKind >= BeMCInstKind_Shl) && (mKind <= BeMCInstKind_Sar);
}
bool IsInformational()
{
return (mKind <= BeMCInstKind_Label);
}
bool IsPsuedo()
{
return (mKind <= BeMCInstKind_Unwind_SetBP);
}
2019-08-23 11:56:54 -07:00
BeMCOperand* GetDest()
{
if (mResult)
return &mResult;
switch (mKind)
{
case BeMCInstKind_Rem:
case BeMCInstKind_IRem:
case BeMCInstKind_MemSet:
case BeMCInstKind_MemCpy:
case BeMCInstKind_Mov:
case BeMCInstKind_MovSX:
case BeMCInstKind_Store:
case BeMCInstKind_Pop:
case BeMCInstKind_Neg:
case BeMCInstKind_Add:
case BeMCInstKind_Sub:
case BeMCInstKind_Mul:
case BeMCInstKind_IMul:
case BeMCInstKind_Div:
case BeMCInstKind_IDiv:
case BeMCInstKind_And:
case BeMCInstKind_Or:
case BeMCInstKind_Xor:
2019-08-23 11:56:54 -07:00
case BeMCInstKind_Shl:
case BeMCInstKind_Shr:
case BeMCInstKind_Sar:
return &mArg0;
}
2019-08-23 11:56:54 -07:00
return NULL;
}
2019-08-23 11:56:54 -07:00
};
class BeMCBlock
{
public:
String mName;
Array<BeMCInst*> mInstructions;
int mLabelIdx;
Array<BeMCBlock*> mPreds;
Array<BeMCBlock*> mSuccs;
int mBlockIdx;
int mMaxDeclBlockId; // If blocks merge, this is the highest index
bool mIsLooped;
2022-06-27 15:56:15 -07:00
bool mHasFakeBr;
2019-08-23 11:56:54 -07:00
BeVTrackingList* mSuccLiveness;
BeVTrackingList* mSuccVRegsInitialized;
BeVTrackingList* mPredVRegsInitialized;
// a lexical block can end in more than one MCBlock, in the case of branching
Array<BeDbgLexicalBlock*> mDbgEndingLexicalBlock;
public:
BeMCBlock()
{
mLabelIdx = -1;
mIsLooped = false;
2022-06-27 15:56:15 -07:00
mHasFakeBr = false;
2019-08-23 11:56:54 -07:00
mBlockIdx = -1;
mMaxDeclBlockId = -1;
mSuccLiveness = NULL;
mSuccVRegsInitialized = NULL;
mPredVRegsInitialized = NULL;
}
void AddPred(BeMCBlock* pred);
2019-08-23 11:56:54 -07:00
int FindLabelInstIdx(int labelIdx);
};
2020-06-13 09:49:16 -07:00
class BeMCContext;
class BeInstEnumerator
{
public:
2020-06-13 09:49:16 -07:00
BeMCContext* mContext;
BeMCBlock* mBlock;
int mReadIdx;
int mWriteIdx;
bool mRemoveCurrent;
public:
2020-06-13 09:49:16 -07:00
BeInstEnumerator(BeMCContext* context, BeMCBlock* block)
{
2020-06-13 09:49:16 -07:00
mContext = context;
mBlock = block;
mReadIdx = 0;
mWriteIdx = 0;
mRemoveCurrent = false;
}
~BeInstEnumerator()
{
if (mReadIdx >= mBlock->mInstructions.mSize)
{
mBlock->mInstructions.mSize = mWriteIdx;
}
}
2020-06-13 09:49:16 -07:00
void Next();
bool HasMore()
{
return mReadIdx < mBlock->mInstructions.mSize;
}
void RemoveCurrent()
{
mRemoveCurrent = true;
}
BeMCInst* Get()
{
return mBlock->mInstructions[mReadIdx];
}
};
2019-08-23 11:56:54 -07:00
class BeMCPhiValue
{
public:
BeMCBlock* mBlockFrom;
BeMCOperand mValue;
2019-08-23 11:56:54 -07:00
int mLandingLabel;
};
class BeMCPhi
{
public:
BeMCBlock* mBlock;
2019-08-23 11:56:54 -07:00
Array<BeMCPhiValue> mValues;
int mIdx;
BeMCOperand mBrTrue;
BeMCOperand mBrFalse;
};
enum BeMCRMMode
{
BeMCRMMode_Invalid,
BeMCRMMode_Direct,
BeMCRMMode_Deref
2019-08-23 11:56:54 -07:00
};
enum BeMCValueScopeRetainKind : uint8
{
BeMCValueScopeRetainKind_None,
BeMCValueScopeRetainKind_Soft,
BeMCValueScopeRetainKind_Hard
};
class BeMCVRegInfo
{
public:
X64CPURegister mReg;
2022-07-27 12:26:36 -04:00
X64CPURegister mNaturalReg; // From param
2019-08-23 11:56:54 -07:00
BeType* mType;
int mAlign;
2019-08-23 11:56:54 -07:00
int mFrameOffset; // 0 = 'RBP' (probably first local var or saved RBP), 8 means retAddr
bool mRegNumPinned;
bool mHasDynLife;
bool mDoConservativeLife; // Keep alive through 'init' as well as 'uninit'
2022-07-27 12:26:36 -04:00
bool mIsExpr; // Not an actual value, something like 'mRelTo + mRelOffset'
2019-08-23 11:56:54 -07:00
bool mWantsExprActualize;
bool mWantsExprOffsetActualize;
2019-08-23 11:56:54 -07:00
bool mChainLifetimeEnd; // Kill relTo's when we are killed
bool mForceMem;
bool mForceReg;
bool mSpilled;
BeMCValueScopeRetainKind mValueScopeRetainedKind;
bool mAwaitingDbgStart;
bool mHasAmbiguousInitialization;
2019-08-23 11:56:54 -07:00
bool mIsRetVal;
bool mForceMerge; // Original param, not the 'debug holder'
bool mDefOnFirstUse;
bool mDisableR11; // Special case when this vreg is reserved for temporary (it's the last volatile int reg)
bool mDisableR12; // Special case when this vreg is used in an ModRM scale, which isn't allowed
bool mDisableR13; // Special case when this vreg is used in an ModRM scale, which isn't allowed
bool mDisableRAX; // Special case when RAX must be preserved (ie: For IDIV)
bool mDisableRDX; // Special case when RDX must be preserved (ie: For IDIV)
2022-07-27 12:26:36 -04:00
bool mDisableEx; // Disable any registers that require a REX
2019-08-23 11:56:54 -07:00
int mVRegAffinity; // Try to match the mReg of this vreg
BeMCOperand mRelTo;
int mRelOffsetScale;
BeMCOperand mRelOffset;
2019-08-23 11:56:54 -07:00
int mVolatileVRegSave;
BeDbgVariable* mDbgVariable;
2019-08-23 11:56:54 -07:00
bool mFoundLastUse;
2019-08-23 11:56:54 -07:00
bool mMustExist; // Regs we must be able to debug
2022-07-27 12:26:36 -04:00
// Must be refreshed with RefreshRefCounts
2019-08-23 11:56:54 -07:00
int mRefCount;
int mAssignCount;
2019-08-23 11:56:54 -07:00
public:
BeMCVRegInfo()
{
mAlign = -1;
mRegNumPinned = false;
2019-08-23 11:56:54 -07:00
mReg = X64Reg_None;
mNaturalReg = X64Reg_None;
mType = NULL;
2019-08-23 11:56:54 -07:00
mIsExpr = false;
mWantsExprActualize = false;
mWantsExprOffsetActualize = false;
2019-08-23 11:56:54 -07:00
mChainLifetimeEnd = false;
mFrameOffset = INT_MIN;
mHasDynLife = false;
mDoConservativeLife = false;
mForceMem = false;
mSpilled = false;
mValueScopeRetainedKind = BeMCValueScopeRetainKind_None;
mForceReg = false;
mAwaitingDbgStart = false;
mHasAmbiguousInitialization = false;
mForceMerge = false;
mDefOnFirstUse = false;
mDisableR11 = false;
mDisableR12 = false;
mDisableR13 = false;
mDisableRAX = false;
mDisableRDX = false;
mDisableEx = false;
mVRegAffinity = -1;
mRelOffsetScale = 1;
mDbgVariable = NULL;
mRefCount = -1;
mAssignCount = -1;
mVolatileVRegSave = -1;
mMustExist = false;
mIsRetVal = false;
mFoundLastUse = false;
2019-08-23 11:56:54 -07:00
}
bool CanEliminate()
{
return (!mIsExpr) && (!mMustExist);
}
bool CanUserModify()
{
if (mDbgVariable == NULL)
return false;
// In Beef, the debugger cannot modify param values (just as the language user can't)
return mDbgVariable->mParamNum == -1;
}
bool IsDirectRelTo()
{
return ((mRelTo.mKind == BeMCOperandKind_VReg) || (mRelTo.mKind == BeMCOperandKind_NativeReg)) &&
(mRelOffset.IsZero()) && (mRelOffsetScale == 1);
2019-08-23 11:56:54 -07:00
}
bool IsDirectRelToAny()
{
return (mRelTo) && (mRelOffset.IsZero()) && (mRelOffsetScale == 1);
}
2019-08-23 11:56:54 -07:00
void SetRetVal()
{
//BF_ASSERT(!mForceMem);
mForceReg = true;
mIsRetVal = true;
}
};
enum BeMCInstForm
{
BeMCInstForm_Unknown,
BeMCInstForm_R8_RM8,
BeMCInstForm_R16_RM16,
BeMCInstForm_R32_RM32,
BeMCInstForm_R64_RM64,
2019-08-23 11:56:54 -07:00
BeMCInstForm_R8_RM64_ADDR,
BeMCInstForm_R16_RM64_ADDR,
BeMCInstForm_R32_RM64_ADDR,
BeMCInstForm_R64_RM64_ADDR,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM8_R8,
BeMCInstForm_RM16_R16,
BeMCInstForm_RM32_R32,
BeMCInstForm_RM64_R64,
BeMCInstForm_RM64_R8_ADDR,
BeMCInstForm_RM64_R16_ADDR,
BeMCInstForm_RM64_R32_ADDR,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM64_R64_ADDR,
BeMCInstForm_RM8_IMM8,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM16_IMM8,
BeMCInstForm_RM32_IMM8,
BeMCInstForm_RM64_IMM8,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM16_IMM16,
BeMCInstForm_RM32_IMM16,
BeMCInstForm_RM64_IMM16,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM32_IMM32,
BeMCInstForm_RM64_IMM32,
2019-08-23 11:56:54 -07:00
BeMCInstForm_RM64_IMM64,
BeMCInstForm_RM8,
BeMCInstForm_RM16,
BeMCInstForm_RM32,
BeMCInstForm_RM64,
2019-08-23 11:56:54 -07:00
BeMCInstForm_IMM32,
BeMCInstForm_R8,
BeMCInstForm_R16,
BeMCInstForm_R32,
BeMCInstForm_R64,
2024-11-20 06:05:52 -05:00
// FRM32 = float, FRM64 = double
2019-08-23 11:56:54 -07:00
BeMCInstForm_XMM32_IMM,
BeMCInstForm_XMM64_IMM,
2024-11-20 06:05:52 -05:00
BeMCInstForm_XMM32_FRM32,
2019-08-23 11:56:54 -07:00
BeMCInstForm_XMM64_FRM32,
BeMCInstForm_XMM32_FRM64,
BeMCInstForm_XMM64_FRM64,
2019-08-23 11:56:54 -07:00
BeMCInstForm_FRM32_XMM32,
BeMCInstForm_FRM64_XMM32,
BeMCInstForm_FRM32_XMM64,
BeMCInstForm_FRM64_XMM64,
2020-08-23 05:42:42 -07:00
BeMCInstForm_FRM128_XMM128,
2019-08-23 11:56:54 -07:00
BeMCInstForm_XMM32_RM32,
BeMCInstForm_XMM64_RM32,
BeMCInstForm_XMM32_RM64,
BeMCInstForm_XMM64_RM64,
2020-08-23 05:42:42 -07:00
BeMCInstForm_XMM128_RM128,
BeMCInstForm_R32_F32,
2019-08-23 11:56:54 -07:00
BeMCInstForm_R64_F32,
BeMCInstForm_R32_F64,
BeMCInstForm_R64_F64,
BeMCInstForm_Symbol,
BeMCInstForm_SymbolAddr
};
class BeCOFFObject;
class BeMCContext;
enum BeTrackKind
{
BetTrackKind_Default = 0,
// Liveness
BeTrackKind_Exists = 0,
2019-08-23 11:56:54 -07:00
// Initialized
BeTrackKind_Initialized = 0,
BeTrackKind_Uninitialized = 1, // Tracks from DbgDecl through to initialization
BeTrackKind_COUNT = 2
};
// BeVTrackingEntry is immutable -- the Set/Clear/Merge methods allocate new entries if
// the requested change produces a new liveness set
class BeVTrackingContext
{
public:
struct Stats
{
int mBitsBytes;
int mListBytes;
int mSuccBytes;
Stats()
{
mBitsBytes = 0;
mListBytes = 0;
mSuccBytes = 0;
}
};
public:
Stats mStats;
BumpAllocator mAlloc;
BeMCContext* mMCContext;
int mNumEntries;
int mNumItems;
int mNumBlocks; // # of entries in mBits
int mTrackKindCount;
public:
BeVTrackingContext(BeMCContext* mcContext);
2019-08-23 11:56:54 -07:00
void Init(int numItems);
void Clear();
int GetBitsBytes();
int GetIdx(int baseIdx, BeTrackKind trackKind);
2019-08-23 11:56:54 -07:00
void Print(BeVTrackingList* list);
BeVTrackingList* AllocEmptyList();
BeVTrackingList* AddFiltered(BeVTrackingList* list, SizedArrayImpl<int>& indices, bool perserveChangeList);
BeVTrackingList* AddFiltered(BeVTrackingList* list, int idx, bool perserveChangeList);
2019-08-23 11:56:54 -07:00
BeVTrackingList* Add(BeVTrackingList* list, const SizedArrayImpl<int>& indices, bool perserveChangeList);
BeVTrackingList* Add(BeVTrackingList* list, int idx, bool perserveChangeList);
2019-08-23 11:56:54 -07:00
BeVTrackingList* ClearFiltered(BeVTrackingList* list, const SizedArrayImpl<int>& indices);
BeVTrackingList* Modify(BeVTrackingList* list, const SizedArrayImpl<int>& adds, const SizedArrayImpl<int>& removes, SizedArrayImpl<int>& filteredAdds, SizedArrayImpl<int>& filteredRemoves, bool preserveChanges = false);
2019-08-23 11:56:54 -07:00
int FindIndex(BeVTrackingList* entry, int val);
bool IsSet(BeVTrackingList* entry, int idx);
bool IsSet(BeVTrackingList* entry, int idx, BeTrackKind trackKind);
BeVTrackingList* Clear(BeVTrackingList* list, const SizedArrayImpl<int>& indices);
bool IsEmpty(BeVTrackingList* list);
BeVTrackingList* Merge(BeVTrackingList* prevDestEntry, BeVTrackingList* mergeFrom);
BeVTrackingList* MergeChanges(BeVTrackingList* prevDestEntry, BeVTrackingList* mergeFrom);
2019-08-23 11:56:54 -07:00
BeVTrackingList* SetChanges(BeVTrackingList* prevDestEntry, BeVTrackingList* mergeFrom);
BeVTrackingList* RemoveChange(BeVTrackingList* prevDestEntry, int idx);
};
class BeMCLoopDetector
{
public:
class Node
{
public:
BeVTrackingList* mPredBlocksSeen;
public:
Node()
{
mPredBlocksSeen = NULL;
}
};
BeVTrackingContext mTrackingContext;
BeMCContext* mMCContext;
Array<Node> mNodes;
BfBitSet mBitSet;
2019-08-23 11:56:54 -07:00
public:
BeMCLoopDetector(BeMCContext* context);
void DetectLoops(BeMCBlock* mcBlock, BeVTrackingList* blocksSeen);
void DetectLoops(BeMCBlock* mcBlock);
2019-08-23 11:56:54 -07:00
void DetectLoops();
};
class BeMCColorizer
{
public:
2019-08-23 11:56:54 -07:00
struct Node
{
HashSet<int> mEdges;
int mGraphEdgeCount;
bool mInGraph;
bool mSpilled;
bool mWantsReg;
int mRegCost[X64Reg_COUNT];
int mLowestRegCost;
int mMemCost;
//int mActualVRegIdx;
Node()
{
Prepare();
}
void AdjustRegCost(X64CPURegister reg, int adjust)
{
BF_ASSERT((int)reg >= 0);
BF_ASSERT((int)reg < X64Reg_COUNT);
int newCost = mRegCost[(int)reg] + adjust;
mRegCost[(int)reg] = newCost;
if (newCost < mLowestRegCost)
mLowestRegCost = newCost;
}
void Prepare()
{
mWantsReg = false;
mInGraph = false;
mSpilled = false;
mGraphEdgeCount = 0;
mLowestRegCost = 0;
mMemCost = 0;
memset(mRegCost, 0, sizeof(mRegCost));
//mActualVRegIdx = -1;
}
};
struct BlockInfo
{
HashSet<X64CPURegister> mSuccLiveRegs;
bool mEntryCount;
2019-08-23 11:56:54 -07:00
BlockInfo()
{
mEntryCount = 0;
2019-08-23 11:56:54 -07:00
}
};
enum RegKind
{
RegKind_Ints,
RegKind_Floats,
};
Array<BlockInfo> mBlockInfo;
Array<Node> mNodes;
BeMCContext* mContext;
2019-08-23 11:56:54 -07:00
bool mReserveParamRegs;
public:
BeMCColorizer(BeMCContext* mcContext);
2019-08-23 11:56:54 -07:00
void Prepare();
void AddEdge(int vreg0, int vreg1);
2019-08-23 11:56:54 -07:00
void PropogateMemCost(const BeMCOperand& operand, int memCost);
void GenerateRegCosts();
void AssignRegs(RegKind regKind); // Returns false if we had spills - we need to rerun
bool Validate();
};
struct BeMCDefState
{
public:
BeMCInst* mInst;
BeMCBlock* mBlock;
public:
BeMCDefState()
{
mInst = NULL;
mBlock = NULL;
}
};
// This chains remaps for InstCombine
class BeMCRemapper
{
public:
struct Node
{
int mTo;
int mFrom;
Node()
{
mTo = -1;
mFrom = -1;
}
};
Array<Node> mNodes;
public:
void Init(int size)
{
mNodes.Resize(size);
}
void Add(int from, int toOrig)
{
auto fromNode = &mNodes[from];
if (fromNode->mTo != -1)
return; // Silently fail if we've already remapped
// Chain to end
int to = toOrig;
while (true)
{
auto toNode = &mNodes[to];
if (toNode->mFrom != -1)
{
to = toNode->mFrom;
continue;
}
toNode->mFrom = from;
fromNode->mTo = to;
return;
}
2019-08-23 11:56:54 -07:00
}
int GetHead(int idx)
{
while (true)
{
auto node = &mNodes[idx];
if (node->mTo == -1)
return idx;
idx = node->mTo;
}
}
int GetNext(int idx)
{
return mNodes[idx].mFrom;
}
};
struct BeMCSwitchEntry
{
BeMCBlock* mBlock;
int mOfs;
};
enum BeMCNativeTypeCode
{
BeMCNativeTypeCode_Int8,
BeMCNativeTypeCode_Int16,
BeMCNativeTypeCode_Int32,
BeMCNativeTypeCode_Int64,
BeMCNativeTypeCode_Float,
BeMCNativeTypeCode_Double,
2020-08-23 05:42:42 -07:00
BeMCNativeTypeCode_M128,
BeMCNativeTypeCode_M256,
BeMCNativeTypeCode_M512,
2019-08-23 11:56:54 -07:00
BeMCNativeTypeCode_COUNT
};
enum BeMCBinIdentityKind
{
BeMCBinIdentityKind_None,
BeMCBinIdentityKind_Right_IsOne,
BeMCBinIdentityKind_Right_IsZero,
BeMCBinIdentityKind_Right_IsOne_Result_Zero,
BeMCBinIdentityKind_Any_IsOne,
BeMCBinIdentityKind_Any_IsZero
};
struct BeMCLivenessStats
{
int mCalls;
int mHandledCalls;
int mInstructions;
};
class BeVTrackingGenContext
{
public:
struct Entry
{
bool mGenerateQueued;
int mGenerateCount;
Entry()
{
2019-08-23 11:56:54 -07:00
mGenerateQueued = false;
mGenerateCount = 0;
}
};
int mCalls;
int mHandledCalls;
int mInstructions;
Array<Entry> mBlocks;
BeVTrackingList* mEmptyList;
BumpAllocator mAlloc;
public:
BeVTrackingGenContext()
{
mCalls = 0;
mHandledCalls = 0;
mInstructions = 0;
2019-08-23 11:56:54 -07:00
mEmptyList = NULL;
}
};
struct BeRMParamsInfo
{
X64CPURegister mRegA;
X64CPURegister mRegB;
int mBScale;
int mDisp;
BeMCRMMode mMode;
int mErrorVReg;
int mVRegWithScaledOffset;
BeRMParamsInfo()
{
mRegA = X64Reg_None;
mRegB = X64Reg_None;
mBScale = 1;
mDisp = 0;
mMode = BeMCRMMode_Invalid;
mErrorVReg = -1;
mVRegWithScaledOffset = -1;
}
};
2022-01-11 08:17:09 -05:00
enum BeMCOverflowCheckKind
{
BeMCOverflowCheckKind_None,
BeMCOverflowCheckKind_B,
BeMCOverflowCheckKind_O
};
2019-08-23 11:56:54 -07:00
// This class only processes one function per instantiation
class BeMCContext
{
public:
BeCOFFObject* mCOFFObject;
DynMemStream& mOut;
2019-08-23 11:56:54 -07:00
bool mDebugging;
bool mFailed;
int mDetectLoopIdx;
2019-08-23 11:56:54 -07:00
BeVTrackingContext mLivenessContext;
BeVTrackingContext mVRegInitializedContext;
OwnedVector<BeMCBlock> mMCBlockAlloc;
OwnedVector<BeMCPhi> mPhiAlloc;
BeMCColorizer mColorizer;
BumpAllocator mAlloc;
Array<BeMCBlock*> mBlocks;
Dictionary<BeValue*, BeMCOperand> mValueToOperand;
BeType* mNativeIntType;
BeModule* mModule;
BeMCBlock* mActiveBlock;
BeMCInst* mActiveInst;
2019-08-23 11:56:54 -07:00
int* mInsertInstIdxRef;
BeBlock* mActiveBeBlock;
BeFunction* mBeFunction;
2019-08-23 11:56:54 -07:00
BeDbgFunction* mDbgFunction;
Array<BeMCVRegInfo*> mVRegInfo;
Array<BeCmpResult> mCmpResults;
int mCompositeRetVRegIdx;
int mTLSVRegIdx;
int mLegalizationIterations;
2019-08-23 11:56:54 -07:00
Array<int> mCallArgVRegs[BeMCNativeTypeCode_COUNT];
int mStackSize;
bool mUseBP;
2021-01-22 04:58:08 -08:00
bool mHasVAStart;
2019-08-23 11:56:54 -07:00
int mCurLabelIdx;
int mCurPhiIdx;
2019-08-23 11:56:54 -07:00
int mMaxCallParamCount; // -1 if we have no calls
Array<X64CPURegister> mParamsUsedRegs;
HashSet<X64CPURegister> mUsedRegs;
2019-08-23 11:56:54 -07:00
BeDbgLoc* mCurDbgLoc;
BeVTrackingList* mCurVRegsInit;
BeVTrackingList* mCurVRegsLive;
Array<int> mTextRelocs;
Array<BeMCSwitchEntry> mSwitchEntries;
2019-08-23 11:56:54 -07:00
Dictionary<int, X64CPURegister> mDbgPreferredRegs;
public:
2019-08-23 11:56:54 -07:00
void NotImpl();
void Fail(const StringImpl& str);
2020-09-01 15:56:03 -07:00
void AssertFail(const StringImpl& str, int line);
void SoftFail(const StringImpl& str, BeDbgLoc* dbgLoc = NULL);
2019-08-23 11:56:54 -07:00
void ToString(BeMCInst* inst, String& str, bool showVRegFlags, bool showVRegDetails);
String ToString(const BeMCOperand& operand);
String ToString(bool showVRegFlags = true, bool showVRegDetails = false);
void Print(bool showVRegFlags, bool showVRegDetails);
void Print();
2022-05-13 14:07:40 -07:00
BeMCOperand GetOperand(BeValue* value, bool allowMetaResult = false, bool allowFail = false, bool skipForceVRegAddr = false); // Meta results are PHIs or CmpResults
2019-08-23 11:56:54 -07:00
BeMCOperand CreateNot(const BeMCOperand& operand);
2020-08-23 05:42:42 -07:00
BeMCOperand TryToVector(BeValue* value);
BeType* GetType(const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
bool AreTypesEquivalent(BeType* type0, BeType* type1);
void AddRelRefs(BeMCOperand& operand, int refCount);
int FindSafeInstInsertPos(int instIdx, bool forceSafeCheck = false);
BeMCInst* AllocInst(int insertIdx = -1);
BeMCInst* AllocInst(BeMCInstKind instKind, int insertIdx = -1);
BeMCInst* AllocInst(BeMCInstKind instKind, const BeMCOperand& arg0, int insertIdx = -1);
BeMCInst* AllocInst(BeMCInstKind instKind, const BeMCOperand& arg0, const BeMCOperand& arg1, int insertIdx = -1);
2020-06-13 09:49:16 -07:00
void MergeInstFlags(BeMCInst* prevInst, BeMCInst* inst, BeMCInst* nextInst);
void RemoveInst(BeMCBlock* block, int instIdx, bool needChangesMerged = true, bool removeFromList = true);
2022-01-11 08:17:09 -05:00
BeMCOperand AllocBinaryOp(BeMCInstKind instKind, const BeMCOperand & lhs, const BeMCOperand & rhs, BeMCBinIdentityKind identityKind, BeMCOverflowCheckKind overflowCheckKind = BeMCOverflowCheckKind_None);
BeMCOperand GetCallArgVReg(int argIdx, BeTypeCode typeCode);
2019-08-23 11:56:54 -07:00
BeMCOperand CreateCall(const BeMCOperand& func, const SizedArrayImpl<BeMCOperand>& args, BeType* retType = NULL, BfIRCallingConv callingConv = BfIRCallingConv_CDecl, bool structRet = false, bool noReturn = false, bool isVarArg = false);
BeMCOperand CreateCall(const BeMCOperand& func, const SizedArrayImpl<BeValue*>& args, BeType* retType = NULL, BfIRCallingConv callingConv = BfIRCallingConv_CDecl, bool structRet = false, bool noReturn = false, bool isVarArg = false);
2019-08-23 11:56:54 -07:00
BeMCOperand CreateLoad(const BeMCOperand& mcTarget);
void CreateStore(BeMCInstKind instKind, const BeMCOperand& val, const BeMCOperand& ptr);
void CreateMemSet(const BeMCOperand& addr, uint8 val, int size, int align);
void CreateMemCpy(const BeMCOperand& dest, const BeMCOperand& src, int size, int align);
void CreateTableSwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx);
void CreateBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx);
void CreateCondBr(BeMCBlock* mcBlock, BeMCOperand& testVal, const BeMCOperand& trueBlock, const BeMCOperand& falseBlock);
void CreatePhiAssign(BeMCBlock* mcBlock, const BeMCOperand& testVal, const BeMCOperand& result, const BeMCOperand& doneLabel);
2019-08-23 11:56:54 -07:00
BeMCOperand GetImmediate(int64 val);
BeMCOperand OperandToAddr(const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
BeMCOperand GetVReg(int regNum);
BeMCOperand AllocVirtualReg(BeType* type, int refCount = -1, bool mustBeReg = false);
int GetUnderlyingVReg(int vregIdx);
bool HasForceRegs(const BeMCOperand& operand);
bool OperandsEqual(const BeMCOperand& op0, const BeMCOperand& op1, bool exact = false);
bool ContainsNonOffsetRef(const BeMCOperand& checkOperand, const BeMCOperand& findOperand);
BeMCInst* CreateDefineVReg(const BeMCOperand& vreg, int insertIdx = -1);
int CreateLabel(int insertIdx = -1, int labelIdx = -1);
bool FindTarget(const BeMCOperand& loc, BeMCBlock*& outBlock, int& outInstIdx);
BeMCOperand AllocRelativeVirtualReg(BeType* type, const BeMCOperand& relTo, const BeMCOperand& relOffset, int relScale);
2019-08-23 11:56:54 -07:00
BeMCVRegInfo* GetVRegInfo(const BeMCOperand& operand);
bool HasSymbolAddr(const BeMCOperand& operand);
2020-05-22 06:39:12 -07:00
BeMCOperand ReplaceWithNewVReg(BeMCOperand& operand, int& instIdx, bool isInput, bool mustBeReg = true, bool preserveDeref = false);
BeMCOperand RemapOperand(BeMCOperand& operand, BeMCRemapper& regRemaps);
2019-08-23 11:56:54 -07:00
bool IsLive(BeVTrackingList* liveRegs, int vregIdx, BeMCRemapper& regRemaps);
void AddRegRemap(int from, int to, BeMCRemapper& regRemaps, bool allowRemapToDbgVar = false);
bool GetEncodedOperand(const BeMCOperand& operand, int& vregAddrIdx);
bool HasPointerDeref(const BeMCOperand& operand);
bool AreOperandsEquivalent(const BeMCOperand& op1, const BeMCOperand& op2, BeMCRemapper& regRemaps);
2019-08-23 11:56:54 -07:00
bool CouldBeReg(const BeMCOperand& operand);
bool CheckForce(BeMCVRegInfo* vregInfo);
void MarkLive(BeVTrackingList* liveRegs, SizedArrayImpl<int>& newRegs, BeVTrackingList*& initRegs, const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
BeVTrackingList* MergeLiveRegs(BeVTrackingList* prevDestEntry, BeVTrackingList* mergeFrom);
void GenerateLiveness(BeMCBlock* block, BeVTrackingGenContext* genCtx, bool& modifiedBlockBefore, bool& modifiedBlockAfter);
void GenerateLiveness();
2019-08-23 11:56:54 -07:00
void IntroduceVRegs(const BeMCOperand& newVReg, BeMCBlock* block, int startInstIdx, int lastInstIdx);
void VRegSetInitialized(BeMCBlock* mcBlock, BeMCInst* inst, const BeMCOperand& operand, SizedArrayImpl<int>& addVec, SizedArrayImpl<int>& removeVec, bool deepSet, bool doSet);
2019-08-23 11:56:54 -07:00
bool CheckVRegEqualityRange(BeMCBlock * mcBlock, int instIdx, const BeMCOperand & vreg0, const BeMCOperand & vreg1, BeMCRemapper& regRemaps, bool onlyCheckFirstLifetime = false);
BeMCInst* FindSafePreBranchInst(BeMCBlock* mcBlock);
void SimpleInitializedPass();
void DoLastUsePassHelper(BeMCInst* inst, const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
void InitializedPassHelper(BeMCBlock* block, BeVTrackingGenContext* genCtx, bool& modifiedBefore, bool& modifiedAfter);
void GenerateVRegInitFlags(BeVTrackingGenContext& genCtx);
void DoInitInjectionPass();
void ReplaceVRegsInit(BeMCBlock* mcBlock, int instIdx, BeVTrackingList* prevList, BeVTrackingList* newList);
void FixVRegInitFlags(BeMCInst* inst, const BeMCOperand& operand);
void SetVTrackingValue(BeMCOperand& operand, BeVTrackingValue& vTrackingValue);
2019-08-23 11:56:54 -07:00
bool IsVolatileReg(X64CPURegister reg);
bool IsXMMReg(X64CPURegister reg);
X64CPURegister ResizeRegister(X64CPURegister reg, int numBits);
2020-08-23 05:42:42 -07:00
X64CPURegister ResizeRegister(X64CPURegister reg, BeType* type);
X64CPURegister GetFullRegister(X64CPURegister reg);
bool HasLoad(const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
bool IsAddress(BeMCOperand& operand);
bool IsAddressable(BeMCOperand& operand);
bool IsVRegExpr(BeMCOperand& operand);
2020-08-23 05:42:42 -07:00
void FixOperand(BeMCOperand& operand, int depth = 0);
BeMCOperand GetFixedOperand(const BeMCOperand& operand);
2019-08-23 11:56:54 -07:00
uint8 GetREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit);
void EmitREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit);
2019-08-23 11:56:54 -07:00
uint8 EncodeRegNum(X64CPURegister regNum);
int GetRegSize(int regNum);
void ValidateRMResult(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true);
void GetRMParams(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true);
bool HasImmediateTarget(const BeMCOperand& operand);
void DisableRegister(const BeMCOperand& operand, X64CPURegister reg);
2019-08-23 11:56:54 -07:00
void MarkInvalidRMRegs(const BeMCOperand& operand);
void GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB); // Expands regs
BeMCRMMode GetRMForm(const BeMCOperand& operand, bool& isMulti);
void GetValAddr(const BeMCOperand& operand, X64CPURegister& reg, int& offset);
2019-08-23 11:56:54 -07:00
int GetHighestVRegRef(const BeMCOperand& operand);
BeMCInstForm GetInstForm(BeMCInst* inst);
2019-08-23 11:56:54 -07:00
BeMCInstForm ToIMM16(BeMCInstForm instForm);
BeMCInstForm ToIMM32OrSmaller(BeMCInstForm instForm);
void SetCurrentInst(BeMCInst* mcInst);
int FindPreserveVolatiles(BeMCBlock* mcBlock, int instIdx);
int FindRestoreVolatiles(BeMCBlock* mcBlock, int instIdx);
2019-08-23 11:56:54 -07:00
uint8 GetJumpOpCode(BeCmpKind cmpKind, bool isLong);
2020-08-27 10:11:42 -07:00
BeMCOperand IntXMMGetPacked(BeMCOperand arg, BeVectorType* vecType);
2019-08-23 11:56:54 -07:00
void Emit(uint8 val);
void EmitModRM(int mod, int reg, int rm);
void EmitModRMRelStack(int rx, int regOffset, int scale);
void EmitModRMRel(int rx, X64CPURegister regA, X64CPURegister regB, int bScale, int relOffset);
void EmitModRM(int rx, BeMCOperand rm, int relocOfs = 0);
void EmitModRM(BeMCOperand r, BeMCOperand rm, int relocOfs = 0);
void EmitModRM_Addr(BeMCOperand r, BeMCOperand rm);
2019-08-23 11:56:54 -07:00
void EmitModRM_XMM_IMM(int rx, BeMCOperand& imm);
void EmitInstPrefix(BeMCInstForm instForm, BeMCInst* inst);
void EmitInst(BeMCInstForm instForm, uint16 codeBytes, BeMCInst* inst);
void EmitInst(BeMCInstForm instForm, uint16 codeBytes, uint8 rx, BeMCInst* inst);
2019-08-23 11:56:54 -07:00
void EmitStdInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode_rm_r, uint8 opcode_r_rm, uint8 opcode_rm_imm, uint8 opcode_rm_imm_rx);
void EmitStdInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode_rm_r, uint8 opcode_r_rm, uint8 opcode_rm_imm, uint8 opcode_rm_imm_rx, uint8 opcode_rm_imm8, uint8 opcode_rm_imm8_rx);
2019-08-23 11:56:54 -07:00
bool EmitStdXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode);
bool EmitStdXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode, uint8 opcode_dest_frm);
2022-07-27 12:26:36 -04:00
bool EmitPackedXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode);
2020-08-27 10:11:42 -07:00
bool EmitIntXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode);
bool EmitIntBitwiseXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 opcode);
2019-08-23 11:56:54 -07:00
void EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src);
void DoTLSSetup();
void DoChainedBlockMerge();
void DoSplitLargeBlocks();
2019-08-23 11:56:54 -07:00
void DetectLoops();
void DoLastUsePass();
bool DoInitializedPass();
void RefreshRefCounts();
2019-08-23 11:56:54 -07:00
void DoInstCombinePass();
void DoRegAssignPass();
void DoFrameObjPass();
void DoActualization();
void DoLoads();
bool DoLegalization();
void DoSanityChecking();
void DoBlockCombine();
bool DoJumpRemovePass();
void DoRegFinalization();
void DoCodeEmission();
2019-08-23 11:56:54 -07:00
void HandleParams();
2019-08-23 11:56:54 -07:00
public:
BeMCContext(BeCOFFObject* coffObject);
void Generate(BeFunction* function);
};
NS_BF_END