mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 20:42:21 +02:00
Comptime debugging
This commit is contained in:
parent
bbb97d1490
commit
ff2e40e3bf
40 changed files with 6213 additions and 443 deletions
|
@ -750,6 +750,11 @@ public:
|
|||
return (mKind == BfTypedValueKind_UntypedValue);
|
||||
}
|
||||
|
||||
bool IsNoValueType() const
|
||||
{
|
||||
return (mKind == BfTypedValueKind_NoValue);
|
||||
}
|
||||
|
||||
bool IsParams()
|
||||
{
|
||||
return (mKind == BfTypedValueKind_ParamsSplat) || (mKind == BfTypedValueKind_Params);
|
||||
|
|
|
@ -7658,6 +7658,12 @@ void BfCompiler::Cancel()
|
|||
mCanceling = true;
|
||||
mFastFinish = true;
|
||||
mHadCancel = true;
|
||||
if (mCEMachine != NULL)
|
||||
{
|
||||
AutoCrit autoCrit(mCEMachine->mCritSect);
|
||||
mCEMachine->mSpecialCheck = true;
|
||||
mFastFinish = true;
|
||||
}
|
||||
BfLogSysM("BfCompiler::Cancel\n");
|
||||
BpEvent("BfCompiler::Cancel", "");
|
||||
}
|
||||
|
@ -7665,6 +7671,8 @@ void BfCompiler::Cancel()
|
|||
void BfCompiler::RequestFastFinish()
|
||||
{
|
||||
mFastFinish = true;
|
||||
if (mCEMachine != NULL)
|
||||
mCEMachine->mSpecialCheck = true;
|
||||
BfLogSysM("BfCompiler::RequestFastFinish\n");
|
||||
BpEvent("BfCompiler::RequestFastFinish", "");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "BfFixits.h"
|
||||
#include "CeMachine.h"
|
||||
#include "BfDefBuilder.h"
|
||||
#include "CeMachine.h"
|
||||
#include "CeDebugger.h"
|
||||
|
||||
#pragma warning(pop)
|
||||
#pragma warning(disable:4996)
|
||||
|
@ -4018,6 +4020,35 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
|
|||
|
||||
BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringImpl& findName, bool ignoreInitialError, bool* hadError)
|
||||
{
|
||||
if ((mModule->mCompiler->mCEMachine != NULL) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
|
||||
{
|
||||
auto ceDebugger = mModule->mCompiler->mCEMachine->mDebugger;
|
||||
auto ceContext = ceDebugger->mCurDbgState->mCeContext;
|
||||
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
|
||||
if (activeFrame->mFunction->mDbgInfo != NULL)
|
||||
{
|
||||
int instIdx = activeFrame->GetInstIdx();
|
||||
for (auto& dbgVar : activeFrame->mFunction->mDbgInfo->mVariables)
|
||||
{
|
||||
if (dbgVar.mName == findName)
|
||||
{
|
||||
if (dbgVar.mValue.mKind == CeOperandKind_AllocaAddr)
|
||||
{
|
||||
return BfTypedValue(mModule->mBfIRBuilder->CreateConstAggCE(mModule->mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs), dbgVar.mType, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (findName == "FR")
|
||||
{
|
||||
auto ptrType = mModule->CreatePointerType(mModule->GetPrimitiveType(BfTypeCode_UInt8));
|
||||
auto intVal = mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, activeFrame->mFrameAddr);
|
||||
auto ptrVal = mModule->mBfIRBuilder->CreateIntToPtr(intVal, mModule->mBfIRBuilder->MapType(ptrType));
|
||||
return BfTypedValue(ptrVal, ptrType);
|
||||
}
|
||||
}
|
||||
|
||||
auto identifierNode = BfNodeDynCast<BfIdentifierNode>(refNode);
|
||||
if (mModule->mCurMethodState != NULL)
|
||||
{
|
||||
|
@ -4649,7 +4680,8 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
|
|||
|
||||
if (isFailurePass)
|
||||
{
|
||||
mModule->Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", mModule->TypeToString(typeInstance).c_str(), fieldDef->mName.c_str()), targetSrc);
|
||||
if (mModule->GetCeDbgState() == NULL)
|
||||
mModule->Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", mModule->TypeToString(typeInstance).c_str(), fieldDef->mName.c_str()), targetSrc);
|
||||
}
|
||||
|
||||
auto resolvePassData = mModule->mCompiler->mResolvePassData;
|
||||
|
@ -6039,23 +6071,46 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
CeEvalFlags evalFlags = CeEvalFlags_None;
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NoCeRebuildFlags) != 0)
|
||||
evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_NoRebuild);
|
||||
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
|
||||
if (constRet)
|
||||
|
||||
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
|
||||
{
|
||||
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
|
||||
BF_ASSERT(!constRet.mType->IsVar());
|
||||
return constRet;
|
||||
}
|
||||
auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
|
||||
if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowCalls) != 0)
|
||||
{
|
||||
ceDbgState->mHadSideEffects = true;
|
||||
|
||||
if (mModule->mCompiler->mFastFinish)
|
||||
{
|
||||
if ((mModule->mCurMethodInstance == NULL) || (!mModule->mCurMethodInstance->mIsAutocompleteMethod))
|
||||
{
|
||||
// We didn't properly resolve this so queue for a rebuild later
|
||||
mModule->DeferRebuildType(mModule->mCurTypeInstance);
|
||||
SetAndRestoreValue<CeDebugger*> prevDebugger(mModule->mCompiler->mCEMachine->mDebugger, NULL);
|
||||
|
||||
evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_DbgCall);
|
||||
auto result = ceDbgState->mCeContext->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
ceDbgState->mBlockedSideEffects = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
|
||||
if (constRet)
|
||||
{
|
||||
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
|
||||
BF_ASSERT(!constRet.mType->IsVar());
|
||||
return constRet;
|
||||
}
|
||||
|
||||
if (mModule->mCompiler->mFastFinish)
|
||||
{
|
||||
if ((mModule->mCurMethodInstance == NULL) || (!mModule->mCurMethodInstance->mIsAutocompleteMethod))
|
||||
{
|
||||
// We didn't properly resolve this so queue for a rebuild later
|
||||
mModule->DeferRebuildType(mModule->mCurTypeInstance);
|
||||
}
|
||||
}
|
||||
doConstReturn = true;
|
||||
}
|
||||
doConstReturn = true;
|
||||
}
|
||||
}
|
||||
else if (mModule->mIsComptimeModule)
|
||||
|
@ -17499,6 +17554,51 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto ceDbgState = mModule->GetCeDbgState())
|
||||
{
|
||||
if (targetFunctionName.StartsWith("__"))
|
||||
{
|
||||
auto ceDebugger = mModule->mCompiler->mCEMachine->mDebugger;
|
||||
|
||||
auto _ResolveArg = [&](int argIdx, BfType* type = NULL)
|
||||
{
|
||||
if (argIdx >= args.mSize)
|
||||
return BfTypedValue();
|
||||
return mModule->CreateValueFromExpression(args[argIdx], type);
|
||||
};
|
||||
|
||||
if (targetFunctionName == "__getHighBits")
|
||||
{
|
||||
auto typedVal = _ResolveArg(0);
|
||||
if ((typedVal) && (typedVal.mType->IsPrimitiveType()))
|
||||
{
|
||||
auto primType = (BfPrimitiveType*)typedVal.mType;
|
||||
|
||||
int64 val = ceDebugger->ValueToInt(typedVal);
|
||||
int64 bitCount = ceDebugger->ValueToInt(_ResolveArg(1));
|
||||
int64 resultVal = val >> (typedVal.mType->mSize * 8 - bitCount);
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)resultVal), typedVal.mType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (targetFunctionName == "__clearHighBits")
|
||||
{
|
||||
auto typedVal = _ResolveArg(0);
|
||||
if ((typedVal) && (typedVal.mType->IsPrimitiveType()))
|
||||
{
|
||||
auto primType = (BfPrimitiveType*)typedVal.mType;
|
||||
|
||||
int64 val = ceDebugger->ValueToInt(typedVal);
|
||||
int64 bitCount = ceDebugger->ValueToInt(_ResolveArg(1));
|
||||
int64 andBits = (0x8000000000000000LL) >> ((typedVal.mType->mSize - 8) * 8 + bitCount - 1);
|
||||
int64 resultVal = val & ~andBits;
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)resultVal), typedVal.mType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (auto expr = BfNodeDynCast<BfExpression>(target))
|
||||
{
|
||||
|
@ -18968,7 +19068,7 @@ BfTypedValue BfExprEvaluator::PerformAssignment_CheckOp(BfAssignmentExpression*
|
|||
}
|
||||
|
||||
void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue)
|
||||
{
|
||||
{
|
||||
auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp);
|
||||
|
||||
BfExpression* targetNode = assignExpr->mLeft;
|
||||
|
@ -19375,10 +19475,54 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
|||
}
|
||||
else if (!alreadyWritten)
|
||||
{
|
||||
//ptr = mModule->LoadValue(ptr);
|
||||
BF_ASSERT(ptr.IsAddr());
|
||||
convVal = mModule->LoadValue(convVal);
|
||||
auto storeInst = mModule->mBfIRBuilder->CreateAlignedStore(convVal.mValue, ptr.mValue, ptr.mType->mAlign, mIsVolatileReference);
|
||||
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
|
||||
{
|
||||
auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
|
||||
bool success = false;
|
||||
|
||||
if ((convVal.mValue.IsConst()) && (ptr.mValue.IsConst()))
|
||||
{
|
||||
auto constant = mModule->mBfIRBuilder->GetConstant(ptr.mValue);
|
||||
auto valConstant = mModule->mBfIRBuilder->GetConstant(convVal.mValue);
|
||||
|
||||
auto ceTypedVal = mModule->mCompiler->mCEMachine->mDebugger->GetAddr(constant);
|
||||
if (!ceTypedVal)
|
||||
{
|
||||
mModule->Fail("Invalid assignment address", assignExpr);
|
||||
return;
|
||||
}
|
||||
|
||||
auto ceContext = mModule->mCompiler->mCEMachine->mCurContext;
|
||||
if (ceContext->CheckMemory(ceTypedVal.mAddr, convVal.mType->mSize))
|
||||
{
|
||||
if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowSideEffects) != 0)
|
||||
{
|
||||
ceDbgState->mHadSideEffects = true;
|
||||
if (ceContext->WriteConstant(mModule, ceTypedVal.mAddr, valConstant, convVal.mType))
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ceDbgState->mBlockedSideEffects = true;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
mModule->Fail("Assignment failed", assignExpr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyWritten)
|
||||
{
|
||||
//ptr = mModule->LoadValue(ptr);
|
||||
BF_ASSERT(ptr.IsAddr());
|
||||
convVal = mModule->LoadValue(convVal);
|
||||
auto storeInst = mModule->mBfIRBuilder->CreateAlignedStore(convVal.mValue, ptr.mValue, ptr.mType->mAlign, mIsVolatileReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21570,7 +21714,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
|
|||
leftValue.mType = leftValue.mType->GetUnderlyingType();
|
||||
|
||||
if ((binaryOp == BfBinaryOp_ConditionalAnd) || (binaryOp == BfBinaryOp_ConditionalOr))
|
||||
{
|
||||
{
|
||||
if (mModule->mCurMethodState->mDeferredLocalAssignData != NULL)
|
||||
mModule->mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
|
||||
if (mModule->mCurMethodState->mCurScope->mScopeKind == BfScopeKind_StatementTarget)
|
||||
|
|
|
@ -1684,6 +1684,12 @@ String BfIRBuilder::ToString(BfIRValue irValue)
|
|||
BfIRValue targetConst(BfIRValueFlags_Const, box->mTarget);
|
||||
return ToString(targetConst) + " box to " + ToString(box->mToType);
|
||||
}
|
||||
else if (constant->mConstType == BfConstType_GEP32_1)
|
||||
{
|
||||
auto gepConst = (BfConstantGEP32_1*)constant;
|
||||
BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
|
||||
return ToString(targetConst) + StrFormat(" Gep32 %d", gepConst->mIdx0);
|
||||
}
|
||||
else if (constant->mConstType == BfConstType_GEP32_2)
|
||||
{
|
||||
auto gepConst = (BfConstantGEP32_2*)constant;
|
||||
|
@ -4616,8 +4622,30 @@ BfIRValue BfIRBuilder::CreateIntToPtr(BfIRValue val, BfIRType type)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
BfIRValue BfIRBuilder::CreateIntToPtr(uint64 val, BfIRType type)
|
||||
{
|
||||
return CreateIntToPtr(CreateConst(BfTypeCode_IntPtr, val), type);
|
||||
}
|
||||
|
||||
BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0)
|
||||
{
|
||||
if (val.IsConst())
|
||||
{
|
||||
auto constGEP = mTempAlloc.Alloc<BfConstantGEP32_1>();
|
||||
constGEP->mConstType = BfConstType_GEP32_1;
|
||||
constGEP->mTarget = val.mId;
|
||||
constGEP->mIdx0 = idx0;
|
||||
|
||||
BfIRValue retVal;
|
||||
retVal.mFlags = BfIRValueFlags_Const;
|
||||
retVal.mId = mTempAlloc.GetChunkedId(constGEP);
|
||||
|
||||
#ifdef CHECK_CONSTHOLDER
|
||||
retVal.mHolder = this;
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
|
||||
BfIRValue retVal = WriteCmd(BfIRCmd_InboundsGEP1_32, val, idx0);
|
||||
NEW_CMD_INSERTED_IRVALUE;
|
||||
return retVal;
|
||||
|
@ -4650,6 +4678,39 @@ BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0, int idx1)
|
|||
|
||||
BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, BfIRValue idx0)
|
||||
{
|
||||
auto constant = GetConstant(val);
|
||||
if (constant != NULL)
|
||||
{
|
||||
if (constant->mConstType == BfConstType_IntToPtr)
|
||||
{
|
||||
auto fromPtrToInt = (BfConstantIntToPtr*)constant;
|
||||
auto fromTarget = GetConstantById(fromPtrToInt->mTarget);
|
||||
if (IsInt(fromTarget->mTypeCode))
|
||||
{
|
||||
if (fromPtrToInt->mToType.mKind == BfIRTypeData::TypeKind_TypeId)
|
||||
{
|
||||
auto type = mModule->mContext->mTypes[fromPtrToInt->mToType.mId];
|
||||
if (type->IsPointer())
|
||||
{
|
||||
auto elementType = type->GetUnderlyingType();
|
||||
auto addConstant = GetConstant(idx0);
|
||||
if ((addConstant != NULL) && (IsInt(addConstant->mTypeCode)))
|
||||
{
|
||||
return CreateIntToPtr(CreateConst(fromTarget->mTypeCode, (uint64)(fromTarget->mInt64 + addConstant->mInt64 * elementType->GetStride())),
|
||||
fromPtrToInt->mToType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto idxConstant = GetConstant(idx0))
|
||||
{
|
||||
if (IsInt(idxConstant->mTypeCode))
|
||||
return CreateInBoundsGEP(val, idxConstant->mInt32);
|
||||
}
|
||||
}
|
||||
|
||||
BfIRValue retVal = WriteCmd(BfIRCmd_InBoundsGEP1, val, idx0);
|
||||
NEW_CMD_INSERTED_IRVALUE;
|
||||
return retVal;
|
||||
|
|
|
@ -126,6 +126,7 @@ enum BfConstType
|
|||
BfConstType_GlobalVar = BfTypeCode_Length,
|
||||
BfConstType_BitCast,
|
||||
BfConstType_BitCastNull,
|
||||
BfConstType_GEP32_1,
|
||||
BfConstType_GEP32_2,
|
||||
BfConstType_ExtractValue,
|
||||
BfConstType_PtrToInt,
|
||||
|
@ -878,6 +879,13 @@ struct BfConstantIntToPtr
|
|||
BfIRType mToType;
|
||||
};
|
||||
|
||||
struct BfConstantGEP32_1
|
||||
{
|
||||
BfConstType mConstType;
|
||||
int mTarget;
|
||||
int mIdx0;
|
||||
};
|
||||
|
||||
struct BfConstantGEP32_2
|
||||
{
|
||||
BfConstType mConstType;
|
||||
|
@ -1223,6 +1231,7 @@ public:
|
|||
BfIRValue CreateBitCast(BfIRValue val, BfIRType type);
|
||||
BfIRValue CreatePtrToInt(BfIRValue val, BfTypeCode typeCode);
|
||||
BfIRValue CreateIntToPtr(BfIRValue val, BfIRType type);
|
||||
BfIRValue CreateIntToPtr(uint64 val, BfIRType type);
|
||||
BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0);
|
||||
BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0, int idx1);
|
||||
BfIRValue CreateInBoundsGEP(BfIRValue val, BfIRValue idx0);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "BfDefBuilder.h"
|
||||
#include "BfDeferEvalChecker.h"
|
||||
#include "CeMachine.h"
|
||||
#include "CeDebugger.h"
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -1045,7 +1046,7 @@ void BfModule::FinishInit()
|
|||
mHasFullDebugInfo = moduleOptions.mEmitDebugInfo == 1;
|
||||
|
||||
if (mIsComptimeModule)
|
||||
mHasFullDebugInfo = false;
|
||||
mHasFullDebugInfo = true;
|
||||
|
||||
if (((!mCompiler->mIsResolveOnly) && (!mIsScratchModule) && (moduleOptions.mEmitDebugInfo != 0) && (mIsReified)) ||
|
||||
(mIsComptimeModule))
|
||||
|
@ -1732,6 +1733,15 @@ String* BfModule::GetStringPoolString(BfIRValue constantStr, BfIRConstHolder * c
|
|||
return NULL;
|
||||
}
|
||||
|
||||
CeDbgState* BfModule::GetCeDbgState()
|
||||
{
|
||||
if (!mIsComptimeModule)
|
||||
return NULL;
|
||||
if ((mCompiler->mCEMachine != NULL) && (mCompiler->mCEMachine->mDebugger != NULL))
|
||||
return mCompiler->mCEMachine->mDebugger->mCurDbgState;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BfIRValue BfModule::GetStringCharPtr(int stringId, bool force)
|
||||
{
|
||||
if ((mBfIRBuilder->mIgnoreWrites) && (!force))
|
||||
|
@ -3066,8 +3076,10 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
|
||||
//BF_ASSERT(refNode != NULL);
|
||||
|
||||
if (mIsComptimeModule)
|
||||
if ((mIsComptimeModule) && (!mCompiler->mCEMachine->mDbgPaused))
|
||||
{
|
||||
mHadBuildError = true;
|
||||
|
||||
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
|
||||
{
|
||||
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
|
||||
|
@ -3075,8 +3087,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
mCompiler->mPassInstance->MoreInfo(error, refNode);
|
||||
return bfError;
|
||||
}
|
||||
|
||||
mHadBuildError = true;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4139,7 +4150,7 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
|
|||
}
|
||||
}
|
||||
else if (mBfIRBuilder != NULL)
|
||||
{
|
||||
{
|
||||
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
|
||||
|
||||
SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
|
||||
|
@ -12452,6 +12463,39 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
|
|||
return GetDefaultTypedValue(typedValue.mType);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
|
||||
{
|
||||
auto ceDebugger = mCompiler->mCEMachine->mDebugger;
|
||||
auto ceContext = ceDebugger->mCurDbgState->mCeContext;
|
||||
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
|
||||
|
||||
auto ceTypedValue = ceDebugger->GetAddr(constantValue);
|
||||
if (ceTypedValue)
|
||||
{
|
||||
if ((typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()))
|
||||
{
|
||||
void* data = ceContext->GetMemoryPtr(ceTypedValue.mAddr, sizeof(addr_ce));
|
||||
if (data == NULL)
|
||||
{
|
||||
Fail("Invalid address", refNode);
|
||||
return GetDefaultTypedValue(typedValue.mType);
|
||||
}
|
||||
|
||||
addr_ce dataAddr = *(addr_ce*)data;
|
||||
return BfTypedValue(mBfIRBuilder->CreateIntToPtr(
|
||||
mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)dataAddr), mBfIRBuilder->MapType(typedValue.mType)), typedValue.mType);
|
||||
}
|
||||
|
||||
auto constVal = ceContext->CreateConstant(this, ceContext->mMemory.mVals + ceTypedValue.mAddr, typedValue.mType);
|
||||
if (!constVal)
|
||||
{
|
||||
Fail("Failed to create const", refNode);
|
||||
return GetDefaultTypedValue(typedValue.mType);
|
||||
}
|
||||
return BfTypedValue(constVal, typedValue.mType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14605,6 +14649,11 @@ void BfModule::MarkUsingThis()
|
|||
|
||||
BfTypedValue BfModule::GetThis(bool markUsing)
|
||||
{
|
||||
if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
|
||||
{
|
||||
return mCompiler->mCEMachine->mDebugger->mCurDbgState->mExplicitThis;
|
||||
}
|
||||
|
||||
auto useMethodState = mCurMethodState;
|
||||
while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
|
||||
{
|
||||
|
@ -14628,7 +14677,7 @@ BfTypedValue BfModule::GetThis(bool markUsing)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
//TODO: Do we allow useMethodState to be NULL anymore?
|
||||
return BfTypedValue();
|
||||
}
|
||||
|
@ -16616,6 +16665,7 @@ void BfModule::EmitDtorBody()
|
|||
}
|
||||
else
|
||||
{
|
||||
PopulateType(fieldInst->mResolvedType);
|
||||
if (fieldInst->mResolvedType->IsValuelessType())
|
||||
{
|
||||
value = mBfIRBuilder->GetFakeVal();
|
||||
|
|
|
@ -33,6 +33,7 @@ class BfType;
|
|||
class BfResolvedType;
|
||||
class BfExprEvaluator;
|
||||
class CeEmitContext;
|
||||
class CeDbgState;
|
||||
|
||||
enum BfPopulateType
|
||||
{
|
||||
|
@ -1543,6 +1544,7 @@ public:
|
|||
void VerifyOnDemandMethods();
|
||||
bool IsSkippingExtraResolveChecks();
|
||||
bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing, bool isWarning);
|
||||
CeDbgState* GetCeDbgState();
|
||||
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false);
|
||||
BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
|
||||
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
|
||||
|
|
|
@ -12086,7 +12086,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
|
||||
{
|
||||
if ((!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
|
||||
{
|
||||
{
|
||||
if (!ignoreErrors)
|
||||
Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
else if (!silentFail)
|
||||
|
|
|
@ -720,7 +720,7 @@ BfBlock* BfParser::ParseInlineBlock(int spaceIdx, int endIdx)
|
|||
|
||||
while (true)
|
||||
{
|
||||
NextToken(endIdx + 1);
|
||||
NextToken(endIdx + 1, false, true);
|
||||
if (mSyntaxToken == BfSyntaxToken_HIT_END_IDX)
|
||||
{
|
||||
mSrcIdx = usedEndIdx;
|
||||
|
@ -1384,7 +1384,7 @@ double BfParser::ParseLiteralDouble()
|
|||
return strtod(buf, NULL);
|
||||
}
|
||||
|
||||
void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||
void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePreprocessor)
|
||||
{
|
||||
auto prevToken = mToken;
|
||||
|
||||
|
@ -2337,7 +2337,13 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
}
|
||||
break;
|
||||
case '#':
|
||||
HandlePreprocessor();
|
||||
if (disablePreprocessor)
|
||||
{
|
||||
TokenFail("Unexpected character");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
HandlePreprocessor();
|
||||
if (mSyntaxToken == BfSyntaxToken_EOF)
|
||||
return;
|
||||
break;
|
||||
|
|
|
@ -227,7 +227,7 @@ public:
|
|||
void MoveSource(const char* data, int length); // Takes ownership of data ptr
|
||||
void RefSource(const char* data, int length);
|
||||
void MakeNegative(uint64& val, bool& hadOverflow);
|
||||
void NextToken(int endIdx = -1, bool outerIsInterpolate = false);
|
||||
void NextToken(int endIdx = -1, bool outerIsInterpolate = false, bool disablePreprocessor = false);
|
||||
BfAstNode* CreateNode();
|
||||
|
||||
void Parse(BfPassInstance* passInstance);
|
||||
|
|
|
@ -3503,6 +3503,10 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa
|
|||
BF_ASSERT(sizeExpr != NULL);
|
||||
if (sizeExpr != NULL)
|
||||
{
|
||||
BfMethodState methodState;
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodState(ctx->mModule->mCurMethodState, &methodState);
|
||||
methodState.mTempKind = BfMethodState::TempKind_Static;
|
||||
|
||||
BfConstResolver constResolver(ctx->mModule);
|
||||
BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||
constResolver.mAllowGenericConstValue = true;
|
||||
|
|
|
@ -3523,7 +3523,7 @@ void BfModule::VisitCodeBlock(BfBlock* block)
|
|||
mCurMethodState->mMixinState->mResultExpr = expr;
|
||||
break;
|
||||
}
|
||||
else if ((mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
|
||||
else if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
|
||||
{
|
||||
// Only in mixin definition - result ignored
|
||||
CreateValueFromExpression(expr);
|
||||
|
|
|
@ -27,6 +27,14 @@ String Beefy::EncodeDataPtr(uint32 addr, bool doPrefix)
|
|||
return StrFormat("%08X", addr);
|
||||
}
|
||||
|
||||
String Beefy::EncodeDataPtr(int addr, bool doPrefix)
|
||||
{
|
||||
if (doPrefix)
|
||||
return StrFormat("0x%08X", addr);
|
||||
else
|
||||
return StrFormat("%08X", addr);
|
||||
}
|
||||
|
||||
String Beefy::EncodeDataPtr(uint64 addr, bool doPrefix)
|
||||
{
|
||||
if (doPrefix)
|
||||
|
|
|
@ -269,6 +269,7 @@ void* DecodeLocalDataPtr(const char*& strRef);
|
|||
String EncodeDataPtr(void* addr, bool doPrefix);
|
||||
String EncodeDataPtr(uint32 addr, bool doPrefix);
|
||||
String EncodeDataPtr(uint64 addr, bool doPrefix);
|
||||
String EncodeDataPtr(int addr, bool doPrefix);
|
||||
void* ZeroedAlloc(int size);
|
||||
/*template <typename T>
|
||||
T* ZeroedAlloc()
|
||||
|
|
4239
IDEHelper/Compiler/CeDebugger.cpp
Normal file
4239
IDEHelper/Compiler/CeDebugger.cpp
Normal file
File diff suppressed because it is too large
Load diff
357
IDEHelper/Compiler/CeDebugger.h
Normal file
357
IDEHelper/Compiler/CeDebugger.h
Normal file
|
@ -0,0 +1,357 @@
|
|||
#pragma once
|
||||
|
||||
#include "BfSystem.h"
|
||||
#include "BfModule.h"
|
||||
#include "BeefySysLib/util/Heap.h"
|
||||
#include "BeefySysLib/util/AllocDebug.h"
|
||||
#include "../Debugger.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BfCompiler;
|
||||
class CeFrame;
|
||||
class CeExprEvaluator;
|
||||
class CeContext;
|
||||
class CeMachine;
|
||||
class CeFunction;
|
||||
class BfReducer;
|
||||
class CeDebugger;
|
||||
class DebugVisualizerEntry;
|
||||
|
||||
class CeBreakpoint : public Breakpoint
|
||||
{
|
||||
public:
|
||||
uintptr mCurBindAddr;
|
||||
bool mHasBound;
|
||||
int mIdx;
|
||||
|
||||
public:
|
||||
CeBreakpoint()
|
||||
{
|
||||
mCurBindAddr = 1;
|
||||
mHasBound = false;
|
||||
mIdx = -1;
|
||||
}
|
||||
|
||||
virtual uintptr GetAddr() { return mCurBindAddr; }
|
||||
virtual bool IsMemoryBreakpointBound() { return false; }
|
||||
};
|
||||
|
||||
struct CeFormatInfo
|
||||
{
|
||||
int mCallStackIdx;
|
||||
bool mHidePointers;
|
||||
bool mIgnoreDerivedClassInfo;
|
||||
bool mNoVisualizers;
|
||||
bool mNoMembers;
|
||||
bool mRawString;
|
||||
bool mNoEdit;
|
||||
DbgTypeKindFlags mTypeKindFlags;
|
||||
intptr mArrayLength;
|
||||
intptr mOverrideCount;
|
||||
intptr mMaxCount;
|
||||
DwDisplayType mDisplayType;
|
||||
int mTotalSummaryLength;
|
||||
String mReferenceId;
|
||||
String mSubjectExpr;
|
||||
String mExpectedType;
|
||||
String mNamespaceSearch;
|
||||
int mExpandItemDepth;
|
||||
BfTypedValue mExplicitThis;
|
||||
|
||||
CeFormatInfo()
|
||||
{
|
||||
mCallStackIdx = -1;
|
||||
mHidePointers = false;
|
||||
mIgnoreDerivedClassInfo = false;
|
||||
mRawString = false;
|
||||
mNoVisualizers = false;
|
||||
mNoMembers = false;
|
||||
mNoEdit = false;
|
||||
mTypeKindFlags = DbgTypeKindFlag_None;
|
||||
mArrayLength = -1;
|
||||
mOverrideCount = -1;
|
||||
mMaxCount = -1;
|
||||
mTotalSummaryLength = 0;
|
||||
mDisplayType = DwDisplayType_NotSpecified;
|
||||
mExpandItemDepth = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CeEvaluationContext
|
||||
{
|
||||
public:
|
||||
CeDebugger* mDebugger;
|
||||
BfParser* mParser;
|
||||
BfReducer* mReducer;
|
||||
BfPassInstance* mPassInstance;
|
||||
BfExprEvaluator* mExprEvaluator;
|
||||
BfExpression* mExprNode;
|
||||
BfTypedValue mResultOverride;
|
||||
String mExprString;
|
||||
|
||||
BfTypedValue mExplicitThis;
|
||||
int mCallStackIdx;
|
||||
|
||||
public:
|
||||
CeEvaluationContext(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo = NULL, BfTypedValue contextValue = BfTypedValue());
|
||||
void Init(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo = NULL, BfTypedValue contextValue = BfTypedValue());
|
||||
bool HasExpression();
|
||||
~CeEvaluationContext();
|
||||
BfTypedValue EvaluateInContext(BfTypedValue contextTypedValue);
|
||||
String GetErrorStr();
|
||||
bool HadError();
|
||||
};
|
||||
|
||||
class CeDbgState
|
||||
{
|
||||
public:
|
||||
CeFrame* mActiveFrame;
|
||||
CeContext* mCeContext;
|
||||
BfTypedValue mExplicitThis;
|
||||
DwEvalExpressionFlags mDbgExpressionFlags;
|
||||
bool mHadSideEffects;
|
||||
bool mBlockedSideEffects;
|
||||
|
||||
public:
|
||||
CeDbgState()
|
||||
{
|
||||
mActiveFrame = NULL;
|
||||
mCeContext = NULL;
|
||||
mDbgExpressionFlags = DwEvalExpressionFlag_None;
|
||||
mHadSideEffects = false;
|
||||
mBlockedSideEffects = false;
|
||||
}
|
||||
};
|
||||
|
||||
class CePendingExpr
|
||||
{
|
||||
public:
|
||||
int mThreadId;
|
||||
BfParser* mParser;
|
||||
BfType* mExplitType;
|
||||
CeFormatInfo mFormatInfo;
|
||||
DwEvalExpressionFlags mExpressionFlags;
|
||||
int mCursorPos;
|
||||
BfAstNode* mExprNode;
|
||||
String mReferenceId;
|
||||
int mCallStackIdx;
|
||||
String mResult;
|
||||
int mIdleTicks;
|
||||
String mException;
|
||||
|
||||
CePendingExpr();
|
||||
~CePendingExpr();
|
||||
};
|
||||
|
||||
class CeFileInfo
|
||||
{
|
||||
public:
|
||||
Array<CeBreakpoint*> mOrderedBreakpoints;
|
||||
};
|
||||
|
||||
class CeDbgFieldEntry
|
||||
{
|
||||
public:
|
||||
BfType* mType;
|
||||
int mDataOffset;
|
||||
|
||||
public:
|
||||
CeDbgFieldEntry()
|
||||
{
|
||||
mType = NULL;
|
||||
mDataOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CeDbgTypeInfo
|
||||
{
|
||||
public:
|
||||
struct ConstIntEntry
|
||||
{
|
||||
public:
|
||||
int mFieldIdx;
|
||||
int64 mVal;
|
||||
};
|
||||
|
||||
public:
|
||||
BfType* mType;
|
||||
Array<CeDbgFieldEntry> mFieldOffsets;
|
||||
Array<ConstIntEntry> mConstIntEntries;
|
||||
};
|
||||
|
||||
struct CeTypedValue
|
||||
{
|
||||
addr_ce mAddr;
|
||||
BfIRType mType;
|
||||
|
||||
CeTypedValue()
|
||||
{
|
||||
mAddr = 0;
|
||||
mType = BfIRType();
|
||||
}
|
||||
|
||||
CeTypedValue(addr_ce addr, BfIRType type)
|
||||
{
|
||||
mAddr = addr;
|
||||
mType = type;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return mType.mKind != BfIRTypeData::TypeKind_None;
|
||||
}
|
||||
};
|
||||
|
||||
class CeDebugger : public Debugger
|
||||
{
|
||||
public:
|
||||
BfCompiler* mCompiler;
|
||||
CeMachine* mCeMachine;
|
||||
DebugManager* mDebugManager;
|
||||
CePendingExpr* mDebugPendingExpr;
|
||||
CeDbgState* mCurDbgState;
|
||||
Array<CeBreakpoint*> mBreakpoints;
|
||||
Dictionary<String, CeFileInfo*> mFileInfo;
|
||||
Dictionary<int, CeDbgTypeInfo> mDbgTypeInfoMap;
|
||||
|
||||
CeEvaluationContext* mCurEvaluationContext;
|
||||
CeBreakpoint* mActiveBreakpoint;
|
||||
int mBreakpointVersion;
|
||||
bool mBreakpointCacheDirty;
|
||||
bool mBreakpointFramesDirty;
|
||||
int mCurDisasmFuncId;
|
||||
|
||||
public:
|
||||
bool SetupStep(int frameIdx = 0);
|
||||
CeFrame* GetFrame(int callStackIdx);
|
||||
String EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance);
|
||||
String Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags);
|
||||
DwDisplayInfo* GetDisplayInfo(const StringImpl& referenceId);
|
||||
String GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, bool isStatic);
|
||||
DebugVisualizerEntry* FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures);
|
||||
bool ParseFormatInfo(const StringImpl& formatInfoStr, CeFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, BfTypedValue contextTypedValue = BfTypedValue());
|
||||
String MaybeQuoteFormatInfoParam(const StringImpl& str);
|
||||
BfTypedValue EvaluateInContext(const BfTypedValue& contextTypedValue, const StringImpl& subExpr, CeFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL);
|
||||
void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors);
|
||||
String GetArrayItems(DebugVisualizerEntry* debugVis, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData);
|
||||
String GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce endNodePtr, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData);
|
||||
String GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData);
|
||||
String GetTreeItems(DebugVisualizerEntry* debugVis, Array<addr_ce>& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData);
|
||||
bool EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr);
|
||||
CeTypedValue GetAddr(BfConstant* constant);
|
||||
CeTypedValue GetAddr(const BfTypedValue typeVal);
|
||||
String ReadString(BfTypeCode charType, intptr addr, intptr maxLength, CeFormatInfo& formatInfo);
|
||||
void ProcessEvalString(BfTypedValue useTypedValue, String& evalStr, String& displayString, CeFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength);
|
||||
String TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatFlags, bool fullPrecision = false);
|
||||
void HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array<String>& dbgVisWildcardCaptures, CeFormatInfo& formatInfo);
|
||||
void ClearBreakpointCache();
|
||||
void UpdateBreakpointCache();
|
||||
void UpdateBreakpointFrames();
|
||||
void UpdateBreakpointAddrs();
|
||||
void UpdateBreakpoints(CeFunction* ceFunction);
|
||||
void Continue();
|
||||
CeDbgTypeInfo* GetDbgTypeInfo(int typeId);
|
||||
CeDbgTypeInfo* GetDbgTypeInfo(BfIRType irType);
|
||||
int64 ValueToInt(const BfTypedValue& typedVal);
|
||||
BfType* FindType(const StringImpl& name);
|
||||
|
||||
public:
|
||||
CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler);
|
||||
~CeDebugger();
|
||||
|
||||
virtual void OutputMessage(const StringImpl& msg) override;
|
||||
virtual void OutputRawMessage(const StringImpl& msg) override;
|
||||
virtual int GetAddrSize() override;
|
||||
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) override;
|
||||
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override;
|
||||
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
|
||||
virtual void Run() override;
|
||||
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;
|
||||
virtual void InitiateHotResolve(DbgHotResolveFlags flags) override;
|
||||
virtual intptr GetDbgAllocHeapSize() override;
|
||||
virtual String GetDbgAllocInfo() override;
|
||||
virtual void Update() override;
|
||||
virtual void ContinueDebugEvent() override;
|
||||
virtual void ForegroundTarget() override;
|
||||
virtual Breakpoint* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
|
||||
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
|
||||
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
|
||||
virtual Breakpoint* CreateAddressBreakpoint(intptr address) override;
|
||||
virtual uintptr GetBreakpointAddr(Breakpoint* breakpoint) override;
|
||||
virtual void CheckBreakpoint(Breakpoint* breakpoint) override;
|
||||
virtual void HotBindBreakpoint(Breakpoint* wdBreakpoint, int lineNum, int hotIdx) override;
|
||||
virtual void DeleteBreakpoint(Breakpoint* wdBreakpoint) override;
|
||||
virtual void DetachBreakpoint(Breakpoint* wdBreakpoint) override;
|
||||
virtual void MoveBreakpoint(Breakpoint* wdBreakpoint, int lineNum, int wantColumn, bool rebindNow) override;
|
||||
virtual void MoveMemoryBreakpoint(Breakpoint* wdBreakpoint, intptr addr, int byteCount) override;
|
||||
virtual void DisableBreakpoint(Breakpoint* wdBreakpoint) override;
|
||||
virtual void SetBreakpointCondition(Breakpoint* wdBreakpoint, const StringImpl& condition) override;
|
||||
virtual void SetBreakpointLogging(Breakpoint* wdBreakpoint, const StringImpl& logging, bool breakAfterLogging) override;
|
||||
virtual Breakpoint* FindBreakpointAt(intptr address) override;
|
||||
virtual Breakpoint* GetActiveBreakpoint() override;
|
||||
virtual void BreakAll() override;
|
||||
virtual bool TryRunContinue() override;
|
||||
virtual void StepInto(bool inAssembly) override;
|
||||
virtual void StepIntoSpecific(intptr addr) override;
|
||||
virtual void StepOver(bool inAssembly) override;
|
||||
virtual void StepOut(bool inAssembly) override;
|
||||
virtual void SetNextStatement(bool inAssembly, const StringImpl& fileName, int64 lineNumOrAsmAddr, int wantColumn) override;
|
||||
//virtual DbgTypedValue GetRegister(const StringImpl& regName, CPURegisters* registers, Array<RegForm>* regForms = NULL) override;
|
||||
virtual String Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags) override;
|
||||
virtual String EvaluateContinue() override;
|
||||
virtual void EvaluateContinueKeep() override;
|
||||
virtual String EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos) override;
|
||||
virtual String EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos) override;
|
||||
virtual String GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count) override;
|
||||
virtual String GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen) override;
|
||||
virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
|
||||
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
|
||||
virtual String GetProcessInfo() override;
|
||||
virtual String GetThreadInfo() override;
|
||||
virtual void SetActiveThread(int threadId) override;
|
||||
virtual int GetActiveThread() override;
|
||||
virtual void FreezeThread(int threadId) override;
|
||||
virtual void ThawThread(int threadId) override;
|
||||
virtual bool IsActiveThreadWaiting() override;
|
||||
virtual void ClearCallStack() override;
|
||||
virtual void UpdateCallStack(bool slowEarlyOut = true) override;
|
||||
virtual int GetCallStackCount() override;
|
||||
virtual int GetRequestedStackFrameIdx() override;
|
||||
virtual int GetBreakStackFrameIdx() override;
|
||||
virtual bool ReadMemory(intptr address, uint64 length, void* dest, bool local = false) override;
|
||||
virtual bool WriteMemory(intptr address, void* src, uint64 length) override;
|
||||
virtual DbgMemoryFlags GetMemoryFlags(intptr address) override;
|
||||
virtual void UpdateRegisterUsage(int stackFrameIdx) override;
|
||||
virtual void UpdateCallStackMethod(int stackFrameIdx) override;
|
||||
virtual void GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override;
|
||||
virtual void GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) override;
|
||||
virtual String GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags) override;
|
||||
virtual String Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) override;
|
||||
virtual int GetJmpState(int stackFrameIdx) override;
|
||||
virtual intptr GetStackFrameCalleeAddr(int stackFrameIdx) override;
|
||||
virtual String GetStackMethodOwner(int stackFrameIdx, int& language) override;
|
||||
virtual String FindCodeAddresses(const StringImpl& fileName, int line, int column, bool allowAutoResolve) override;
|
||||
virtual String GetAddressSourceLocation(intptr address) override;
|
||||
virtual String GetAddressSymbolName(intptr address, bool demangle) override;
|
||||
virtual String DisassembleAtRaw(intptr address) override;
|
||||
virtual String DisassembleAt(intptr address) override;
|
||||
virtual String FindLineCallAddresses(intptr address) override;
|
||||
virtual String GetCurrentException() override;
|
||||
virtual String GetModulesInfo() override;
|
||||
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override;
|
||||
virtual void CancelSymSrv() override;
|
||||
virtual bool HasPendingDebugLoads() override;
|
||||
virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;
|
||||
virtual int LoadDebugInfoForModule(const StringImpl& moduleName) override;
|
||||
virtual int LoadDebugInfoForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;
|
||||
virtual void StopDebugging() override;
|
||||
virtual void Terminate() override;
|
||||
virtual void Detach() override;
|
||||
virtual Profiler* StartProfiling() override;
|
||||
virtual Profiler* PopProfiler() override; // Profiler requested by target program
|
||||
virtual void ReportMemory(MemReporter* memReporter) override;
|
||||
virtual bool IsOnDemandDebugger() override;
|
||||
};
|
||||
|
||||
NS_BF_END
|
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,8 @@ class BeSwitchInst;
|
|||
class BeGlobalVariable;
|
||||
class CeMachine;
|
||||
class CeFunction;
|
||||
class CeDebugger;
|
||||
class CeBreakpoint;
|
||||
|
||||
#define CEOP_SIZED(OPNAME) \
|
||||
CeOp_##OPNAME##_8, \
|
||||
|
@ -69,6 +71,7 @@ enum CeErrorKind
|
|||
enum CeOp : int16
|
||||
{
|
||||
CeOp_InvalidOp,
|
||||
CeOp_DbgBreak,
|
||||
CeOp_Ret,
|
||||
CeOp_SetRetType,
|
||||
CeOp_Jmp,
|
||||
|
@ -204,10 +207,55 @@ enum CeOp : int16
|
|||
CeOp_COUNT
|
||||
};
|
||||
|
||||
enum CeOperandKind
|
||||
{
|
||||
CeOperandKind_None,
|
||||
CeOperandKind_FrameOfs,
|
||||
CeOperandKind_AllocaAddr,
|
||||
CeOperandKind_Block,
|
||||
CeOperandKind_Immediate,
|
||||
CeOperandKind_ConstStructTableIdx,
|
||||
CeOperandKind_CallTableIdx
|
||||
};
|
||||
|
||||
class CeOperand
|
||||
{
|
||||
public:
|
||||
CeOperandKind mKind;
|
||||
union
|
||||
{
|
||||
int mFrameOfs;
|
||||
int mBlockIdx;
|
||||
int mImmediate;
|
||||
int mCallTableIdx;
|
||||
int mStructTableIdx;
|
||||
BeConstant* mConstant;
|
||||
};
|
||||
BeType* mType;
|
||||
|
||||
public:
|
||||
CeOperand()
|
||||
{
|
||||
mKind = CeOperandKind_None;
|
||||
mFrameOfs = 0;
|
||||
mType = NULL;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return mKind != CeOperandKind_None;
|
||||
}
|
||||
|
||||
bool IsImmediate()
|
||||
{
|
||||
return mKind == CeOperandKind_Immediate;
|
||||
}
|
||||
};
|
||||
|
||||
struct CeEmitEntry
|
||||
{
|
||||
int mCodePos;
|
||||
int mFile;
|
||||
int mScope;
|
||||
int mLine;
|
||||
int mColumn;
|
||||
};
|
||||
|
@ -490,6 +538,40 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CeDbgVariable
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
CeOperand mValue;
|
||||
BfType* mType;
|
||||
};
|
||||
|
||||
class CeDbgFunctionInfo
|
||||
{
|
||||
public:
|
||||
Array<CeDbgVariable> mVariables;
|
||||
};
|
||||
|
||||
class CeBreakpointBind
|
||||
{
|
||||
public:
|
||||
CeOp mPrevOpCode;
|
||||
CeBreakpoint* mBreakpoint;
|
||||
};
|
||||
|
||||
struct CeDbgScope
|
||||
{
|
||||
public:
|
||||
String mFilePath;
|
||||
int mInlinedAt;
|
||||
|
||||
public:
|
||||
CeDbgScope()
|
||||
{
|
||||
mInlinedAt = -1;
|
||||
}
|
||||
};
|
||||
|
||||
class CeFunction
|
||||
{
|
||||
public:
|
||||
|
@ -511,7 +593,7 @@ public:
|
|||
bool mFailed;
|
||||
bool mIsVarReturn;
|
||||
Array<uint8> mCode;
|
||||
Array<String> mFiles;
|
||||
Array<CeDbgScope> mDbgScopes;
|
||||
Array<CeEmitEntry> mEmitTable;
|
||||
Array<CeCallEntry> mCallTable;
|
||||
Array<CeStringEntry> mStringTable;
|
||||
|
@ -519,10 +601,13 @@ public:
|
|||
Array<CeStaticFieldEntry> mStaticFieldTable;
|
||||
Array<BfType*> mTypeTable;
|
||||
Array<CeFunction*> mInnerFunctions;
|
||||
Dictionary<int, CeBreakpointBind> mBreakpoints;
|
||||
String mGenError;
|
||||
int mFrameSize;
|
||||
int mMaxReturnSize;
|
||||
int mId;
|
||||
int mId;
|
||||
int mBreakpointVersion;
|
||||
CeDbgFunctionInfo* mDbgInfo;
|
||||
|
||||
public:
|
||||
CeFunction()
|
||||
|
@ -537,11 +622,15 @@ public:
|
|||
mIsVarReturn = false;
|
||||
mFrameSize = 0;
|
||||
mMaxReturnSize = 0;
|
||||
mBreakpointVersion = 0;
|
||||
mId = -1;
|
||||
mDbgInfo = NULL;
|
||||
}
|
||||
|
||||
~CeFunction();
|
||||
void Print();
|
||||
void UnbindBreakpoints();
|
||||
CeEmitEntry* FindEmitEntry(int loc, int* entryIdx = NULL);
|
||||
};
|
||||
|
||||
enum CeEvalFlags
|
||||
|
@ -551,52 +640,8 @@ enum CeEvalFlags
|
|||
CeEvalFlags_PersistantError = 2,
|
||||
CeEvalFlags_DeferIfNotOnlyError = 4,
|
||||
CeEvalFlags_NoRebuild = 8,
|
||||
CeEvalFlags_ForceReturnThis = 0x10
|
||||
};
|
||||
|
||||
enum CeOperandKind
|
||||
{
|
||||
CeOperandKind_None,
|
||||
CeOperandKind_FrameOfs,
|
||||
CeOperandKind_AllocaAddr,
|
||||
CeOperandKind_Block,
|
||||
CeOperandKind_Immediate,
|
||||
CeOperandKind_ConstStructTableIdx,
|
||||
CeOperandKind_CallTableIdx
|
||||
};
|
||||
|
||||
class CeOperand
|
||||
{
|
||||
public:
|
||||
CeOperandKind mKind;
|
||||
union
|
||||
{
|
||||
int mFrameOfs;
|
||||
int mBlockIdx;
|
||||
int mImmediate;
|
||||
int mCallTableIdx;
|
||||
int mStructTableIdx;
|
||||
BeConstant* mConstant;
|
||||
};
|
||||
BeType* mType;
|
||||
|
||||
public:
|
||||
CeOperand()
|
||||
{
|
||||
mKind = CeOperandKind_None;
|
||||
mFrameOfs = 0;
|
||||
mType = NULL;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return mKind != CeOperandKind_None;
|
||||
}
|
||||
|
||||
bool IsImmediate()
|
||||
{
|
||||
return mKind == CeOperandKind_Immediate;
|
||||
}
|
||||
CeEvalFlags_ForceReturnThis = 0x10,
|
||||
CeEvalFlags_DbgCall = 0x20
|
||||
};
|
||||
|
||||
#define BF_CE_DEFAULT_STACK_SIZE 4*1024*1024
|
||||
|
@ -609,7 +654,21 @@ public:
|
|||
enum CeOperandInfoKind
|
||||
{
|
||||
CEOI_None,
|
||||
CEOI_None8 = CEOI_None,
|
||||
CEOI_None16 = CEOI_None,
|
||||
CEOI_None32 = CEOI_None,
|
||||
CEOI_None64 = CEOI_None,
|
||||
CEOI_NoneF32 = CEOI_None,
|
||||
CEOI_NoneF64 = CEOI_None,
|
||||
|
||||
CEOI_FrameRef,
|
||||
CEOI_FrameRef8,
|
||||
CEOI_FrameRef16,
|
||||
CEOI_FrameRef32,
|
||||
CEOI_FrameRef64,
|
||||
CEOI_FrameRefF32,
|
||||
CEOI_FrameRefF64,
|
||||
|
||||
CEOI_IMM8,
|
||||
CEOI_IMM16,
|
||||
CEOI_IMM32,
|
||||
|
@ -631,18 +690,24 @@ enum CeSizeClass
|
|||
|
||||
class CeDumpContext
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
Dictionary<int, CeDbgVariable*> mVarMap;
|
||||
CeFunction* mCeFunction;
|
||||
String mStr;
|
||||
uint8* mStart;
|
||||
uint8* mPtr;
|
||||
uint8* mEnd;
|
||||
int mJmp;
|
||||
|
||||
public:
|
||||
CeDumpContext()
|
||||
{
|
||||
mJmp = -1;
|
||||
}
|
||||
|
||||
void DumpOperandInfo(CeOperandInfoKind operandInfoKind);
|
||||
|
||||
void Next();
|
||||
void Dump();
|
||||
};
|
||||
|
||||
|
@ -760,6 +825,11 @@ public:
|
|||
mInstPtr = NULL;
|
||||
mReturnType = NULL;
|
||||
}
|
||||
|
||||
int GetInstIdx()
|
||||
{
|
||||
return (int)(mInstPtr - &mFunction->mCode[0] - 2);
|
||||
}
|
||||
};
|
||||
|
||||
class CeStaticFieldInfo
|
||||
|
@ -909,6 +979,7 @@ public:
|
|||
BfType* GetBfType(BfIRType irType);
|
||||
void PrepareConstStructEntry(CeConstStructData& constStructData);
|
||||
bool CheckMemory(addr_ce addr, int32 size);
|
||||
uint8* GetMemoryPtr(addr_ce addr, int32 size);
|
||||
bool GetStringFromAddr(addr_ce strInstAddr, StringImpl& str);
|
||||
bool GetStringFromStringView(addr_ce addr, StringImpl& str);
|
||||
bool GetCustomAttribute(BfModule* module, BfIRConstHolder* constHolder, BfCustomAttributes* customAttributes, int attributeIdx, addr_ce resultAddr);
|
||||
|
@ -928,12 +999,40 @@ struct CeTypeInfo
|
|||
int mRevision;
|
||||
};
|
||||
|
||||
class CeStepState
|
||||
{
|
||||
public:
|
||||
enum Kind
|
||||
{
|
||||
Kind_None,
|
||||
Kind_StepOver,
|
||||
Kind_StepOver_Asm,
|
||||
Kind_StepInfo,
|
||||
Kind_StepInfo_Asm,
|
||||
Kind_StepOut,
|
||||
Kind_StepOut_Asm,
|
||||
Kind_Jmp
|
||||
};
|
||||
|
||||
Kind mKind;
|
||||
int mNextInstIdx;
|
||||
int mStartDepth;
|
||||
|
||||
public:
|
||||
CeStepState()
|
||||
{
|
||||
mKind = Kind_None;
|
||||
mNextInstIdx = -1;
|
||||
mStartDepth = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CeMachine
|
||||
{
|
||||
public:
|
||||
Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
|
||||
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
|
||||
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
|
||||
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit and debugging
|
||||
Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
|
||||
HashSet<BfMethodInstance*> mMethodInstanceSet;
|
||||
HashSet<BfFieldInstance*> mFieldInstanceSet;
|
||||
|
@ -959,6 +1058,14 @@ public:
|
|||
BfReducer* mTempReducer;
|
||||
BfPassInstance* mTempPassInstance;
|
||||
|
||||
CritSect mCritSect;
|
||||
SyncEvent mDebugEvent;
|
||||
CeStepState mStepState;
|
||||
CeDebugger* mDebugger;
|
||||
bool mDbgPaused;
|
||||
bool mSpecialCheck;
|
||||
bool mDbgWantBreak;
|
||||
|
||||
public:
|
||||
CeMachine(BfCompiler* compiler);
|
||||
~CeMachine();
|
||||
|
@ -967,6 +1074,7 @@ public:
|
|||
BeContext* GetBeContext();
|
||||
BeModule* GetBeModule();
|
||||
|
||||
int GetInstSize(CeFunction* ceFunction, int instIdx);
|
||||
void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
|
||||
void RemoveFunc(CeFunction* ceFunction);
|
||||
void RemoveMethod(BfMethodInstance* methodInstance);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue