mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-07 19:18:19 +02:00
487 lines
No EOL
15 KiB
C++
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 |