#pragma once #include "BeefySysLib/Common.h" #include "BeefySysLib/util/HashSet.h" #include "../BumpList.h" #include "../Compiler/BfIRBuilder.h" #include "BeContext.h" #include "../X64.h" NS_BF_BEGIN class BeContext; class BeValue; class BeCallInst; class BeValue; class BeBlock; class BeArgument; class BeInst; class BeNopInst; class BeUnreachableInst; class BeEnsureInstructionAtInst; class BeUndefValueInst; class BeExtractValueInst; class BeInsertValueInst; class BeNumericCastInst; class BeBitCastInst; class BeNegInst; class BeNotInst; class BeBinaryOpInst; class BeCmpInst; class BeObjectAccessCheckInst; class BeAllocaInst; class BeLifetimeExtendInst; class BeAliasValueInst; class BeLifetimeStartInst; class BeLifetimeEndInst; class BeLifetimeFenceInst; class BeValueScopeStartInst; class BeValueScopeRetainInst; class BeValueScopeEndInst; class BeLoadInst; class BeStoreInst; class BeSetCanMergeInst; class BeMemSetInst; class BeFenceInst; class BeStackSaveInst; class BeStackRestoreInst; class BeGEPInst; class BeBrInst; class BeCondBrInst; class BePhiIncoming; class BePhiInst; class BeSwitchInst; class BeRetInst; class BeCallInst; class BeDbgVariable; class BeDbgDeclareInst; class BeValueVisitor { public: void VisitChild(BeValue* value); virtual void Visit(BeValue* beValue) {} virtual void Visit(BeBlock* beBlock) {} virtual void Visit(BeArgument* beArgument) {} virtual void Visit(BeInst* beInst) {} virtual void Visit(BeNopInst* nopInst) {} virtual void Visit(BeUnreachableInst* unreachableInst) {} virtual void Visit(BeEnsureInstructionAtInst* ensureCodeAtInst) {} virtual void Visit(BeUndefValueInst* undefValue) {} virtual void Visit(BeExtractValueInst* extractValue) {} virtual void Visit(BeInsertValueInst* insertValue) {} virtual void Visit(BeNumericCastInst* castInst) {} virtual void Visit(BeBitCastInst* castInst) {} virtual void Visit(BeNegInst* negInst) {} virtual void Visit(BeNotInst* notInst) {} virtual void Visit(BeBinaryOpInst* binaryOpInst) {} virtual void Visit(BeFenceInst* fenceInst) {} virtual void Visit(BeStackSaveInst* stackSaveInst) {} virtual void Visit(BeStackRestoreInst* stackRestoreInst) {} virtual void Visit(BeCmpInst* cmpInst) {} virtual void Visit(BeObjectAccessCheckInst* objectAccessCheckInst) {} virtual void Visit(BeAllocaInst* allocaInst) {} virtual void Visit(BeAliasValueInst* aliasValueInst) {} virtual void Visit(BeLifetimeExtendInst* lifetimeExtendInst) {} virtual void Visit(BeLifetimeStartInst* lifetimeStartInst) {} virtual void Visit(BeLifetimeEndInst* lifetimeEndInst) {} virtual void Visit(BeLifetimeFenceInst* lifetimeFenceInst) {} virtual void Visit(BeValueScopeStartInst* valueScopeStartInst) {} virtual void Visit(BeValueScopeRetainInst* valueScopeRetainInst) {} virtual void Visit(BeValueScopeEndInst* valueScopeEndInst) {} virtual void Visit(BeLoadInst* allocaInst) {} virtual void Visit(BeStoreInst* storeInst) {} virtual void Visit(BeSetCanMergeInst* setCanMergeInst) {} virtual void Visit(BeMemSetInst* memSetInst) {} virtual void Visit(BeGEPInst* gepInst) {} virtual void Visit(BeBrInst* brInst) {} virtual void Visit(BeCondBrInst* condBrInst) {} virtual void Visit(BePhiIncoming* phiIncomingInst) {} virtual void Visit(BePhiInst* phiInst) {} virtual void Visit(BeSwitchInst* switchInst) {} virtual void Visit(BeRetInst* retInst) {} virtual void Visit(BeCallInst* callInst) {} //virtual void Visit(BeDbgVariable* dbgVariable) {} virtual void Visit(BeDbgDeclareInst* dbgDeclareInst) {} }; class BeModule; class BeFunction; class BeDbgLoc; class BeInliner : public BeValueVisitor { public: BumpAllocator* mAlloc; OwnedVector* mOwnedValueVec; Dictionary mValueMap; Dictionary mInlinedAtMap; BeModule* mModule; BeFunction* mSrcFunc; BeFunction* mDestFunc; BeCallInst* mCallInst; BeBlock* mDestBlock; BeDbgLoc* mSrcDbgLoc; BeDbgLoc* mDestDbgLoc; public: BeInliner() { mSrcDbgLoc = NULL; mDestDbgLoc = NULL; } BeValue* Remap(BeValue* srcValue); BeDbgLoc* ExtendInlineDbgLoc(BeDbgLoc* srcInlineAt); void AddInst(BeInst* destInst, BeInst* srcInst); template T* AllocInst(T* srcInst) { auto inst = mAlloc->Alloc(); AddInst(inst, srcInst); return inst; } template T* AllocInstOwned(T* srcInst) { auto inst = mOwnedValueVec->Alloc(); AddInst(inst, srcInst); return inst; } virtual void Visit(BeValue* beValue) override; virtual void Visit(BeBlock* beBlock) override; virtual void Visit(BeArgument* beArgument) override; virtual void Visit(BeInst* beInst) override; virtual void Visit(BeNopInst* nopInst) override; virtual void Visit(BeUnreachableInst* unreachableInst) override; virtual void Visit(BeEnsureInstructionAtInst* ensureCodeAtInst) override; virtual void Visit(BeUndefValueInst* undefValue) override; virtual void Visit(BeExtractValueInst* extractValue) override; virtual void Visit(BeInsertValueInst* insertValue) override; virtual void Visit(BeNumericCastInst* castInst) override; virtual void Visit(BeBitCastInst* castInst) override; virtual void Visit(BeNegInst* negInst) override; virtual void Visit(BeNotInst* notInst) override; virtual void Visit(BeBinaryOpInst* binaryOpInst) override; virtual void Visit(BeCmpInst* cmpInst) override; virtual void Visit(BeFenceInst* fenceInst) override; virtual void Visit(BeStackSaveInst* stackSaveInst) override; virtual void Visit(BeStackRestoreInst* stackRestoreInst) override; virtual void Visit(BeObjectAccessCheckInst* objectAccessCheckInst) override; virtual void Visit(BeAllocaInst* allocaInst) override; virtual void Visit(BeAliasValueInst* aliasValueInst) override; virtual void Visit(BeLifetimeStartInst* lifetimeStartInst) override; virtual void Visit(BeLifetimeExtendInst* lifetimeExtendInst) override; virtual void Visit(BeLifetimeEndInst* lifetimeEndInst) override; virtual void Visit(BeLifetimeFenceInst* lifetimeFenceInst) override; virtual void Visit(BeValueScopeStartInst* valueScopeStartInst) override; virtual void Visit(BeValueScopeRetainInst* valueScopeRetainInst) override; virtual void Visit(BeValueScopeEndInst* valueScopeEndInst) override; virtual void Visit(BeLoadInst* allocaInst) override; virtual void Visit(BeStoreInst* storeInst) override; virtual void Visit(BeSetCanMergeInst* setCanMergeInst) override; virtual void Visit(BeMemSetInst* memSetInst) override; virtual void Visit(BeGEPInst* gepInst) override; virtual void Visit(BeBrInst* brInst) override; virtual void Visit(BeCondBrInst* condBrInst) override; virtual void Visit(BePhiIncoming* phiIncomingInst) override; virtual void Visit(BePhiInst* phiInst) override; virtual void Visit(BeSwitchInst* switchInst) override; virtual void Visit(BeRetInst* retInst) override; virtual void Visit(BeCallInst* callInst) override; virtual void Visit(BeDbgDeclareInst* dbgDeclareInst) override; }; class BeValue : public BeHashble { public: int mRefCount; #ifdef _DEBUG bool mLifetimeEnded; bool mWasRemoved; BeValue() { mLifetimeEnded = false; mWasRemoved = false; mRefCount = 0; } #else BeValue() { mRefCount = 0; } #endif virtual ~BeValue() { } static const int TypeId = 0; virtual void Accept(BeValueVisitor* beVisitor) = 0; virtual bool TypeIdIsA(int typeId) = 0; virtual BeValue* DynCast(int typeId) { if (TypeIdIsA(typeId)) return this; return NULL; } static bool ClassIsA(int typeId) { return typeId == 0; } virtual int GetTypeId() { return TypeId; } public: virtual BeType* GetType() { return NULL; } virtual void SetName(const StringImpl& name) { } }; #define BE_VALUE_TYPE(name, TBase) static const int TypeId = __LINE__; \ virtual void Accept(BeValueVisitor* beVisitor) override { beVisitor->Visit(this); } \ static bool ClassIsA(int typeId) { return (typeId == TypeId) || TBase::ClassIsA(typeId); } \ virtual bool TypeIdIsA(int typeId) override { return ClassIsA(typeId); } \ virtual int GetTypeId() override { return TypeId; } \ TBase* ToBase() { return (TBase*)this; } template T* BeValueDynCast(BeValue* value) { if (value == NULL) return NULL; BeValue* result = value->DynCast(T::TypeId); return (T*)result; } template T* BeValueDynCastExact(BeValue* value) { if (value == NULL) return NULL; if (value->GetTypeId() != T::TypeId) return NULL; return (T*)value; } class BeBlock; class BeInst; class BeModule; class BeDbgLoc; class BeMDNode; class BeGlobalVariable; class BeConstant; struct BeConstData { struct ConstantEntry { int mIdx; BeConstant* mConstant; }; Array mData; Array mConsts; }; class BeConstant : public BeValue { public: BE_VALUE_TYPE(BeConstant, BeValue); BeType* mType; union { bool mBool; int64 mInt64; int32 mInt32; int16 mInt16; int8 mInt8; uint64 mUInt64; uint32 mUInt32; uint16 mUInt16; uint8 mUInt8; uint8 mChar; uint32 mChar32; double mDouble; //BeType* mTypeParam; //BeGlobalVariable* mGlobalVar; BeConstant* mTarget; }; bool IsNull() { if (mType->mTypeCode == BeTypeCode_NullPtr) return true; return false; } virtual BeType* GetType(); virtual void GetData(BeConstData& data); virtual void HashContent(BeHashContext& hashCtx) override; }; class BeCastConstant : public BeConstant { public: BE_VALUE_TYPE(BeCastConstant, BeConstant); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mType->HashReference(hashCtx); mTarget->HashReference(hashCtx); } virtual void GetData(BeConstData& data) override { mTarget->GetData(data); } }; class BeGEPConstant : public BeConstant { public: BE_VALUE_TYPE(BeGEPConstant, BeConstant); int mIdx0; int mIdx1; virtual BeType* GetType(); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mTarget->HashReference(hashCtx); hashCtx.Mixin(mIdx0); hashCtx.Mixin(mIdx1); } }; class BeExtractValueConstant : public BeConstant { public: BE_VALUE_TYPE(BeExtractValueConstant, BeConstant); int mIdx0; virtual BeType* GetType(); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mTarget->HashReference(hashCtx); hashCtx.Mixin(mIdx0); } }; class BeStructConstant : public BeConstant { public: BE_VALUE_TYPE(BeStructConstant, BeConstant); SizedArray mMemberValues; virtual void GetData(BeConstData& data) override; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mType); hashCtx.Mixin(mMemberValues.size()); for (auto member : mMemberValues) member->HashReference(hashCtx); } }; class BeUndefConstant : public BeConstant { public: BE_VALUE_TYPE(BeUndefConstant, BeConstant); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(mType); hashCtx.Mixin(TypeId); } }; class BeStringConstant : public BeConstant { public: BE_VALUE_TYPE(BeStringConstant, BeConstant); String mString; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mString); } }; class BeGlobalVariable : public BeConstant { public: BE_VALUE_TYPE(BeGlobalVariable, BeConstant); BeModule* mModule; String mName; BeConstant* mInitializer; BfIRLinkageType mLinkageType; BfIRStorageKind mStorageKind; bool mIsConstant; bool mIsTLS; int mAlign; bool mUnnamedAddr; virtual BeType* GetType(); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mName); if (mInitializer != NULL) mInitializer->HashReference(hashCtx); hashCtx.Mixin(mLinkageType); hashCtx.Mixin(mStorageKind); hashCtx.Mixin(mIsConstant); hashCtx.Mixin(mIsTLS); hashCtx.Mixin(mAlign); hashCtx.Mixin(mUnnamedAddr); } virtual void GetData(BeConstData& data) override { data.mConsts.Add({ (int)data.mData.size(), this }); data.mData.Insert(data.mData.size(), (uint8)0, 8); } }; class BeFunctionParam { public: String mName; bool mStructRet; bool mNoAlias; bool mNoCapture; bool mZExt; int mDereferenceableSize; int mByValSize; BeFunctionParam() { mStructRet = false; mNoAlias = false; mNoCapture = false; mZExt = false; mDereferenceableSize = -1; mByValSize = -1; } }; class BeDbgFunction; class BeIntrinsic : public BeValue { public: BE_VALUE_TYPE(BeIntrinsic, BeValue); String mName; BfIRIntrinsic mKind; BeType* mReturnType; BeIntrinsic() { mReturnType = NULL; } virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mKind); } }; class BeFunction : public BeConstant { public: BE_VALUE_TYPE(BeFunction, BeConstant); BeModule* mModule; #ifdef _DEBUG StringT<256> mName; #else String mName; #endif BfIRLinkageType mLinkageType; bool mIsVarReturn; bool mAlwaysInline; bool mNoUnwind; bool mUWTable; bool mNoReturn; bool mDidInlinePass; bool mNoFramePointerElim; bool mIsDLLExport; bool mIsDLLImport; BfIRCallingConv mCallingConv; Array mBlocks; Array mParams; BeDbgFunction* mDbgFunction; BeGlobalVariable* mRemapBindVar; public: BeFunction() { mCallingConv = BfIRCallingConv_CDecl; mLinkageType = BfIRLinkageType_External; mModule = NULL; mDbgFunction = NULL; mIsVarReturn = false; mAlwaysInline = false; mDidInlinePass = false; mNoUnwind = false; mUWTable = false; mNoReturn = false; mNoFramePointerElim = false; mIsDLLExport = false; mIsDLLImport = false; mRemapBindVar = NULL; } BeFunctionType* GetFuncType() { BF_ASSERT(mType->IsPointer()); return (BeFunctionType*)(((BePointerType*)mType)->mElementType); } bool IsDecl() { return mBlocks.size() == 0; } bool HasStructRet() { return (!mParams.IsEmpty()) && (mParams[0].mStructRet); } virtual void HashContent(BeHashContext& hashCtx) override; }; class BeBlock : public BeValue { public: BE_VALUE_TYPE(BeBlock, BeValue); String mName; Array mInstructions; BeFunction* mFunction; public: bool IsEmpty(); virtual void HashContent(BeHashContext& hashCtx) override; }; ////////////////////////////////////////////////////////////////////////// class BeInst : public BeValue { public: BE_VALUE_TYPE(BeInst, BeValue); BeBlock* mParentBlock; const char* mName; BeDbgLoc* mDbgLoc; public: BeContext* GetContext(); BeModule* GetModule(); virtual bool CanBeReferenced() { return GetType() != NULL; } virtual void SetName(const StringImpl& name) override; BeInst() { mParentBlock = NULL; mName = NULL; mDbgLoc = NULL; } virtual void HashInst(BeHashContext& hashCtx) = 0; virtual void HashContent(BeHashContext& hashCtx) override; }; class BeNopInst : public BeInst { public: BE_VALUE_TYPE(BeNopInst, BeInst); virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeUnreachableInst : public BeInst { public: BE_VALUE_TYPE(BeUnreachableInst, BeInst); virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeEnsureInstructionAtInst : public BeInst { public: BE_VALUE_TYPE(BeEnsureInstructionAtInst, BeInst); virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeUndefValueInst : public BeInst { public: BE_VALUE_TYPE(BeUndefValueInst, BeInst); BeType* mType; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mType->HashReference(hashCtx); } }; class BeExtractValueInst : public BeInst { public: BE_VALUE_TYPE(BeExtractValueInst, BeInst); BeValue* mAggVal; int mIdx; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mAggVal->HashReference(hashCtx); hashCtx.Mixin(mIdx); } }; class BeInsertValueInst : public BeInst { public: BE_VALUE_TYPE(BeInsertValueInst, BeInst); BeValue* mAggVal; BeValue* mMemberVal; int mIdx; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mAggVal->HashReference(hashCtx); mMemberVal->HashReference(hashCtx); hashCtx.Mixin(mIdx); } }; class BeNumericCastInst : public BeInst { public: BE_VALUE_TYPE(BeNumericCastInst, BeInst); BeValue* mValue; BeType* mToType; bool mValSigned; bool mToSigned; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); mToType->HashReference(hashCtx); hashCtx.Mixin(mValSigned); hashCtx.Mixin(mToSigned); } }; class BeBitCastInst : public BeInst { public: BE_VALUE_TYPE(BeBitCastInst, BeInst); BeValue* mValue; BeType* mToType; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); mToType->HashReference(hashCtx); } }; class BeNegInst : public BeInst { public: BE_VALUE_TYPE(BeNegInst, BeInst); BeValue* mValue; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); } }; class BeNotInst : public BeInst { public: BE_VALUE_TYPE(BeNotInst, BeInst); BeValue* mValue; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); } }; enum BeBinaryOpKind { BeBinaryOpKind_None, BeBinaryOpKind_Add, BeBinaryOpKind_Subtract, BeBinaryOpKind_Multiply, BeBinaryOpKind_SDivide, BeBinaryOpKind_UDivide, BeBinaryOpKind_SModulus, BeBinaryOpKind_UModulus, BeBinaryOpKind_BitwiseAnd, BeBinaryOpKind_BitwiseOr, BeBinaryOpKind_ExclusiveOr, BeBinaryOpKind_LeftShift, BeBinaryOpKind_RightShift, BeBinaryOpKind_ARightShift, BeBinaryOpKind_Equality, BeBinaryOpKind_InEquality, BeBinaryOpKind_GreaterThan, BeBinaryOpKind_LessThan, BeBinaryOpKind_GreaterThanOrEqual, BeBinaryOpKind_LessThanOrEqual, }; class BeBinaryOpInst : public BeInst { public: BE_VALUE_TYPE(BeBinaryOpInst, BeInst); BeBinaryOpKind mOpKind; BfOverflowCheckKind mOverflowCheckKind; BeValue* mLHS; BeValue* mRHS; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mOpKind); hashCtx.Mixin(mOverflowCheckKind); mLHS->HashReference(hashCtx); mRHS->HashReference(hashCtx); } }; enum BeCmpKind { BeCmpKind_None, BeCmpKind_SLT, BeCmpKind_ULT, BeCmpKind_SLE, BeCmpKind_ULE, BeCmpKind_EQ, BeCmpKind_NE, BeCmpKind_SGT, BeCmpKind_UGT, BeCmpKind_SGE, BeCmpKind_UGE, BeCmpKind_NB, BeCmpKind_NO, }; class BeCmpInst : public BeInst { public: BE_VALUE_TYPE(BeCmpInst, BeInst); BeValue* mLHS; BeValue* mRHS; BeCmpKind mCmpKind; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mLHS->HashReference(hashCtx); mRHS->HashReference(hashCtx); hashCtx.Mixin(mCmpKind); } }; class BeObjectAccessCheckInst : public BeInst { public: BE_VALUE_TYPE(BeObjectAccessCheckInst, BeInst); BeValue* mValue; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); } }; class BeAllocaInst : public BeInst { public: BE_VALUE_TYPE(BeAllocaInst, BeInst); BeType* mType; BeValue* mArraySize; int mAlign; bool mNoChkStk; bool mForceMem; public: virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mType->HashReference(hashCtx); if (mArraySize != NULL) mArraySize->HashReference(hashCtx); hashCtx.Mixin(mAlign); hashCtx.Mixin(mNoChkStk); hashCtx.Mixin(mForceMem); } }; class BeAliasValueInst : public BeInst { public: BE_VALUE_TYPE(BeAliasValueInst, BeInst); BeValue* mPtr; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mPtr->HashReference(hashCtx); } virtual BeType* GetType() override { return mPtr->GetType(); } }; class BeLifetimeStartInst : public BeInst { public: BE_VALUE_TYPE(BeLifetimeStartInst, BeInst); BeValue* mPtr; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mPtr->HashReference(hashCtx); } }; class BeLifetimeEndInst : public BeInst { public: BE_VALUE_TYPE(BeLifetimeEndInst, BeInst); BeValue* mPtr; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mPtr->HashReference(hashCtx); } }; class BeLifetimeFenceInst : public BeInst { public: BE_VALUE_TYPE(BeLifetimeFenceInst, BeInst); BeBlock* mFenceBlock; // Lifetime is blocked from extending into the end of this block BeValue* mPtr; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mFenceBlock->HashReference(hashCtx); mPtr->HashReference(hashCtx); } }; class BeLifetimeExtendInst : public BeInst { public: BE_VALUE_TYPE(BeLifetimeExtendInst, BeInst); BeValue* mPtr; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mPtr->HashReference(hashCtx); } }; class BeValueScopeStartInst : public BeInst { public: BE_VALUE_TYPE(BeValueScopeStartInst, BeInst); virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeValueScopeRetainInst : public BeInst { public: BE_VALUE_TYPE(BeValueScopeRetainInst, BeInst); BeValue* mValue; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); } }; class BeValueScopeEndInst : public BeInst { public: BE_VALUE_TYPE(BeValueScopeEndInst, BeInst); BeValueScopeStartInst* mScopeStart; bool mIsSoft; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mScopeStart->HashReference(hashCtx); hashCtx.Mixin(mIsSoft); } }; class BeLoadInst : public BeInst { public: BE_VALUE_TYPE(BeLoadInst, BeInst); BeValue* mTarget; bool mIsVolatile; public: virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mTarget->HashReference(hashCtx); } }; class BeStoreInst : public BeInst { public: BE_VALUE_TYPE(BeStoreInst, BeInst); BeValue* mVal; BeValue* mPtr; bool mIsVolatile; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mVal->HashReference(hashCtx); mPtr->HashReference(hashCtx); } }; class BeSetCanMergeInst : public BeInst { public: BE_VALUE_TYPE(BeSetCanMergeInst, BeInst); BeValue* mVal; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mVal->HashReference(hashCtx); } }; class BeMemSetInst : public BeInst { public: BE_VALUE_TYPE(BeGEPInst, BeInst); BeValue* mAddr; BeValue* mVal; BeValue* mSize; int mAlignment; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mAddr->HashReference(hashCtx); mVal->HashReference(hashCtx); mSize->HashReference(hashCtx); hashCtx.Mixin(mAlignment); } }; class BeFenceInst : public BeInst { public: BE_VALUE_TYPE(BeFenceInst, BeInst); virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeStackSaveInst : public BeInst { public: BE_VALUE_TYPE(BeStackSaveInst, BeInst); virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } virtual BeType* GetType() override { return GetContext()->GetPrimitiveType(BeTypeCode_NullPtr); } }; class BeStackRestoreInst : public BeInst { public: BE_VALUE_TYPE(BeStackRestoreInst, BeInst); BeValue* mStackVal; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mStackVal->HashReference(hashCtx); } }; class BeGEPInst : public BeInst { public: BE_VALUE_TYPE(BeGEPInst, BeInst); BeValue* mPtr; BeValue* mIdx0; BeValue* mIdx1; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mPtr->HashReference(hashCtx); mIdx0->HashReference(hashCtx); if (mIdx1 != NULL) mIdx1->HashReference(hashCtx); } }; class BeBrInst : public BeInst { public: BE_VALUE_TYPE(BeBrInst, BeInst); BeBlock* mTargetBlock; bool mNoCollapse; bool mIsFake; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mTargetBlock->HashReference(hashCtx); hashCtx.Mixin(mNoCollapse); hashCtx.Mixin(mIsFake); } }; class BeCondBrInst : public BeInst { public: BE_VALUE_TYPE(BeCondBrInst, BeInst); BeValue* mCond; BeBlock* mTrueBlock; BeBlock* mFalseBlock; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mCond->HashReference(hashCtx); mTrueBlock->HashReference(hashCtx); mFalseBlock->HashReference(hashCtx); } }; class BePhiIncoming : public BeValue { public: BE_VALUE_TYPE(BePhiIncoming, BeValue); BeBlock* mBlock; BeValue* mValue; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mBlock->HashReference(hashCtx); mValue->HashReference(hashCtx); } }; class BePhiInst : public BeInst { public: BE_VALUE_TYPE(BePhiInst, BeInst); BeType* mType; SizedArray mIncoming; virtual BeType* GetType() override; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mType->HashReference(hashCtx); hashCtx.Mixin(mIncoming.size()); for (auto incoming : mIncoming) { incoming->mBlock->HashReference(hashCtx); incoming->mValue->HashReference(hashCtx); } } }; class BeSwitchCase { public: BeConstant* mValue; BeBlock* mBlock; }; class BeSwitchInst : public BeInst { public: BE_VALUE_TYPE(BeSwitchInst, BeInst); BeValue* mValue; BeBlock* mDefaultBlock; Array mCases; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); mDefaultBlock->HashReference(hashCtx); for (auto& caseVal : mCases) { caseVal.mValue->HashReference(hashCtx); caseVal.mBlock->HashReference(hashCtx); } } }; class BeRetInst : public BeInst { public: BE_VALUE_TYPE(BeRetInst, BeInst); BeValue* mRetValue; virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); if (mRetValue != NULL) mRetValue->HashReference(hashCtx); } }; class BeSetRetInst : public BeRetInst { public: BE_VALUE_TYPE(BeSetRetInst, BeRetInst); public: int32 mReturnTypeId; }; class BeCallInst : public BeInst { public: struct Arg { BeValue* mValue; int mDereferenceableSize; int mByRefSize; bool mStructRet; bool mZExt; bool mNoAlias; bool mNoCapture; Arg() { mValue = NULL; mStructRet = false; mZExt = false; mNoAlias = false; mNoCapture = false; mDereferenceableSize = -1; mByRefSize = -1; } }; public: BE_VALUE_TYPE(BeCallInst, BeInst); BeValue* mInlineResult; BeValue* mFunc; SizedArray mArgs; BfIRCallingConv mCallingConv; bool mNoReturn; bool mTailCall; virtual BeType* GetType() override; BeCallInst() { mInlineResult = NULL; mFunc = NULL; mCallingConv = BfIRCallingConv_CDecl; mNoReturn = false; mTailCall = false; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); if (mInlineResult != NULL) mInlineResult->HashReference(hashCtx); mFunc->HashReference(hashCtx); for (auto& arg : mArgs) { arg.mValue->HashReference(hashCtx); hashCtx.Mixin(arg.mStructRet); hashCtx.Mixin(arg.mZExt); hashCtx.Mixin(arg.mDereferenceableSize); hashCtx.Mixin(arg.mByRefSize); } hashCtx.Mixin(mCallingConv); hashCtx.Mixin(mNoReturn); hashCtx.Mixin(mTailCall); } bool HasStructRet() { return (!mArgs.IsEmpty()) && (mArgs[0].mStructRet); } }; ////////////////////////////////////////////////////////////////////////// class BeComptimeError : public BeInst { public: BE_VALUE_TYPE(BeComptimeError, BeInst); public: int mError; public: virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mError); } }; class BeComptimeGetType : public BeInst { public: BE_VALUE_TYPE(BeComptimeGetType, BeInst); public: int mTypeId; BeType* mResultType; public: virtual BeType* GetType() override { return mResultType; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mTypeId); } }; class BeComptimeGetReflectType : public BeInst { public: BE_VALUE_TYPE(BeComptimeGetReflectType, BeInst); public: int mTypeId; BeType* mResultType; public: virtual BeType* GetType() override { return mResultType; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mTypeId); } }; class BeComptimeDynamicCastCheck : public BeInst { public: BE_VALUE_TYPE(BeComptimeDynamicCastCheck, BeInst); public: BeValue* mValue; int mTypeId; BeType* mResultType; public: virtual BeType* GetType() override { return mResultType; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); hashCtx.Mixin(mTypeId); } }; class BeComptimeGetVirtualFunc : public BeInst { public: BE_VALUE_TYPE(BeComptimeGetVirtualFunc, BeInst); public: BeValue* mValue; int mVirtualTableIdx; BeType* mResultType; public: virtual BeType* GetType() override { return mResultType; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); hashCtx.Mixin(mVirtualTableIdx); } }; class BeComptimeGetInterfaceFunc : public BeInst { public: BE_VALUE_TYPE(BeComptimeGetInterfaceFunc, BeInst); public: BeValue* mValue; int mIFaceTypeId; int mMethodIdx; BeType* mResultType; public: virtual BeType* GetType() override { return mResultType; } virtual void HashInst(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); hashCtx.Mixin(mIFaceTypeId); hashCtx.Mixin(mMethodIdx); } }; ////////////////////////////////////////////////////////////////////////// class BeArgument : public BeValue { public: BE_VALUE_TYPE(BeArgument, BeValue); BeModule* mModule; int mArgIdx; virtual BeType* GetType() override; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mArgIdx); } }; struct BeDumpContext { public: Dictionary mValueNameMap; Dictionary mSeenNames; void ToString(StringImpl& str, BeValue* value, bool showType = true, bool mdDrillDown = false); void ToString(StringImpl& str, BeType* type); void ToString(StringImpl& str, BeDbgFunction* dbgFunction, bool showScope); static void ToString(StringImpl& str, int val); static void ToString(StringImpl& str, BeCmpKind cmpKind); static void ToString(StringImpl& str, BeBinaryOpKind opKind); String ToString(BeValue* value, bool showType = true, bool mdDrillDown = false); String ToString(BeType* type); String ToString(BeDbgFunction* dbgFunction); static String ToString(int val); static String ToString(BeCmpKind cmpKind); static String ToString(BeBinaryOpKind opKind); }; ////////////////////////////////////////////////////////////////////////// class BeDbgVariable; class BeDbgDeclareInst : public BeInst { public: BE_VALUE_TYPE(BeDbgDeclareInst, BeInst); public: BeDbgVariable* mDbgVar; BeValue* mValue; bool mIsValue; virtual void HashInst(BeHashContext& hashCtx) override; }; class BeMDNode : public BeValue { public: BE_VALUE_TYPE(BeMDNode, BeValue); public: virtual ~BeMDNode() { } virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); } }; class BeDbgFile; class BeDbgLoc : public BeMDNode { public: BE_VALUE_TYPE(BeDbgLoc, BeMDNode); public: int mLine; int mColumn; BeMDNode* mDbgScope; BeDbgLoc* mDbgInlinedAt; int mIdx; bool mHadInline; public: BeDbgLoc() { } int GetInlineDepth(); int GetInlineMatchDepth(BeDbgLoc* other); BeDbgLoc* GetInlinedAt(int idx = 0); BeDbgLoc* GetRoot(); BeDbgFunction* GetDbgFunc(); BeDbgFile* GetDbgFile(); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mLine); hashCtx.Mixin(mColumn); if (mDbgScope != NULL) mDbgScope->HashReference(hashCtx); else hashCtx.Mixin(-1); if (mDbgInlinedAt != NULL) mDbgInlinedAt->HashReference(hashCtx); } }; class BeDbgLexicalBlock : public BeMDNode { public: BE_VALUE_TYPE(BeDbgLexicalBlock, BeMDNode); public: BeDbgFile* mFile; BeMDNode* mScope; BeBlock* mLastBeBlock; int mId; virtual void HashContent(BeHashContext& hashCtx) override; }; class BeDbgNamespace : public BeMDNode { public: BE_VALUE_TYPE(BeDbgNamespace, BeMDNode); public: BeMDNode* mScope; String mName; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mScope->HashReference(hashCtx); hashCtx.MixinStr(mName); } }; class BeDbgType : public BeMDNode { public: BE_VALUE_TYPE(BeDbgType, BeMDNode); public: int mSize; int mAlign; int mCvDeclTypeId; int mCvDefTypeId; BumpList mDerivedTypes; BeDbgType() { mSize = -1; mAlign = -1; mCvDeclTypeId = -1; mCvDefTypeId = -1; } BeDbgType* FindDerivedType(int typeId) { for (auto derivedType : mDerivedTypes) { if (derivedType->GetTypeId() == typeId) return derivedType; } return NULL; } virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mSize); hashCtx.Mixin(mAlign); } }; class BeDbgBasicType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgBasicType, BeDbgType); public: String mName; int mEncoding; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mSize); hashCtx.Mixin(mAlign); hashCtx.MixinStr(mName); hashCtx.Mixin(mEncoding); } }; class BeDbgArrayType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgArrayType, BeDbgType); public: BeDbgType* mElement; int mNumElements; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.Mixin(mSize); hashCtx.Mixin(mAlign); hashCtx.Mixin(mNumElements); mElement->HashReference(hashCtx); } }; class BeDbgArtificialType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgArtificialType, BeDbgType); public: BeDbgType* mElement; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mElement->HashReference(hashCtx); } }; class BeDbgConstType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgConstType, BeDbgType); public: BeDbgType* mElement; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mElement->HashReference(hashCtx); } }; class BeDbgReferenceType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgReferenceType, BeDbgType); public: BeDbgType* mElement; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mElement->HashReference(hashCtx); } }; class BeDbgPointerType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgPointerType, BeDbgType); public: BeDbgType* mElement; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mElement->HashReference(hashCtx); } }; class BeDbgInheritance : public BeMDNode { public: BE_VALUE_TYPE(BeDbgInheritance, BeMDNode); public: BeDbgType* mBaseType; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mBaseType->HashReference(hashCtx); } }; class BeDbgStructMember : public BeMDNode { public: BE_VALUE_TYPE(BeDbgStructMember, BeMDNode); public: String mName; BeDbgType* mType; int mFlags; int mOffset; bool mIsStatic; BeValue* mStaticValue; public: BeDbgStructMember() { mType = NULL; mFlags = 0; mOffset = -1; mIsStatic = false; mStaticValue = NULL; } virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mName); mType->HashReference(hashCtx); hashCtx.Mixin(mFlags); hashCtx.Mixin(mOffset); hashCtx.Mixin(mIsStatic); if (mStaticValue != NULL) mStaticValue->HashReference(hashCtx); } }; class BeDbgFunctionType : public BeMDNode { public: BE_VALUE_TYPE(BeDbgFunctionType, BeMDNode); public: BeDbgType* mReturnType; Array mParams; public: virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); if (mReturnType != NULL) mReturnType->HashReference(hashCtx); hashCtx.Mixin(mParams.size()); for (auto param : mParams) param->HashReference(hashCtx); } }; /*class BeDbgVariableRange { public: enum Kind { Kind_None, Kind_Reg, // Direct reg usage Kind_Indexed // [RBP+8] type usage (spilled) }; public: int mCodeStartOfs; int mCodeRange; Kind mKind; X64CPURegister mReg; int mOfs; public: BeDbgVariableRange() { mCodeStartOfs = -1; mCodeRange = -1; mKind = Kind_None; mReg = X64Reg_None; mOfs = 0; } };*/ class BeDbgVariableRange { public: int mOffset; int mLength; }; class BeDbgVariableLoc { public: enum Kind { Kind_None, Kind_Reg, // Direct reg usage Kind_Indexed, // [RBP+8] type usage (spilled) Kind_SymbolAddr }; Kind mKind; X64CPURegister mReg; int mOfs; public: BeDbgVariableLoc() { mKind = Kind_None; mReg = X64Reg_None; mOfs = 0; } }; class BeDbgVariable : public BeMDNode { public: BE_VALUE_TYPE(BeDbgVariable, BeMDNode); public: String mName; BeDbgType* mType; BeValue* mValue; int mParamNum; BfIRInitType mInitType; BfIRInitType mPendingInitType; bool mPendingInitDef; BeMDNode* mScope; BeDbgLoc* mDeclDbgLoc; BeDbgVariableLoc mPrimaryLoc; BeDbgVariableLoc mSavedLoc; int mDeclStart; int mDeclEnd; int mDeclMCBlockId; bool mDeclLifetimeExtend; bool mDbgLifeEnded; bool mIsValue; // Value vs Addr Array mSavedRanges; Array mGaps; public: BeDbgVariable() { mType = NULL; mValue = NULL; mParamNum = -1; mInitType = BfIRInitType_NotSet; mPendingInitType = BfIRInitType_NotNeeded; mPendingInitDef = false; mScope = NULL; mDeclDbgLoc = NULL; mDeclStart = -1; mDeclEnd = -1; mDeclMCBlockId = -1; mIsValue = false; mDbgLifeEnded = false; mDeclLifetimeExtend = false; } virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mName); mType->HashReference(hashCtx); if (mValue != NULL) mValue->HashReference(hashCtx); hashCtx.Mixin(mParamNum); hashCtx.Mixin(mInitType); hashCtx.Mixin(mPendingInitType); if (mScope != NULL) mScope->HashReference(hashCtx); if (mDeclDbgLoc != NULL) mDeclDbgLoc->HashReference(hashCtx); // The others only get filled in after generation -- not part of hash } }; class BeDbgFile; class BeDbgCodeEmission { public: BeDbgLoc* mDbgLoc; int mPos; }; class BeDbgFunction : public BeMDNode { public: BE_VALUE_TYPE(BeDbgFunction, BeMDNode); public: int mIdx; BeMDNode* mScope; BeDbgFile* mFile; int mLine; String mName; String mLinkageName; BeDbgFunctionType* mType; //Array mParams; Array mGenericArgs; Array mGenericConstValueArgs; BeFunction* mValue; bool mIsLocalToUnit; bool mIsStaticMethod; bool mIncludedAsMember; int mFlags; int mVK; int mVIndex; Array mVariables; int mPrologSize; int mCodeLen; Array mEmissions; int mCvTypeId; int mCvFuncId; int mCvArgListId; public: BeDbgFunction() { mIdx = -1; mScope = NULL; mFile = NULL; mLine = -1; mType = NULL; mValue = NULL; mFlags = 0; mIsLocalToUnit = false; mVK = -1; mVIndex = -1; mIsStaticMethod = true; mIncludedAsMember = false; mPrologSize = 0; mCodeLen = -1; mCvTypeId = -1; mCvFuncId = -1; mCvArgListId = -1; } BeDbgType* GetParamType(int paramIdx) { /*if (!mParams.empty()) return mParams[paramIdx]->mType;*/ if (paramIdx < (int)mVariables.size()) { auto param = mVariables[paramIdx]; if (param->mParamNum == paramIdx) return param->mType; } return mType->mParams[paramIdx]; } bool HasThis() { return !mIsStaticMethod; /*bool matchLLVM = false; // This matches the LLVM CV emitter if (matchLLVM) { return (BeValueDynCast(mScope) != NULL) && (mType->mParams.size() > 0); } else { return ((mVariables.size() > 0) && (mVariables[0]->mName == "this")); }*/ } virtual void HashContent(BeHashContext& hashCtx) override; }; class BeDbgInlinedScope : public BeMDNode { public: BE_VALUE_TYPE(BeDbgInlinedScope, BeMDNode); BeMDNode* mScope; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); mScope->HashReference(hashCtx); } }; class BeDbgFile; class BeDbgStructType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgStructType, BeDbgType); public: BeMDNode* mScope; String mName; BeDbgType* mDerivedFrom; Array mMembers; Array mMethods; bool mIsFullyDefined; bool mIsStatic; BeDbgFile* mDefFile; int mDefLine; public: BeDbgStructType() { mScope = NULL; mDerivedFrom = NULL; mIsStatic = false; mIsFullyDefined = false; mDefFile = NULL; mDefLine = 0; } void SetMembers(SizedArrayImpl& members); virtual void HashContent(BeHashContext& hashCtx) override; }; class BeDbgEnumMember : public BeMDNode { public: BE_VALUE_TYPE(BeDbgEnumMember, BeMDNode); public: String mName; int64 mValue; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mName); hashCtx.Mixin(mValue); } }; class BeDbgEnumType : public BeDbgType { public: BE_VALUE_TYPE(BeDbgEnumType, BeDbgType); public: BeMDNode* mScope; String mName; BeDbgType* mElementType; bool mIsFullyDefined; Array mMembers; public: BeDbgEnumType() { mScope = NULL; mElementType = NULL; mIsFullyDefined = false; } void SetMembers(SizedArrayImpl& members); virtual void HashContent(BeHashContext& hashCtx) override { mScope->HashReference(hashCtx); hashCtx.MixinStr(mName); if (mElementType != NULL) mElementType->HashReference(hashCtx); hashCtx.Mixin(mIsFullyDefined); for (auto member : mMembers) member->HashReference(hashCtx); } }; class BeDbgFile : public BeMDNode { public: BE_VALUE_TYPE(BeDbgFile, BeMDNode); public: String mFileName; String mDirectory; Val128 mMD5Hash; int mIdx; void ToString(String& str); void GetFilePath(String& outStr); virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mFileName); hashCtx.Mixin(mMD5Hash); hashCtx.MixinStr(mDirectory); } }; class BeDbgGlobalVariable : public BeMDNode { public: BE_VALUE_TYPE(BeDbgGlobalVariable, BeMDNode); BeMDNode* mContext; String mName; String mLinkageName; BeDbgFile* mFile; int mLineNum; BeDbgType* mType; bool mIsLocalToUnit; BeConstant* mValue; BeMDNode* mDecl; virtual void HashContent(BeHashContext& hashCtx) override { hashCtx.Mixin(TypeId); hashCtx.MixinStr(mName); hashCtx.MixinStr(mLinkageName); if (mFile != NULL) mFile->HashReference(hashCtx); hashCtx.Mixin(mLineNum); mType->HashReference(hashCtx); hashCtx.Mixin(mIsLocalToUnit); if (mValue != NULL) mValue->HashReference(hashCtx); if (mDecl != NULL) mDecl->HashReference(hashCtx); } }; class BeDbgModule : public BeMDNode { public: BE_VALUE_TYPE(BeDbgModule, BeMDNode); public: BeModule* mBeModule; String mFileName; String mDirectory; String mProducer; OwnedVector mFiles; OwnedVector mNamespaces; OwnedVector mGlobalVariables; OwnedVector mTypes; Array mFuncs; // Does not include methods in structs virtual void HashContent(BeHashContext& hashCtx) override; BeDbgReferenceType* CreateReferenceType(BeDbgType* dbgType); }; ////////////////////////////////////////////////////////////////////////// class BeDbgModule; class BeModule { public: BeIRCodeGen* mBeIRCodeGen; Array mConfigConsts32; Array mConfigConsts64; BeFunction* mActiveFunction; BumpAllocator mAlloc; OwnedVector mOwnedValues; // Those that need dtors OwnedVector mGlobalVariables; BeContext* mContext; String mModuleName; String mTargetTriple; String mTargetCPU; BeBlock* mActiveBlock; int mInsertPos; BeDbgLoc* mCurDbgLoc; BeDbgLoc* mPrevDbgLocInline; BeDbgLoc* mLastDbgLoc; Array mArgs; Array mFunctions; Dictionary mFunctionMap; int mCurDbgLocIdx; int mCurLexBlockId; BeDbgModule* mDbgModule; public: void AddInst(BeInst* inst); static void ToString(StringImpl& str, BeType* type); static void StructToString(StringImpl& str, BeStructType* type); template T* AllocInst() { T* newInst = mAlloc.Alloc(); AddInst(newInst); return newInst; } template T* AllocInstOwned() { T* newInst = mOwnedValues.Alloc(); AddInst(newInst); return newInst; } public: BeModule(const StringImpl& moduleName, BeContext* context); ~BeModule(); void Hash(BeHashContext& hashCtx); String ToString(BeFunction* func = NULL); void Print(); void Print(BeFunction* func); void PrintValue(BeValue* val); void DoInlining(BeFunction* func); void DoInlining(); static BeCmpKind InvertCmp(BeCmpKind cmpKind); static BeCmpKind SwapCmpSides(BeCmpKind cmpKind); void SetActiveFunction(BeFunction* function); BeArgument* GetArgument(int arg); BeBlock* CreateBlock(const StringImpl& name); void AddBlock(BeFunction* function, BeBlock* block); void RemoveBlock(BeFunction* function, BeBlock* block); BeBlock* GetInsertBlock(); void SetInsertPoint(BeBlock* block); void SetInsertPointAtStart(BeBlock* block); BeFunction* CreateFunction(BeFunctionType* funcType, BfIRLinkageType linkageType, const StringImpl& name); BeDbgLoc* GetCurrentDebugLocation(); void SetCurrentDebugLocation(BeDbgLoc* dbgLoc); void SetCurrentDebugLocation(int line, int column, BeMDNode* diScope, BeDbgLoc* diInlinedAt); BeDbgLoc* DupDebugLocation(BeDbgLoc* dbgLoc); void DupCurrentDebugLocation(); /// BeNopInst* CreateNop(); BeUndefValueInst* CreateUndefValue(BeType* type); BeNumericCastInst* CreateNumericCast(BeValue* value, BeType* toType, bool valSigned, bool toSigned); BeBitCastInst* CreateBitCast(BeValue* value, BeType* toType);; BeCmpInst* CreateCmp(BeCmpKind cmpKind, BeValue* lhs, BeValue* rhs); BeBinaryOpInst* CreateBinaryOp(BeBinaryOpKind opKind, BeValue* lhs, BeValue* rhs, BfOverflowCheckKind overflowCheckKind = BfOverflowCheckKind_None); BeAllocaInst* CreateAlloca(BeType* type); BeLoadInst* CreateLoad(BeValue* value, bool isVolatile); BeLoadInst* CreateAlignedLoad(BeValue* value, int alignment, bool isVolatile); BeStoreInst* CreateStore(BeValue* val, BeValue* ptr, bool isVolatile); BeStoreInst* CreateAlignedStore(BeValue* val, BeValue* ptr, int alignment, bool isVolatile); BeGEPInst* CreateGEP(BeValue* ptr, BeValue* idx0, BeValue* idx1); BeBrInst* CreateBr(BeBlock* block); BeCondBrInst* CreateCondBr(BeValue* cond, BeBlock* trueBlock, BeBlock* falseBlock); BeRetInst* CreateRetVoid(); BeRetInst* CreateRet(BeValue* value); BeSetRetInst* CreateSetRet(BeValue* value, int returnTypeId); BeCallInst* CreateCall(BeValue* func, const SizedArrayImpl& args); BeConstant* GetConstant(BeType* type, double floatVal); BeConstant* GetConstant(BeType* type, int64 intVal); BeConstant* GetConstant(BeType* type, bool boolVal); BeConstant* GetConstantNull(BePointerType* type); }; NS_BF_END