1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-07 19:18:19 +02:00
Beef/IDEHelper/DbgExprEvaluator.h

487 lines
No EOL
15 KiB
C++

#pragma once
#include "X86Target.h"
#include "Compiler/BfAst.h"
#include "DwAutoComplete.h"
#include "DbgModule.h"
namespace Beefy
{
class BfPassInstance;
class BfExpression;
}
NS_BF_DBG_BEGIN
class WinDebugger;
class WdStackFrame;
typedef WdStackFrame CPUStackFrame;
enum DbgEvalExprFlags
{
DbgEvalExprFlags_None = 0,
DbgEvalExprFlags_AllowTypeResult = 1,
DbgEvalExprFlags_NoCast = 2
};
class DbgTypedValue
{
public:
DbgType* mType;
union
{
bool mBool;
int8 mInt8;
uint8 mUInt8;
int16 mInt16;
uint16 mUInt16;
int32 mInt32;
uint32 mUInt32;
int64 mInt64;
uint64 mUInt64;
float mSingle;
double mDouble;
const char* mCharPtr;
addr_target mPtr;
const void* mLocalPtr;
intptr mLocalIntPtr;
DbgVariable* mVariable;
};
bool mIsLiteral;
bool mHasNoValue;
bool mIsReadOnly;
union
{
int mRegNum;
int mDataLen;
};
addr_target mSrcAddress;
public:
DbgTypedValue()
{
mType = NULL;
mUInt64 = 0;
mIsLiteral = false;
mSrcAddress = 0;
mHasNoValue = false;
mIsReadOnly = false;
mRegNum = -1;
}
DbgType* ResolveTypeDef() const
{
auto typeDef = mType;
while ((typeDef != NULL) && (typeDef->mTypeCode == DbgType_TypeDef))
typeDef = typeDef->mTypeParam;
return typeDef;
}
int64 GetSExtInt() const
{
auto resolvedType = mType->RemoveModifiers();
switch (resolvedType->mTypeCode)
{
case DbgType_Bool:
case DbgType_i8:
return (int64) mInt8;
case DbgType_i16:
return (int64) mInt16;
case DbgType_i32:
return (int64) mInt32;
case DbgType_i64:
return (int64) mInt64;
default:
BF_FATAL("Invalid type");
}
return 0;
}
int64 GetInt64() const
{
auto resolvedType = mType->RemoveModifiers();
if (resolvedType->mTypeCode == DbgType_Enum)
{
if (resolvedType->mTypeParam->GetByteCount() == 0)
resolvedType = resolvedType->GetPrimaryType();
resolvedType = resolvedType->mTypeParam;
}
else if (resolvedType->mTypeCode == DbgType_Struct)
{
resolvedType = resolvedType->GetPrimaryType();
if (resolvedType->IsTypedPrimitive())
resolvedType = resolvedType->GetUnderlyingType();
}
switch (resolvedType->mTypeCode)
{
case DbgType_Bool:
case DbgType_i8:
case DbgType_SChar:
return (int64) mInt8;
case DbgType_i16:
case DbgType_SChar16:
return (int64) mInt16;
case DbgType_i32:
case DbgType_SChar32:
return (int64) mInt32;
case DbgType_i64:
return (int64) mInt64;
case DbgType_UChar:
case DbgType_u8:
return (int64) mUInt8;
case DbgType_UChar16:
case DbgType_u16:
return (int64) mUInt16;
case DbgType_UChar32:
case DbgType_u32:
return (int64) mUInt32;
case DbgType_u64:
return (int64) mUInt64;
case DbgType_Ptr:
return (int64) mUInt64;
default:
return 0;
//BF_FATAL("Invalid type");
}
return 0;
}
addr_target GetPointer() const
{
if (mType->IsSizedArray())
return mSrcAddress;
if (mType->IsInteger())
return GetInt64();
return mPtr;
}
String GetString() const
{
if (!mType->IsPointer())
return "";
if ((mType->mTypeParam->mTypeCode != DbgType_SChar) && (mType->mTypeParam->mTypeCode != DbgType_UChar))
return "";
if (mIsLiteral)
return mCharPtr;
//return (const char*)mPtr;
return "";
}
operator bool() const
{
return (mType != NULL) && (!mHasNoValue);
}
static DbgTypedValue GetValueless(DbgType* dbgType)
{
DbgTypedValue dbgTypedValue;
dbgTypedValue.mType = dbgType;
dbgTypedValue.mHasNoValue = true;
return dbgTypedValue;
}
};
struct DwFormatInfo
{
int mCallStackIdx;
bool mHidePointers;
bool mIgnoreDerivedClassInfo;
bool mNoVisualizers;
bool mNoMembers;
bool mRawString;
bool mAllowStringView;
bool mNoEdit;
String mStackSearchStr;
DbgTypeKindFlags mTypeKindFlags;
intptr mArrayLength;
intptr mOverrideCount;
intptr mMaxCount;
DwDisplayType mDisplayType;
DbgTypedValue mExplicitThis;
int mTotalSummaryLength;
String mReferenceId;
String mAction;
String mSubjectExpr;
String mExpectedType;
String mNamespaceSearch;
int mExpandItemDepth;
DbgLanguage mLanguage;
DwFormatInfo()
{
mCallStackIdx = -1;
mHidePointers = false;
mIgnoreDerivedClassInfo = false;
mRawString = false;
mAllowStringView = false;
mNoVisualizers = false;
mNoMembers = false;
mNoEdit = false;
mTypeKindFlags = DbgTypeKindFlag_None;
mArrayLength = -1;
mOverrideCount = -1;
mMaxCount = -1;
mTotalSummaryLength = 0;
mDisplayType = DwDisplayType_NotSpecified;
mExpandItemDepth = 0;
mLanguage = DbgLanguage_Unknown;
}
};
struct DbgMethodArgument
{
DbgTypedValue mTypedValue;
bool mWantsRef;
DbgMethodArgument()
{
mWantsRef = false;
}
};
typedef Array<DbgType*> DwTypeVector;
class DbgExprEvaluator;
class DwMethodMatcher
{
public:
BfAstNode* mTargetSrc;
DbgExprEvaluator* mExprEvaluator;
String mMethodName;
SizedArrayImpl<DbgTypedValue>& mArguments;
bool mHadExplicitGenericArguments;
BfType* mExplicitInterfaceCheck;
bool mTargetIsConst;
DwTypeVector mCheckMethodGenericArguments;
DbgSubprogram* mBackupMethodDef;
DbgSubprogram* mBestMethodDef;
DbgType* mBestMethodTypeInstance;
SizedArray<int, 4> mBestMethodGenericArgumentSrcs;
DwTypeVector mBestMethodGenericArguments;
public:
void CompareMethods(DbgSubprogram* prevMethodInstance, DwTypeVector* prevGenericArgumentsSubstitute,
DbgSubprogram* newMethodInstance, DwTypeVector* genericArgumentsSubstitute,
bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail);
public:
DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl<DbgTypedValue>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
bool CheckType(DbgType* typeInstance, bool isFailurePass);
bool CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMethod);
};
class DbgCallResult
{
public:
DbgSubprogram* mSubProgram;
DbgTypedValue mResult;
DbgTypedValue mStructRetVal;
Array<uint8> mSRetData;
};
class DbgStackSearch
{
public:
String mSearchStr;
BfAstNode* mIdentifier;
HashSet<DbgType*> mSearchedTypes;
HashSet<DbgType*> mAutocompleteSearchedTypes;
int mStartingStackIdx;
public:
DbgStackSearch()
{
mIdentifier = NULL;
mStartingStackIdx = -1;
}
};
class DbgExprEvaluator : public BfStructuralVisitor
{
public:
struct NodeReplaceRecord
{
BfAstNode** mNodeRef;
BfAstNode* mNode;
bool mForceTypeRef;
NodeReplaceRecord(BfAstNode* node, BfAstNode** nodeRef, bool forceTypeRef = false)
{
mNode = node;
mNodeRef = nodeRef;
mForceTypeRef = forceTypeRef;
}
};
struct SplatLookupEntry
{
String mFindName;
bool mIsConst;
DbgTypedValue mResult;
SplatLookupEntry()
{
mIsConst = false;
}
};
public:
DebugTarget* mDebugTarget;
DbgModule* mOrigDbgModule;
DbgModule* mDbgModule;
DbgCompileUnit* mDbgCompileUnit;
DbgLanguage mLanguage;
BfPassInstance* mPassInstance;
WinDebugger* mDebugger;
String mExpectingTypeName;
String mSubjectExpr;
DbgTypedValue mSubjectValue;
DbgType* mExpectingType;
DbgSubprogram* mCurMethod;
DbgTypedValue mResult;
DbgTypedValue* mReceivingValue;
intptr mCountResultOverride;
DbgTypedValue mExplicitThis;
BfExpression* mExplicitThisExpr;
Array<DbgCallResult>* mCallResults;
addr_target mCallStackPreservePos;
int mCallResultIdx;
String mNamespaceSearchStr;
Array<DbgType*> mNamespaceSearch;
Dictionary<BfAstNode*, SplatLookupEntry> mSplatLookupMap;
DbgTypedValue mPropTarget;
DbgSubprogram* mPropSet;
DbgSubprogram* mPropGet;
BfAstNode* mPropSrc;
SizedArray<BfExpression*, 2> mIndexerExprValues;
SizedArray<DbgTypedValue, 2> mIndexerValues;
bool mIsEmptyTarget;
DwEvalExpressionFlags mExpressionFlags;
bool mHadSideEffects;
bool mBlockedSideEffects;
bool mIgnoreErrors;
bool mCreatedPendingCall;
bool mValidateOnly;
int mCallStackIdx;
int mCursorPos;
DwAutoComplete* mAutoComplete;
DbgStackSearch* mStackSearch;
Array<Array<uint8>> mTempStorage;
Array<NodeReplaceRecord> mDeferredInsertExplicitThisVector;
String* mReferenceId;
bool mHadMemberReference;
bool mIsComplexExpression;
public:
DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType);
bool CheckTupleCreation(addr_target receiveAddr, BfAstNode* targetSrc, DbgType* tupleType, const BfSizedArray<BfExpression*>& argValues, BfSizedArray<BfTupleNameNode*>* names);
DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues);
void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, bool& failed);
bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues);
DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues);
DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, bool& failed);
DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name);
void PerformBinaryOperation(ASTREF(BfExpression*)& leftExpression, ASTREF(BfExpression*)& rightExpression, BfBinaryOp binaryOp, BfTokenNode* opToken, bool forceLeftType);
void PerformBinaryOperation(DbgType* resultType, DbgTypedValue convLeftValue, DbgTypedValue convRightValue, BfBinaryOp binaryOp, BfTokenNode* opToken);
void PerformUnaryExpression(BfAstNode* opToken, BfUnaryOp unaryOp, ASTREF(BfExpression*)& expr);
DbgTypedValue CreateValueFromExpression(ASTREF(BfExpression*)& expr, DbgType* castToType = NULL, DbgEvalExprFlags flags = DbgEvalExprFlags_None);
const char* GetTypeName(DbgType* type);
DbgTypedValue GetResult();
bool HasPropResult();
DbgLanguage GetLanguage();
DbgFlavor GetFlavor();
public:
DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModule, BfPassInstance* passInstance, int callStackIdx, int cursorPos);
~DbgExprEvaluator();
DbgTypedValue GetInt(int value);
DbgTypedValue GetString(const StringImpl& str);
void Fail(const StringImpl& error, BfAstNode* node);
void Warn(const StringImpl& error, BfAstNode* node);
DbgType* GetExpectingType();
void GetNamespaceSearch();
DbgType* FixType(DbgType* dbgType);
DbgTypedValue FixThis(const DbgTypedValue& thisVal);
DbgType* ResolveTypeRef(BfTypeReference* typeRef);
DbgType* ResolveTypeRef(BfAstNode* typeRef, BfAstNode** parentChildRef = NULL);
DbgType* ResolveTypeRef(const StringImpl& typeRef);
static bool TypeIsSubTypeOf(DbgType* srcType, DbgType* wantType, int* thisOffset = NULL, addr_target* thisAddr = NULL);
DbgTypedValue GetBeefTypeById(int typeId);
void BeefStringToString(addr_target addr, String& outStr);
void BeefStringToString(const DbgTypedValue& val, String& outStr);
void BeefTypeToString(const DbgTypedValue& val, String& outStr);
CPUStackFrame* GetStackFrame();
CPURegisters* GetRegisters();
DbgTypedValue GetRegister(const StringImpl& regName);
DbgSubprogram* GetCurrentMethod();
DbgType* GetCurrentType();
DbgTypedValue GetThis();
DbgTypedValue GetDefaultTypedValue(DbgType* srcType);
bool IsAutoCompleteNode(BfAstNode* node, int lengthAdd = 0);
void AutocompleteCheckType(BfTypeReference* typeReference);
void AutocompleteAddTopLevelTypes(const StringImpl& filter);
void AutocompleteAddMethod(const char* methodName, const StringImpl& filter);
void AutocompleteAddMembers(DbgType* dbgType, bool wantsStatic, bool wantsNonStatic, const StringImpl& filter, bool isCapture = false);
void AutocompleteCheckMemberReference(BfAstNode* target, BfAstNode* dotToken, BfAstNode* memberName);
DbgTypedValue RemoveRef(DbgTypedValue typedValue);
bool StoreValue(DbgTypedValue& ptr, DbgTypedValue& value, BfAstNode* refNode);
bool StoreValue(DbgTypedValue& ptr, BfExpression* expr);
String TypeToString(DbgType* type);
bool CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNode);
bool CanCast(DbgTypedValue typedVal, DbgType* toType, BfCastFlags castFlags = BfCastFlags_None);
DbgTypedValue Cast(BfAstNode* srcNode, const DbgTypedValue& val, DbgType* toType, bool explicitCast = false, bool silentFail = false);
bool HasField(DbgType* type, const StringImpl& fieldName);
DbgTypedValue DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis);
DbgTypedValue LookupField(BfAstNode* targetSrc, DbgTypedValue target, const StringImpl& fieldName);
DbgTypedValue DoLookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError, bool* hadError);
DbgTypedValue LookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
void LookupSplatMember(const DbgTypedValue& target, const StringImpl& fieldName);
void LookupSplatMember(BfAstNode* srcNode, BfAstNode* lookupNode, const DbgTypedValue& target, const StringImpl& fieldName, String* outFindName = NULL, bool* outIsConst = NULL, StringImpl* forceName = NULL);
void LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ignoreInitialError = false, bool* hadError = NULL);
DbgType* FindSubtype(DbgType* type, const StringImpl& name);
void LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError = false);
bool EnsureRunning(BfAstNode* astNode);
virtual void Visit(BfAssignmentExpression* assignExpr) override;
virtual void Visit(BfParenthesizedExpression* parenExpr) override;
virtual void Visit(BfMemberReferenceExpression* memberRefExpr) override;
virtual void Visit(BfIndexerExpression* indexerExpr) override;
virtual void Visit(BfQualifiedNameNode* nameNode) override;
virtual void Visit(BfThisExpression* thisExpr) override;
virtual void Visit(BfIdentifierNode* node) override;
virtual void Visit(BfAttributedIdentifierNode* node) override;
virtual void Visit(BfMixinExpression* mixinExpr) override;
virtual void Visit(BfAstNode* node) override;
virtual void Visit(BfDefaultExpression* defaultExpr) override;
virtual void Visit(BfLiteralExpression* literalExpr) override;
virtual void Visit(BfCastExpression* castExpr) override;
virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override;
virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
virtual void Visit(BfInvocationExpression* invocationExpr) override;
virtual void Visit(BfConditionalExpression* condExpr) override;
virtual void Visit(BfTypeAttrExpression* typeAttrExpr) override;
virtual void Visit(BfTupleExpression* tupleExpr) override;
DbgTypedValue Resolve(BfExpression* expr, DbgType* wantType = NULL);
BfAstNode* FinalizeExplicitThisReferences(BfAstNode* headNode);
};
NS_BF_DBG_END