1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Extensive runtime refactor to reduce generated executable sizes

This commit is contained in:
Brian Fiete 2024-03-16 07:23:29 -04:00
parent 4e750a7e1a
commit ddd9b1b218
74 changed files with 2514 additions and 717 deletions

View file

@ -509,7 +509,7 @@ addr_target COFF::GetSectionAddr(uint16 section, uint32 offset)
return hiBase + offset;
}
int rva = mSectionRVAs[section - 1];
int rva = mSectionHeaders[section - 1].mVirtualAddress;
if (rva == 0)
return ADDR_FLAG_ABS + offset;
@ -5178,6 +5178,7 @@ bool COFF::CvParseDBI(int wantAge)
contribEntry->mLength = curSize;
contribEntry->mDbgModule = this;
contribEntry->mCompileUnitId = contrib.mModule;
contribEntry->mSection = contrib.mSection;
mDebugTarget->mContribMap.Insert(contribEntry);
}
}
@ -5288,7 +5289,7 @@ bool COFF::CvParseDBI(int wantAge)
void COFF::ParseSectionHeader(int sectionIdx)
{
bool fakeRVAS = mSectionRVAs.empty();
bool fakeRVAS = mSectionHeaders.empty();
int sectionSize = 0;
uint8* sectionData = CvReadStream(sectionIdx, &sectionSize);
@ -5300,12 +5301,15 @@ void COFF::ParseSectionHeader(int sectionIdx)
auto& sectionHeader = GET(PESectionHeader);
if (fakeRVAS)
{
mSectionRVAs.push_back(sectionHeader.mVirtualAddress);
mSectionHeaders.push_back(sectionHeader);
}
}
if (fakeRVAS)
mSectionRVAs.push_back(0);
{
PESectionHeader sectionHeader = { 0 };
mSectionHeaders.push_back(sectionHeader);
}
delete sectionData;
}

View file

@ -1220,7 +1220,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
Array<BfType*> vdataTypeList;
HashSet<BfModule*> usedModuleSet;
HashSet<BfType*> reflectTypeSet;
HashSet<BfType*> reflectSkipTypeSet;
HashSet<BfType*> reflectFieldTypeSet;
vdataHashCtx.MixinStr(project->mStartupObject);
@ -1398,20 +1398,49 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
bool madeBfTypeData = false;
auto typeDefType = mContext->mBfTypeType;
bool needsTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
bool needsFullTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
bool needsTypeList = needsFullTypeList || bfModule->IsMethodImplementedAndReified(typeDefType, "GetType_");
bool needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType");
bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName") || bfModule->IsMethodImplementedAndReified(typeDefType, "GetFullName");
bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern")) || (bfModule->IsMethodImplementedAndReified(stringViewType, "Intern"));
Dictionary<int, int> usedStringIdMap;
BfCreateTypeDataContext createTypeDataCtx;
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType));
if (!needsTypeList)
{
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mTypeTypeDef));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
}
if (!needsFullTypeList)
{
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectConstExprType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectPointerType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSizedArrayType));
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectRefType));
}
HashSet<BfType*> boxeeSet;
for (auto type : vdataTypeList)
{
auto typeInst = type->ToTypeInstance();
if ((!type->IsReified()) || (type->IsUnspecializedType()))
continue;
if (type->IsBoxed())
boxeeSet.Add(typeInst->GetUnderlyingType());
}
int usedTypeCount = 0;
HashSet<BfType*> vDataTypeSet;
SmallVector<BfIRValue, 256> typeDataVector;
Array<BfType*> usedTypeDataVector;
for (auto type : vdataTypeList)
{
if (type->IsTypeAlias())
@ -1425,9 +1454,12 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
continue;
bool needsTypeData = (needsTypeList) || ((type->IsObject()) && (needsObjectTypeData));
bool needsTypeData = (needsFullTypeList) || ((type->IsObject()) && (needsObjectTypeData));
bool needsVData = (type->IsObject()) && (typeInst->HasBeenInstantiated());
if ((needsObjectTypeData) && (boxeeSet.Contains(typeInst)))
needsTypeData = true;
bool forceReflectFields = false;
if (bfModule->mProject->mReferencedTypeData.Contains(type))
@ -1437,8 +1469,16 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
forceReflectFields = true;
}
BfIRValue typeVariable;
if (reflectSkipTypeSet.Contains(type))
{
if (!bfModule->mProject->mReferencedTypeData.Contains(type))
{
needsTypeData = false;
needsVData = false;
}
}
BfIRValue typeVariable;
if ((needsTypeData) || (needsVData))
{
if (reflectFieldTypeSet.Contains(type))
@ -1446,14 +1486,25 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
needsTypeData = true;
forceReflectFields = true;
}
else if (reflectTypeSet.Contains(type))
/*else if (reflectTypeSet.Contains(type))
{
needsTypeData = true;
needsVData = true;
}
}*/
typeVariable = bfModule->CreateTypeData(type, usedStringIdMap, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
if (needsVData)
vDataTypeSet.Add(type);
typeVariable = bfModule->CreateTypeData(type, createTypeDataCtx, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
if (typeVariable)
usedTypeDataVector.Add(type);
}
else if ((type->IsInterface()) && (typeInst->mSlotNum >= 0))
{
bfModule->CreateSlotOfs(typeInst);
}
usedTypeCount++;
type->mDirty = false;
if (needsTypeList)
@ -1573,13 +1624,13 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType);
Array<BfIRValue> stringList;
stringList.Resize(usedStringIdMap.size());
for (auto& kv : usedStringIdMap)
stringList.Resize(createTypeDataCtx.mUsedStringIdMap.size());
for (auto& kv : createTypeDataCtx.mUsedStringIdMap)
{
stringList[kv.mValue] = bfModule->mStringObjectPool[kv.mKey];
}
BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)usedStringIdMap.size());
BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)createTypeDataCtx.mUsedStringIdMap.size());
auto stringArray = bfModule->mBfIRBuilder->CreateConstAgg_Value(stringArrayType, stringList);
auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
@ -3994,10 +4045,10 @@ void BfCompiler::VisitSourceExteriorNodes()
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(usingDirective->mTypeRef))
{
mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity);
mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
}
else
mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity);
mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false);
@ -5608,12 +5659,19 @@ void BfCompiler::ClearBuildCache()
}
}
int BfCompiler::GetVDataPrefixDataCount()
{
return (mSystem->mPtrSize == 4) ? 2 : 1;
}
int BfCompiler::GetDynCastVDataCount()
{
int dynElements = 1 + mMaxInterfaceSlots;
return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
}
bool BfCompiler::IsAutocomplete()
{
return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL);
@ -7177,6 +7235,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mActionTypeDef = _GetRequiredType("System.Action");
mEnumTypeDef = _GetRequiredType("System.Enum");
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
mNoStaticCtorAttributeTypeDef = _GetRequiredType("System.NoStaticCtorAttribute");
mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute");
mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute");
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");

View file

@ -442,6 +442,7 @@ public:
BfTypeDef* mDisableChecksAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef;
BfTypeDef* mNoStaticCtorAttributeTypeDef;
BfTypeDef* mComptimeAttributeTypeDef;
BfTypeDef* mConstEvalAttributeTypeDef;
BfTypeDef* mNoExtensionAttributeTypeDef;
@ -501,6 +502,7 @@ public:
void MarkStringPool(BfIRConstHolder* constHolder, BfIRValue irValue);
void ClearUnusedStringPoolEntries();
void ClearBuildCache();
int GetVDataPrefixDataCount();
int GetDynCastVDataCount();
bool IsAutocomplete();
bool IsDataResolvePass();

View file

@ -420,55 +420,74 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
didWork = true;
}
for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++)
for (int populatePass = 0; populatePass < 2; populatePass++)
{
//BP_ZONE("PWL_PopulateType");
if (IsCancellingAndYield())
break;
auto workItemRef = mPopulateTypeWorkList[workIdx];
if (workItemRef == NULL)
for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++)
{
workIdx = mPopulateTypeWorkList.RemoveAt(workIdx);
continue;
}
//BP_ZONE("PWL_PopulateType");
if (IsCancellingAndYield())
break;
if (!mMidCompileWorkList.IsEmpty())
{
// Let these mid-compiles occur as soon as possible
break;
}
BfType* type = workItemRef->mType;
bool rebuildType = workItemRef->mRebuildType;
auto workItemRef = mPopulateTypeWorkList[workIdx];
if (workItemRef == NULL)
{
workIdx = mPopulateTypeWorkList.RemoveAt(workIdx);
continue;
}
if ((onlyReifiedTypes) && (!type->IsReified()))
{
continue;
}
BfType* type = workItemRef->mType;
bool rebuildType = workItemRef->mRebuildType;
auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL))
{
if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser))
if ((onlyReifiedTypes) && (!type->IsReified()))
{
continue;
}
// We want to resolve type aliases first, allowing possible mMidCompileWorkList entries
int wantPass = type->IsTypeAlias() ? 0 : 1;
if (populatePass != wantPass)
continue;
auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL))
{
if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser))
{
continue;
}
}
workIdx = mPopulateTypeWorkList.RemoveAt(workIdx);
if (rebuildType)
RebuildType(type);
BF_ASSERT(this == type->mContext);
auto useModule = type->GetModule();
if (useModule == NULL)
{
if (mCompiler->mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
useModule = mScratchModule;
else
useModule = mUnreifiedModule;
}
if (!type->IsDeleting())
useModule->PopulateType(type, BfPopulateType_Full);
mCompiler->mStats.mQueuedTypesProcessed++;
mCompiler->UpdateCompletion();
didWork = true;
}
}
workIdx = mPopulateTypeWorkList.RemoveAt(workIdx);
if (rebuildType)
RebuildType(type);
BF_ASSERT(this == type->mContext);
auto useModule = type->GetModule();
if (useModule == NULL)
{
if (mCompiler->mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
useModule = mScratchModule;
else
useModule = mUnreifiedModule;
}
if (!type->IsDeleting())
useModule->PopulateType(type, BfPopulateType_Full);
mCompiler->mStats.mQueuedTypesProcessed++;
mCompiler->UpdateCompletion();
didWork = true;
if ((!mMidCompileWorkList.IsEmpty()) && (didWork))
{
// Let the mid-compile occur ASAP
continue;
}
for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++)
@ -1984,6 +2003,7 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
}
else if (dependentTypeInst != NULL)
{
mGhostDependencies.Add(type);
// This keeps us from crashing from accessing deleted types on subsequent compiles
mFailTypes.TryAdd(dependentTypeInst, BfFailKind_Normal);
}
@ -2396,6 +2416,38 @@ void BfContext::UpdateRevisedTypes()
}
}
// Handle these "mid-compiles" now so we handle them as early-stage
BfParser* resolveParser = NULL;
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
resolveParser = mCompiler->mResolvePassData->mParsers[0];
for (int workIdx = 0; workIdx < (int)mMidCompileWorkList.size(); workIdx++)
{
auto workItemRef = mMidCompileWorkList[workIdx];
if (workItemRef == NULL)
{
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
continue;
}
BfType* type = workItemRef->mType;
String reason = workItemRef->mReason;
auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL))
{
if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser))
{
continue;
}
}
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
BfLogSysM("Handling prior-revision MidCompile on type %s in early-stage UpdateRevisedTypes\n", type);
RebuildDependentTypes(type->ToDependedType());
//RebuildDependentTypes_MidCompile(type->ToDependedType(), reason);
}
for (auto typeInst : defEmitParentCheckQueue)
{
if (typeInst->IsDeleting())
@ -2675,6 +2727,8 @@ void BfContext::UpdateRevisedTypes()
RebuildType(type);
}
}
BfLogSysM("BfContext::UpdateRevisedTypes done.\n");
}
void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst)
@ -3459,6 +3513,7 @@ void BfContext::Cleanup()
}
}
mTypeGraveyard.Clear();
mGhostDependencies.Clear();
if (!mDeletingModules.IsEmpty())
{

View file

@ -382,6 +382,7 @@ public:
BfModule* mScratchModule;
BfModule* mUnreifiedModule;
HashSet<String> mUsedModuleNames;
HashSet<BfType*> mGhostDependencies; // We couldn't properly rebuild our dependencies
Dictionary<BfProject*, BfModule*> mProjectModule;
Array<BfModule*> mModules;
Array<BfModule*> mDeletingModules;

View file

@ -5206,7 +5206,12 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
}
else if (fieldDef->mIsStatic)
{
mModule->CheckStaticAccess(typeInstance);
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
{
mModule->CheckStaticAccess(typeInstance);
}
auto retVal = mModule->ReferenceStaticField(fieldInstance);
bool isStaticCtor = (mModule->mCurMethodInstance != NULL) &&
(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
@ -6684,7 +6689,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
#endif
int vExtOfs = typeInst->GetOrigImplBaseVTableSize();
vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + mModule->mCompiler->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, mModule->mCompiler->GetVDataPrefixDataCount() + mModule->mCompiler->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, vExtOfs));
BfIRValue extendPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, vDataIdx);
vDataPtr = mModule->mBfIRBuilder->CreateLoad(extendPtr);
@ -7601,7 +7607,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
}
else
{
mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
if (prevBindResult.mPrevVal == NULL)
{
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
{
mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
}
}
if (target)
{
@ -8613,7 +8626,16 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
// the type has been initialized
auto targetTypeInst = target.mType->ToTypeInstance();
if (targetTypeInst != NULL)
mModule->CheckStaticAccess(targetTypeInst);
{
if (prevBindResult.mPrevVal == NULL)
{
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
{
mModule->CheckStaticAccess(targetTypeInst);
}
}
}
}
if (methodInstance->mReturnType == NULL)
@ -12535,7 +12557,7 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
{
auto targetValue = mModule->CreateValueFromExpression(dynCastExpr->mTarget);
auto targetType = mModule->ResolveTypeRefAllowUnboundGenerics(dynCastExpr->mTypeRef, BfPopulateType_Data, false);
auto targetType = mModule->ResolveTypeRefAllowUnboundGenerics(dynCastExpr->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_None, false);
auto autoComplete = GetAutoComplete();
if (autoComplete != NULL)
@ -18843,6 +18865,10 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
checkedKind = BfCheckedKind_Unchecked;
mModule->mAttributeState->mUsed = true;
}
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef))
{
mModule->mAttributeState->mUsed = true;
}
}
if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0))
@ -20967,7 +20993,7 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
}
elementValue = mModule->LoadOrAggregateValue(elementValue);
if (!elementValue.mValue.IsConst())
if (!elemPtrValue.IsConst())
mModule->mBfIRBuilder->CreateAlignedStore(elementValue.mValue, elemPtrValue, checkArrayType->mElementType->mAlign);
}
}

View file

@ -5391,6 +5391,8 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr);
int numElements = 1;
if (mSystem->mPtrSize == 4)
numElements++;
if ((outNumElements != NULL) || (globalVariablePtr == NULL))
{
@ -5432,11 +5434,6 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
if (outMangledName != NULL)
*outMangledName = classVDataName;
/*if (itr != mClassVDataRefs.end())
{
globalVariable = itr->second;
}*/
BfIRValue globalVariable;
if (globalVariablePtr != NULL)
{
@ -5937,7 +5934,21 @@ BfIRValue BfModule::CreateFieldData(BfFieldInstance* fieldInstance, int customAt
return result;
}
BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
void BfModule::CreateSlotOfs(BfTypeInstance* typeInstance)
{
int virtSlotIdx = -1;
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
// For interfaces we ONLY emit the slot num
StringT<512> slotVarName;
BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
auto intType = GetPrimitiveType(BfTypeCode_Int32);
auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
GetConstValue32(virtSlotIdx), slotVarName);
}
BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
{
if ((IsHotCompile()) && (!type->mDirty))
return BfIRValue();
@ -6004,13 +6015,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
{
CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true);
CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
}
typeTypeData = CreateClassVDataGlobal(typeDataSource);
ctx.mReflectTypeSet.Add(typeDataSource);
}
else
typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
{
//typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
typeTypeData = mBfIRBuilder->CreateConstNull();
}
BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
@ -6119,7 +6135,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
int virtSlotIdx = -1;
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount();
virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
int memberDataOffset = 0;
if (type->IsInterface())
memberDataOffset = virtSlotIdx * mSystem->mPtrSize;
@ -6316,18 +6332,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
String classVDataName;
if (typeInstance->mSlotNum >= 0)
{
// For interfaces we ONLY emit the slot num
StringT<512> slotVarName;
BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
auto intType = GetPrimitiveType(BfTypeCode_Int32);
auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
GetConstValue32(virtSlotIdx), slotVarName);
CreateSlotOfs(typeInstance);
}
else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData))
{
int dynCastDataElems = 0;
int numElements = 1;
int vDataOfs = 1; // The number of intptrs before the iface slot map
int vDataOfs = mCompiler->GetVDataPrefixDataCount(); // The number of intptrs before the iface slot map
numElements += mCompiler->mMaxInterfaceSlots;
if (!typeInstance->IsInterface())
{
@ -6342,7 +6353,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
classVDataVar = CreateClassVDataGlobal(typeInstance, &expectNumElements, &classVDataName);
}
vData.push_back(BfIRValue()); // Type*
for (int i = 0; i < mCompiler->GetVDataPrefixDataCount(); i++)
vData.push_back(BfIRValue()); // Type
SizedArray<BfIRValue, 1> extVTableData;
@ -6752,6 +6764,9 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
// Force override of GetHashCode so we use the pointer address as the hash code
for (auto& checkIFace : checkTypeInst->mInterfaces)
{
if (checkIFace.mStartVirtualIdx < 0)
continue;
for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
{
BfIRValue pushValue;
@ -6976,7 +6991,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
for (auto arg : attr->mCtorArgs)
{
auto argType = ctorMethodInstance->GetParamType(argIdx);
EncodeAttributeData(typeInstance, argType, arg, data, usedStringIdMap);
EncodeAttributeData(typeInstance, argType, arg, data, ctx.mUsedStringIdMap);
argIdx++;
}
@ -7494,7 +7509,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
}
else
{
vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
vDataIdx = mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile()))
{
auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner;
@ -7560,7 +7575,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
BfIRType interfaceDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectInterfaceDataType));
Array<bool> wantsIfaceMethod;
bool wantsIfaceMethods = false;
if (typeInstance->mInterfaces.IsEmpty())
if ((typeInstance->mInterfaces.IsEmpty()) || (!needsTypeData))
interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType);
else
{
@ -7802,7 +7817,22 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
{
BF_ASSERT(!classVDataName.IsEmpty());
vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
//vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
int unboxedTypeId = type->mTypeId;
if (type->IsBoxed())
unboxedTypeId = type->GetUnderlyingType()->mTypeId;
if (mSystem->mPtrSize == 4)
{
vData[0] = mBfIRBuilder->CreateIntToPtr(GetConstValue(type->mTypeId, intPtrType), voidPtrIRType);
vData[1] = mBfIRBuilder->CreateIntToPtr(GetConstValue(unboxedTypeId, intPtrType), voidPtrIRType);
}
else
{
vData[0] = mBfIRBuilder->CreateIntToPtr(GetConstValue(((int64)unboxedTypeId << 32) | type->mTypeId, intPtrType), voidPtrIRType);
}
auto classVDataConstDataType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData);
@ -10459,18 +10489,24 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
mBfIRBuilder->CreateObjectAccessCheck(typedVal.mValue, !IsOptimized());
}
void BfModule::EmitEnsureInstructionAt()
bool BfModule::WantsDebugHelpers()
{
if (mBfIRBuilder->mIgnoreWrites)
return;
return false;
if (mIsComptimeModule)
{
// Always add
}
else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
return;
return false;
return true;
}
void BfModule::EmitEnsureInstructionAt()
{
if (!WantsDebugHelpers())
return;
mBfIRBuilder->CreateEnsureInstructionAt();
}
@ -10549,7 +10585,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
targetType = GetWrappedStructType(targetType);
AddDependency(targetType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
int inheritanceIdOfs = mSystem->mPtrSize;
int inheritanceIdOfs = mSystem->mPtrSize * mCompiler->GetVDataPrefixDataCount();
vDataPtr = irb->CreateAdd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, inheritanceIdOfs));
vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType));
BfIRValue objInheritanceId = irb->CreateLoad(vDataPtr);
@ -11107,6 +11143,9 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
if (methodIdx >= typeInstance->mMethodInstanceGroups.mSize)
return BfModuleMethodInstance();
auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
BfMethodDef* methodDef = NULL;
@ -14003,7 +14042,7 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
return declareModule;
}
BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType, BfModule* referencingModule)
{
if (methodDef->mMethodType == BfMethodType_Init)
return BfModuleMethodInstance();
@ -14129,6 +14168,8 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
instModule->mReifyQueued = true;
}
BfLogSysM("REIFIED(GetMethodInstance QueueSpecializationRequest): %s %s MethodDef:%p RefModule:%s RefMethod:%p\n", TypeToString(typeInst).c_str(), methodDef->mName.c_str(), methodDef, mModuleName.c_str(), mCurMethodInstance);
// This ensures that the method will actually be created when it gets reified
BfMethodSpecializationRequest* specializationRequest = mContext->mMethodSpecializationWorkList.Alloc();
specializationRequest->mFromModule = typeInst->mModule;
@ -14154,7 +14195,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
// Not extern
// Create the instance in the proper module and then create a reference in this one
moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType);
moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType, this);
if (!moduleMethodInst)
return moduleMethodInst;
tryModuleMethodLookup = true;
@ -14549,8 +14590,18 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
/*if ((!mCompiler->mIsResolveOnly) && (!isReified))
BF_ASSERT(!methodInstance->mIsReified);*/
if ((!mCompiler->mIsResolveOnly) && (isReified))
{
auto refModule = referencingModule;
if (refModule == NULL)
refModule = this;
BfLogSysM("REIFIED(GetMethodInstance Reference): %s MethodDef:%p MethodInst:%p RefModule:%s RefMethod:%p\n", methodInstance->mMethodDef->mName.c_str(), methodDef, methodInstance, refModule->mModuleName.c_str(), refModule->mCurMethodInstance);
}
if (methodInstance->mIsReified != isReified)
{
BfLogSysM("GetMethodInstance %p Decl_AwaitingReference setting reified to %d\n", methodInstance, isReified);
}
if ((!isReified) &&
((methodInstance->mDeclModule == NULL) || (!methodInstance->mDeclModule->mIsModuleMutable)))
@ -14975,6 +15026,9 @@ BfIRValue BfModule::GetInterfaceSlotNum(BfTypeInstance* ifaceType)
globalValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External, value, slotVarName);
mInterfaceSlotRefs[ifaceType] = globalValue;
// Make sure we reify
PopulateType(ifaceType, BfPopulateType_Declaration);
AddDependency(ifaceType, mCurTypeInstance, BfDependencyMap::DependencyFlag_StaticValue);
}
return mBfIRBuilder->CreateAlignedLoad(globalValue/*, "slotOfs"*/, 4);
@ -20087,6 +20141,26 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if (mAwaitingInitFinish)
FinishInit();
if ((methodInstance->mIsReified) && (!mCompiler->mIsResolveOnly))
{
BfLogSysM("REIFIED(ProcessMethod): %s %p Module: %s\n", methodInstance->mMethodDef->mName.c_str(), methodInstance, mModuleName.c_str());
}
// Reify types that are actually used - they don't get reified during method declaration
if ((!mCompiler->mIsResolveOnly) && (mIsReified))
{
auto _CheckType = [&](BfType* type)
{
if (!type->IsReified())
PopulateType(type, BfPopulateType_Declaration);
};
_CheckType(methodInstance->mReturnType);
for (auto& param : methodInstance->mParams)
{
_CheckType(param.mResolvedType);
}
}
if (!methodInstance->mIsReified)
BF_ASSERT(!mIsReified);
@ -22047,8 +22121,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if ((retVal) && (!retVal.mType->IsVar()) && (expectingType != NULL))
{
mCurMethodState->mHadReturn = true;
retVal = LoadOrAggregateValue(retVal);
EmitReturn(retVal);
if (!mCurMethodState->mLeftBlockUncond)
{
retVal = LoadOrAggregateValue(retVal);
EmitReturn(retVal);
}
}
}
}
@ -23719,6 +23796,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
BfTypeState typeState(mCurTypeInstance);
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BfModule* resolveModule = mContext->mUnreifiedModule;
if (mCompiler->IsAutocomplete())
prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
@ -23963,7 +24042,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
mIgnoreErrors = false;
}
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_NoReify);
if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
&& (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
@ -24055,14 +24134,14 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{
BfTypeUtils::SplatIterate([&](BfType* checkType)
{
PopulateType(checkType, BfPopulateType_Data);
resolveModule->PopulateType(checkType, BfPopulateType_Data);
}, thisType);
}
}
else
{
thisType = mCurTypeInstance;
PopulateType(thisType, BfPopulateType_Declaration);
resolveModule->PopulateType(thisType, BfPopulateType_Declaration);
}
}
@ -24137,7 +24216,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
bool wasGenericParam = false;
if (resolvedParamType == NULL)
{
BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_NoReify);
if (paramDef->mParamKind == BfParamKind_ExplicitThis)
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut);
resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags);
@ -24388,7 +24467,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
}
int argIdx = 0;
PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
resolveModule->PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis))
{
int thisIdx = methodDef->mHasExplicitThis ? 0 : -1;
@ -24428,7 +24507,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
}
else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting(paramIdx)))
{
PopulateType(checkType, BfPopulateType_Data);
resolveModule->PopulateType(checkType, BfPopulateType_Data);
if (checkType->IsSplattable())
{
bool isSplat = false;
@ -24569,7 +24648,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{
auto paramType = methodInstance->GetParamType(paramIdx);
if (paramType->IsComposite())
PopulateType(paramType, BfPopulateType_Data);
resolveModule->PopulateType(paramType, BfPopulateType_Data);
if (!methodInstance->IsParamSkipped(paramIdx))
{
@ -24588,7 +24667,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if (methodInstance->mIsUnspecializedVariation)
return;
PopulateType(resolvedReturnType, BfPopulateType_Data);
resolveModule->PopulateType(resolvedReturnType, BfPopulateType_Data);
auto retLLVMType = mBfIRBuilder->MapType(resolvedReturnType);
if (resolvedReturnType->IsValuelessType())
retLLVMType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_None);
@ -26023,21 +26102,24 @@ void BfModule::DbgFinish()
if (mBfIRBuilder->DbgHasInfo())
{
bool needForceLinking = false;
for (auto& ownedType : mOwnedTypeInstances)
if (WantsDebugHelpers())
{
bool hasConfirmedReference = false;
for (auto& methodInstGroup : ownedType->mMethodInstanceGroups)
for (auto& ownedType : mOwnedTypeInstances)
{
if ((methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) &&
(!methodInstGroup.mDefault->mMethodDef->mIsStatic) && (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mAlwaysInline) &&
((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Referenced)) &&
(methodInstGroup.mHasEmittedReference))
bool hasConfirmedReference = false;
for (auto& methodInstGroup : ownedType->mMethodInstanceGroups)
{
hasConfirmedReference = true;
if ((methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) &&
(!methodInstGroup.mDefault->mMethodDef->mIsStatic) && (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mAlwaysInline) &&
((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Referenced)) &&
(methodInstGroup.mHasEmittedReference))
{
hasConfirmedReference = true;
}
}
if ((!hasConfirmedReference) || (ownedType->IsBoxed()))
needForceLinking = true;
}
if ((!hasConfirmedReference) || (ownedType->IsBoxed()))
needForceLinking = true;
}
if ((needForceLinking) && (mProject->mCodeGenOptions.mAsmKind == BfAsmKind_None))
@ -26153,7 +26235,7 @@ bool BfModule::Finish()
codeGenOptions.mWriteLLVMIR = mCompiler->mOptions.mWriteIR;
codeGenOptions.mWriteObj = mCompiler->mOptions.mGenerateObj;
codeGenOptions.mWriteBitcode = mCompiler->mOptions.mGenerateBitcode;
codeGenOptions.mVirtualMethodOfs = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
codeGenOptions.mVirtualMethodOfs = mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
codeGenOptions.mDynSlotOfs = mSystem->mPtrSize - mCompiler->GetDynCastVDataCount() * 4;
mCompiler->mStats.mIRBytes += mBfIRBuilder->mStream.GetSize();

View file

@ -158,6 +158,12 @@ enum BfLocalVarAssignKind : int8
BfLocalVarAssignKind_Unconditional = 2
};
struct BfCreateTypeDataContext
{
Dictionary<int, int> mUsedStringIdMap;
HashSet<BfTypeInstance*> mReflectTypeSet;
};
class BfLocalVariable
{
public:
@ -1740,6 +1746,7 @@ public:
bool HasExecutedOutput();
void SkipObjectAccessCheck(BfTypedValue typedVal);
void EmitObjectAccessCheck(BfTypedValue typedVal);
bool WantsDebugHelpers();
void EmitEnsureInstructionAt();
void EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* targetType, BfIRBlock trueBlock, BfIRBlock falseBlock, bool nullSucceeds = false);
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
@ -1966,7 +1973,7 @@ public:
bool ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef);
void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention);
BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0);
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true);
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, bool resolveGenericParam = true);
BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
@ -2062,7 +2069,7 @@ public:
void SetMethodDependency(BfMethodInstance* methodInstance);
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
BfModule* GetOrCreateMethodModule(BfMethodInstance* methodInstance);
BfModuleMethodInstance GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None, BfTypeInstance* foreignType = NULL);
BfModuleMethodInstance GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None, BfTypeInstance* foreignType = NULL, BfModule* referencingModule = NULL);
BfModuleMethodInstance GetMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
BfMethodInstance* GetOuterMethodInstance(BfMethodInstance* methodInstance); // Only useful for local methods
void SetupMethodIdHash(BfMethodInstance* methodInstance);
@ -2075,7 +2082,8 @@ public:
BfIRValue CreateTypeDataRef(BfType* type);
void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx);
BfIRValue CreateTypeData(BfType* type, Dictionary<int, int>& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
void CreateSlotOfs(BfTypeInstance* typeInstance);
BfIRValue CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
BfIRValue FixClassVData(BfIRValue value);
public:

View file

@ -410,7 +410,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors);
genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true;
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
mContext->mUnreifiedModule->PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
if (genericTypeInst->IsTypeAlias())
{
@ -418,7 +418,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
if ((underlyingType != NULL) && (underlyingType->IsGenericTypeInstance()))
{
auto underlyingGenericType = underlyingType->ToGenericTypeInstance();
PopulateType(underlyingType, BfPopulateType_Declaration);
mContext->mUnreifiedModule->PopulateType(underlyingType, BfPopulateType_Declaration);
bool result = ValidateGenericConstraints(typeRef, underlyingGenericType, ignoreErrors);
if (underlyingGenericType->mGenericTypeInfo->mHadValidateErrors)
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
@ -441,7 +441,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
{
startGenericParamIdx = typeDef->mOuterType->mGenericParamDefs.mSize + typeDef->mOuterType->mExternalConstraints.mSize;
auto outerType = GetOuterType(genericTypeInst);
PopulateType(outerType, BfPopulateType_Declaration);
mContext->mUnreifiedModule->PopulateType(outerType, BfPopulateType_Declaration);
if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mHadValidateErrors))
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
}
@ -802,6 +802,11 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
return;
}
if ((typeInst != NULL) && (typeInst->mIsReified) && (!mCompiler->mIsResolveOnly))
{
BfLogSysM("REIFIED(InitType): %s Type:%p FromModule:%s FromMethod:%p\n", TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, mModuleName.c_str(), prevMethodInstance.mPrevVal);
}
BfLogSysM("%p InitType: %s Type: %p TypeDef: %p Revision:%d\n", mContext, TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, (typeInst != NULL) ? typeInst->mTypeDef : NULL, mCompiler->mRevision);
// When we're autocomplete, we can't do the method processing so we have to add this type to the type work list
@ -1212,6 +1217,14 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
canFastReify = false;
}
if (!mCompiler->mIsResolveOnly)
{
for (auto ownedTypes : typeModule->mOwnedTypeInstances)
{
BfLogSysM("REIFIED(PopulateType-Reference): %s %p FromModule:%s FromMethod: %p\n", TypeToString(ownedTypes).c_str(), ownedTypes, mModuleName.c_str(), mCurMethodInstance);
}
}
if (canFastReify)
{
BfLogSysM("Setting reified type %p in module %p in PopulateType on module awaiting finish\n", resolvedTypeRef, typeModule);
@ -1292,7 +1305,17 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
BF_ASSERT((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) == 0);
if ((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) != 0)
{
if (mContext->mGhostDependencies.Contains(resolvedTypeRef))
{
// Not a nice state, but we should be able to recover
return;
}
InternalError("Attempting PopulateType on deleted type");
return;
}
bool isNew = resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined;
if (isNew)
@ -8268,7 +8291,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType
auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get();
typeDefTypeRef->mTypeDef = typeDef;
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType);
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType, resolveFlags);
if (resolvedtypeDefType == NULL)
{
mContext->mTypeDefTypeRefPool.GiveBack(typeDefTypeRef);
@ -11347,7 +11370,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
}
}
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType), populateType, resolveFlags);
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType, resolveFlags), populateType, resolveFlags);
}
}
}
@ -12635,7 +12658,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
}
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, bool resolveGenericParam)
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags, bool resolveGenericParam)
{
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
{
@ -12648,7 +12671,7 @@ BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, B
BfTypeVector typeVector;
for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++)
typeVector.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType);
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType, resolveFlags);
if ((result != NULL) && (genericTypeRef->mCommas.size() + 1 != genericTypeDef->mGenericParamDefs.size()))
{
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, result->ToTypeInstance());

View file

@ -1270,11 +1270,12 @@ bool BfMethodInstance::WasGenericParam(int paramIdx)
bool BfMethodInstance::IsParamSkipped(int paramIdx)
{
auto resolveModule = GetModule()->mContext->mUnreifiedModule;
if (paramIdx == -1)
return false;
BfType* paramType = GetParamType(paramIdx);
if ((paramType->CanBeValuelessType()) && (paramType->IsDataIncomplete()))
GetModule()->PopulateType(paramType, BfPopulateType_Data);
resolveModule->PopulateType(paramType, BfPopulateType_Data);
if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef()))
return true;
return false;
@ -1344,7 +1345,7 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
module->HadSlotCountDependency();
int vDataIdx = -1;
vDataIdx = 1 + module->mCompiler->mMaxInterfaceSlots;
vDataIdx = module->mCompiler->GetVDataPrefixDataCount() + module->mCompiler->mMaxInterfaceSlots;
vDataIdx += module->mCompiler->GetDynCastVDataCount();
if ((module->mCompiler->mOptions.mHasVDataExtender) && (module->mCompiler->IsHotCompile()))
{
@ -1375,7 +1376,9 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
{
module->PopulateType(mReturnType);
BfModule* resolveModule = module->mContext->mUnreifiedModule;
resolveModule->PopulateType(mReturnType);
BfTypeCode loweredReturnTypeCode = BfTypeCode_None;
BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;
@ -1459,7 +1462,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
else
{
if ((checkType->IsComposite()) && (checkType->IsIncomplete()))
module->PopulateType(checkType, BfPopulateType_Data);
resolveModule->PopulateType(checkType, BfPopulateType_Data);
if (checkType->IsMethodRef())
{
@ -1492,7 +1495,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
}
if (checkType->CanBeValuelessType())
module->PopulateType(checkType, BfPopulateType_Data);
resolveModule->PopulateType(checkType, BfPopulateType_Data);
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
continue;

View file

@ -6714,12 +6714,18 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
PopulateType(itrInterface, BfPopulateType_Full_Force);
getNextMethodInst = GetMethodByName(itrInterface, "GetNext");
}
BF_ASSERT(getNextMethodInst);
nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true);
if (nextResult.mType->IsGenericTypeInstance())
if (getNextMethodInst)
{
nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0];
nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true);
if (nextResult.mType->IsGenericTypeInstance())
{
nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0];
}
}
else
{
InternalError("Failed to find GetNext");
}
}
if (nextEmbeddedType == NULL)

View file

@ -3865,8 +3865,8 @@ addr_ce CeContext::GetReflectType(int typeId)
if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
ceModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
Dictionary<int, int> usedStringMap;
auto irData = ceModule->CreateTypeData(bfType, usedStringMap, true, true, true, false);
BfCreateTypeDataContext createTypeDataCtx;
auto irData = ceModule->CreateTypeData(bfType, createTypeDataCtx, true, true, true, false);
BeValue* beValue = NULL;
if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData))

View file

@ -833,6 +833,11 @@ bool DbgSubprogram::IsLambda()
return StringView(mName).Contains('$');
}
int DbgSubprogram::GetByteCount()
{
return (int)(mBlock.mHighPC - mBlock.mLowPC);
}
//////////////////////////////////////////////////////////////////////////
DbgSubprogram::~DbgSubprogram()
@ -5783,7 +5788,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
Array<PESectionHeader> sectionHeaders;
sectionHeaders.Resize(ntHdr.mFileHeader.mNumberOfSections);
mSectionRVAs.Resize(sectionHeaders.size() + 1);
mSectionHeaders.Resize(sectionHeaders.size() + 1);
Array<String> sectionNames;
sectionNames.Resize(ntHdr.mFileHeader.mNumberOfSections);
@ -5792,7 +5797,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
for (int sectNum = 0; sectNum < ntHdr.mFileHeader.mNumberOfSections; sectNum++)
{
mSectionRVAs[sectNum] = sectionHeaders[sectNum].mVirtualAddress;
mSectionHeaders[sectNum] = sectionHeaders[sectNum];
}
int tlsSection = -1;
@ -5827,6 +5832,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
}
DbgSection dwSection;
dwSection.mName = name;
dwSection.mIsExecutable = (sectHdr.mCharacteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
dwSection.mAddrStart = sectHdr.mVirtualAddress;
dwSection.mAddrLength = BF_MAX(sectHdr.mSizeOfRawData, sectHdr.mVirtualSize);
@ -6290,7 +6296,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
}
}
else
targetAddr = mSectionRVAs[symInfo->mSectionNum - 1] + symInfo->mValue;
targetAddr = mSectionHeaders[symInfo->mSectionNum - 1].mVirtualAddress + symInfo->mValue;
if (((targetAddr != 0) || (isTLS)) &&
(name[0] != '.'))

View file

@ -442,6 +442,7 @@ public:
bool IsGenericMethod();
bool ThisIsSplat();
bool IsLambda();
int GetByteCount();
DbgSubprogram* GetRootInlineParent()
{
@ -823,6 +824,7 @@ public:
addr_target mAddress;
int mCompileUnitId;
int mLength;
int mSection;
};
class DbgCompileUnit
@ -874,6 +876,7 @@ public:
class DbgSection
{
public:
String mName;
addr_target mAddrStart;
addr_target mAddrLength;
bool mWritingEnabled;
@ -1183,7 +1186,7 @@ public:
bool mIsDwarf64;
HashSet<DbgSrcFile*> mSrcFileDeferredRefs;
Array<addr_target> mSectionRVAs;
Array<PESectionHeader> mSectionHeaders;
SLIList<DbgSymbol*> mDeferredSymbols;
Beefy::OwnedVector<DbgDeferredHotResolve> mDeferredHotResolveList;
Array<DbgHotTargetSection*> mHotTargetSections;

View file

@ -1548,6 +1548,13 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE Debugger_GetModuleInfo(const char* moduleName)
{
String& outString = *gTLStrReturn.Get();
outString = gDebugger->GetModuleInfo(moduleName);
return outString.c_str();
}
BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
{
gDebugger->CancelSymSrv();

View file

@ -343,6 +343,7 @@ public:
virtual String FindLineCallAddresses(intptr address) = 0;
virtual String GetCurrentException() = 0;
virtual String GetModulesInfo() = 0;
virtual String GetModuleInfo(const StringImpl& moduleName) { return ""; }
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) = 0;
virtual void CancelSymSrv() = 0;
virtual bool HasPendingDebugLoads() = 0;

View file

@ -8,6 +8,8 @@ USING_NS_BF_DBG;
DbgHotScanner::DbgHotScanner(WinDebugger* debugger)
{
mDebugger = debugger;
mBfTypesInfoAddr = 0;
mDbgGCData = { 0 };
}
NS_BF_DBG_BEGIN
@ -255,20 +257,25 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
int* typeIdPtr = NULL;
if (mFoundClassVDataAddrs.TryAdd(classVDataAddr, NULL, &typeIdPtr))
{
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(classVDataAddr);
Fake_Type_Data typeData;
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
*typeIdPtr = typeData.mTypeId;
_MarkTypeUsed(typeData.mTypeId, elementSize);
if ((typeData.mTypeFlags & BfTypeFlags_Delegate) != 0)
if (mBfTypesInfoAddr > 0)
{
Fake_Delegate_Data* dlg = (Fake_Delegate_Data*)((uint8*)spanPtr + objectSize);
if (mFoundFuncPtrs.Add(dlg->mFuncPtr))
addr_target typeId = mDebugger->ReadMemory<int32>(classVDataAddr);
addr_target arrayAddr = mBfTypesInfoAddr + typeId * sizeof(addr_target);
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(arrayAddr);
Fake_Type_Data typeData;
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
*typeIdPtr = typeData.mTypeId;
_MarkTypeUsed(typeData.mTypeId, elementSize);
if ((typeData.mTypeFlags & BfTypeFlags_Delegate) != 0)
{
auto subProgram = mDebugger->mDebugTarget->FindSubProgram(dlg->mFuncPtr, DbgOnDemandKind_None);
if ((subProgram != NULL) && (subProgram->GetLanguage() == DbgLanguage_Beef))
AddSubProgram(subProgram, true, "D ");
Fake_Delegate_Data* dlg = (Fake_Delegate_Data*)((uint8*)spanPtr + objectSize);
if (mFoundFuncPtrs.Add(dlg->mFuncPtr))
{
auto subProgram = mDebugger->mDebugTarget->FindSubProgram(dlg->mFuncPtr, DbgOnDemandKind_None);
if ((subProgram != NULL) && (subProgram->GetLanguage() == DbgLanguage_Beef))
AddSubProgram(subProgram, true, "D ");
}
}
}
}
@ -358,6 +365,7 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
{
if ((module->mFilePath.Contains("Beef")) && (module->mFilePath.Contains("Dbg")))
{
module->ParseTypeData();
module->ParseSymbolData();
auto entry = module->mSymbolNameMap.Find("gGCDbgData");
if ((entry != NULL) && (entry->mValue != NULL))
@ -365,6 +373,44 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
}
}
auto module = mDebugger->mDebugTarget->mTargetBinary;
if (module->mBfTypesInfoAddr == 0)
{
module->mBfTypesInfoAddr = -1;
auto typeTypeEntry = module->FindType("System.Type", DbgLanguage_Beef);
if ((typeTypeEntry != NULL) && (typeTypeEntry->mValue != NULL))
{
auto typeType = typeTypeEntry->mValue;
module->mBfTypeType = typeType;
if (typeType->mNeedsGlobalsPopulated)
typeType->mCompileUnit->mDbgModule->PopulateTypeGlobals(typeType);
for (auto member : typeType->mMemberList)
{
if ((member->mIsStatic) && (member->mName != NULL) && (strcmp(member->mName, "sTypes") == 0) && (member->mLocationData != NULL))
{
DbgAddrType addrType;
module->mBfTypesInfoAddr = member->mCompileUnit->mDbgModule->EvaluateLocation(NULL, member->mLocationData, member->mLocationLen, NULL, &addrType);
}
}
if (module->mBfTypesInfoAddr <= 0)
{
auto entry = module->mSymbolNameMap.Find(
#ifdef BF_DBG_64
"?sTypes@Type@System@bf@@2PEAPEAV123@A"
#else
"?sTypes@Type@System@bf@@2PAPAV123@A"
#endif
);
if (entry)
module->mBfTypesInfoAddr = entry->mValue->mAddress;
}
}
}
mBfTypesInfoAddr = module->mBfTypesInfoAddr;
if (gcDbgDataAddr == 0)
return;

View file

@ -84,6 +84,7 @@ class DbgHotScanner
public:
WinDebugger* mDebugger;
DbgGCData mDbgGCData;
addr_target mBfTypesInfoAddr;
Beefy::Dictionary<addr_target, int> mFoundClassVDataAddrs;
Beefy::Dictionary<addr_target, int> mFoundRawAllocDataAddrs;
Beefy::Dictionary<addr_target, int> mFoundTypeAddrs;

View file

@ -8,6 +8,9 @@ StartupProject = "Tests"
[Configs.Debug.Win64]
IntermediateType = "ObjectAndIRCode"
[Configs.Debug.Win32]
IntermediateType = "ObjectAndIRCode"
[Configs.Test.Win64]
IntermediateType = "ObjectAndIRCode"
COptimizationLevel = "O2"

View file

@ -12872,6 +12872,210 @@ String WinDebugger::GetModulesInfo()
return str;
}
String WinDebugger::GetModuleInfo(const StringImpl& modulePath)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
String result;
for (auto dbgModule : mDebugTarget->mDbgModules)
{
if (modulePath.Equals(dbgModule->mFilePath, StringImpl::CompareKind_OrdinalIgnoreCase))
{
dbgModule->ParseGlobalsData();
dbgModule->PopulateStaticVariableMap();
auto coff = (COFF*)dbgModule;
coff->ParseCompileUnits();
int fileSize = 0;
//
{
FileStream fs;
fs.Open(coff->mFilePath, "rb");
fileSize = fs.GetSize();
}
result += StrFormat("Path: %s FileSize:%0.2fk MemoryImage:%0.2fk\n", coff->mFilePath.c_str(), fileSize / 1024.0f, coff->mImageSize / 1024.0f);
result += "Sections:\n";
for (auto& section : coff->mSections)
{
result += StrFormat("\t%s\t%0.2fk\n", section.mName.c_str(), (section.mAddrLength) / 1024.0f);
}
result += "\n";
result += "Compile Units:\n";
for (auto compileUnit : dbgModule->mCompileUnits)
{
coff->MapCompileUnitMethods(compileUnit);
result += StrFormat("\t%s PCRange:%0.2fk\n", compileUnit->mName.c_str(), (compileUnit->mHighPC - compileUnit->mLowPC) / 1024.0f);
}
result += "\n";
Array<CvModuleInfo*> moduleInfos;
for (auto moduleInfo : coff->mCvModuleInfo)
{
if (moduleInfo->mSectionContrib.mSize > 0)
moduleInfos.Add(moduleInfo);
}
moduleInfos.Sort([](CvModuleInfo* lhs, CvModuleInfo* rhs)
{
return lhs->mSectionContrib.mSize > rhs->mSectionContrib.mSize;
});
int totalContrib = 0;
result += "CV Module Info:\n";
for (auto moduleInfo : moduleInfos)
{
auto section = coff->mSections[moduleInfo->mSectionContrib.mSection - 1];
result += StrFormat("\t%s\t%s\t%0.2fk\t%@-%@\n", moduleInfo->mModuleName, section.mName.c_str(), (moduleInfo->mSectionContrib.mSize) / 1024.0f,
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset),
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset + moduleInfo->mSectionContrib.mSize));
totalContrib += moduleInfo->mSectionContrib.mSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
addr_target minAddr = 0;
Array<DbgCompileUnitContrib*> contribs;
for (auto itr = mDebugTarget->mContribMap.begin(); itr != mDebugTarget->mContribMap.end(); ++itr)
{
auto contrib = *itr;
if (contrib->mDbgModule != coff)
continue;
if (contrib->mAddress < minAddr)
continue;
minAddr = contrib->mAddress + contrib->mLength;
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
if (section->mSizeOfRawData <= 0)
continue;
contribs.Add(contrib);
}
contribs.Sort([](DbgCompileUnitContrib* lhs, DbgCompileUnitContrib* rhs)
{
return lhs->mLength > rhs->mLength;
});
totalContrib = 0;
result += "Contribs:\n";
for (auto contrib : contribs)
{
auto cvModule = coff->mCvModuleInfo[contrib->mCompileUnitId];
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
result += StrFormat("\t%s\t%s\t%0.2fk\t%@\n", cvModule->mModuleName, section->mName, (contrib->mLength)/1024.0f, contrib->mAddress);
totalContrib += contrib->mLength;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
struct SymbolEntry
{
const char* mName;
addr_target mAddress;
int mSize;
};
Array<SymbolEntry> symbolEntries;
for (auto symbol : mDebugTarget->mSymbolMap)
{
if (symbol->mDbgModule != coff)
continue;
if (!symbolEntries.IsEmpty())
{
auto lastSymbol = &symbolEntries.back();
if (lastSymbol->mSize == 0)
lastSymbol->mSize = symbol->mAddress - lastSymbol->mAddress;
}
SymbolEntry symbolEntry;
symbolEntry.mName = symbol->mName;
symbolEntry.mAddress = symbol->mAddress;
symbolEntry.mSize = 0;
symbolEntries.Add(symbolEntry);
}
if (!symbolEntries.IsEmpty())
{
auto lastSymbol = &symbolEntries.back();
for (auto contrib : contribs)
{
if ((lastSymbol->mAddress >= contrib->mAddress) && (lastSymbol->mAddress < contrib->mAddress + contrib->mLength))
{
lastSymbol->mSize = (contrib->mAddress + contrib->mLength) - lastSymbol->mAddress;
break;
}
}
}
symbolEntries.Sort([](const SymbolEntry& lhs, const SymbolEntry& rhs)
{
return lhs.mSize > rhs.mSize;
});
totalContrib = 0;
result += "Symbols:\n";
for (auto symbolEntry : symbolEntries)
{
result += StrFormat("\t%s\t%0.2fk\t%@\n", symbolEntry.mName, (symbolEntry.mSize) / 1024.0f, symbolEntry.mAddress);
totalContrib += symbolEntry.mSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
//////////////////////////////////////////////////////////////////////////
totalContrib = 0;
result += "Static Variables:\n";
for (auto& variable : coff->mStaticVariables)
{
result += StrFormat("\t%s\t%0.2fk\n", variable->mName, (variable->mType->GetByteCount()) / 1024.0f);
totalContrib += variable->mType->GetByteCount();
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
totalContrib = 0;
result += "Methods:\n";
Array<DbgSubprogram*> methods;
for (int typeIdx = 0; typeIdx < coff->mTypes.mSize; typeIdx++)
{
auto type = coff->mTypes[typeIdx];
type->PopulateType();
for (auto method : type->mMethodList)
methods.Add(method);
}
for (auto compileUnit : dbgModule->mCompileUnits)
{
for (auto method : compileUnit->mOrphanMethods)
methods.Add(method);
}
methods.Sort([](DbgSubprogram* lhs, DbgSubprogram* rhs)
{
return lhs->GetByteCount() > rhs->GetByteCount();
});
for (auto method : methods)
{
int methodSize = method->GetByteCount();
if (methodSize <= 0)
continue;
auto name = method->ToString();
result += StrFormat("\t%s\t%0.2fk\n", name.c_str(), methodSize / 1024.0f);
totalContrib += methodSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
}
}
return result;
}
void WinDebugger::CancelSymSrv()
{
AutoCrit autoCrit(mDebugManager->mCritSect);

View file

@ -656,6 +656,7 @@ public:
virtual String GetCurrentException() override;
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override;
virtual String GetModulesInfo() override;
virtual String GetModuleInfo(const StringImpl& moduleName) override;
virtual void CancelSymSrv() override;
virtual bool HasPendingDebugLoads() override;
virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;