Browse Source

Improved Win32 debugging

Brian Fiete 5 years ago
parent
commit
ad9075d1aa

+ 1 - 0
BeefySysLib/util/String.h

@@ -1210,3 +1210,4 @@ namespace std
 		}
 	};
 }
+

+ 10 - 0
IDE/src/IDEApp.bf

@@ -1816,6 +1816,9 @@ namespace IDE
 
         bool SaveWorkspace()
         {
+			if (mWorkspace.mNeedsCreate)
+				mWorkspace.mNeedsCreate = false;
+
 			if (!mWorkspace.IsSingleFileWorkspace)
 			{
 #if !CLI
@@ -9376,6 +9379,11 @@ namespace IDE
 
 		public void AutoGenerateStartupCode(Project project)
 		{
+			// We have to save this to ensure any new project is actually created. Maybe overkill,
+			// but best to stay conservative since this path won't be heavily tested
+			if (!SaveAll())
+				return;
+
 			String namespaceName = scope .();
 			String className = scope .();
 			String startupStr = project.mBeefGlobalOptions.mStartupObject;
@@ -9411,6 +9419,8 @@ namespace IDE
 
 			String srcPath = scope .();
 			project.mRootFolder.GetFullImportPath(srcPath);
+			Directory.CreateDirectory(srcPath).IgnoreError();
+
 			srcPath.Append(Path.DirectorySeparatorChar);
 			srcPath.Append("Program.bf");
 

+ 1 - 0
IDEHelper/Backend/BeMCContext.cpp

@@ -14742,6 +14742,7 @@ void BeMCContext::Generate(BeFunction* function)
 	//mDbgPreferredRegs[8] = X64Reg_RAX;
 	mDebugging = function->mName ==
 	//"?TestPrimitives@Nullable@Tests@bf@@SAXXZ"
+
 		"?Hey@Blurg@bf@@SAHXZ";
 	//"?Main@Program@bf@@CAHPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z";
 

+ 13 - 3
IDEHelper/COFF.cpp

@@ -6113,9 +6113,19 @@ addr_target COFF::EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* loc
 				else
 					result = stackFrame->mRegisters.mIntRegsArray[X64Reg_RBP] + defRangeFPRel.offFramePointer;
 #else				
-				if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_ESP)
-					//result = stackFrame->mRegisters.mIntRegsArray[X86Reg_ESP] + BF_ALIGN(dwSubprogram->mFrameBaseLen, 16) + defRangeFPRel.offFramePointer;
-					result = stackFrame->mRegisters.mIntRegsArray[X86Reg_ESP] + dwSubprogram->mFrameBaseLen + defRangeFPRel.offFramePointer;
+				if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_VFRAME)					
+				{					
+					if (defRangeFPRel.offFramePointer > 0)
+					{
+						// Note that a positive offFramePointer always refers to params, and param fp reg is always EBP-relative.
+						// If this is not true in some cases then we need to actually pass in knowledge of whether is loc data is 
+						//  from a param or not, and we have to store the param fp reg just like the local fp reg (mLocalBaseReg)
+						result = stackFrame->mRegisters.mIntRegsArray[X86Reg_EBP] + defRangeFPRel.offFramePointer;
+					}
+					else
+						//result = stackFrame->mRegisters.mIntRegsArray[X86Reg_EBP] + defRangeFPRel.offFramePointer - 4;
+						result = ((stackFrame->mRegisters.mIntRegsArray[X86Reg_ESP] + dwSubprogram->mFrameBaseLen) & ~7) + defRangeFPRel.offFramePointer;
+				}
 				else if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_EBX)
 					result = stackFrame->mRegisters.mIntRegsArray[X86Reg_EBX] + defRangeFPRel.offFramePointer;
 				else

+ 1 - 1
IDEHelper/Compiler/BfContext.cpp

@@ -780,7 +780,7 @@ void BfContext::ValidateDependencies()
 	while (itr != mResolvedTypes.end())
 	{
 		auto type = itr.mCurEntry->mValue;		
-		if (type->IsGenericTypeInstance())
+		if ((type->IsGenericTypeInstance()) && (type->mDefineState > BfTypeDefineState_Undefined))
 		{
 			// We can't contain deleted generic arguments without being deleted ourselves
 			BfGenericTypeInstance* genericType = (BfGenericTypeInstance*)type;

+ 0 - 1
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -18197,4 +18197,3 @@ void BfExprEvaluator::Visit(BfBinaryOperatorExpression* binOpExpr)
 
 	PerformBinaryOperation(binOpExpr->mLeft, binOpExpr->mRight, binOpExpr->mOp, binOpExpr->mOpToken, BfBinOpFlag_None);
 }
-//

+ 54 - 30
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -995,6 +995,7 @@ BfIRBuilder::BfIRBuilder(BfModule* module) : BfIRConstHolder(module)
 	mActiveFunctionHasBody = false;
 	mHasStarted = false;	
 	mCmdCount = 0;
+	mIsBeefBackend = false;
 }
 
 bool BfIRBuilder::HasExports()
@@ -1374,7 +1375,9 @@ void BfIRBuilder::Start(const StringImpl& moduleName, int ptrSize, bool isOptimi
 }
 
 void BfIRBuilder::SetBackend(bool isBeefBackend)
-{		
+{	
+	mIsBeefBackend = isBeefBackend;
+
 	BF_ASSERT(mIRCodeGen == NULL);
 	if (mDbgVerifyCodeGen)
 	{
@@ -1881,13 +1884,14 @@ public:
 void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDefine)
 {		
 	bool wantDIData = DbgHasInfo() && (!type->IsUnspecializedType());
-	
-	// Types that don't have a proper 'defining module' need to be defined in every module they are used
-	bool isDefiningModule = (type->GetModule() == mModule) || (type->IsFunction());
-	bool wantsForwardDecl = !isDefiningModule && !forceDefine;
-
+			
+	// Types that don't have a proper 'defining module' need to be defined in every module they are used	
+	bool wantsDIForwardDecl = (type->GetModule() != mModule) && (!type->IsFunction());
+	// Forward declarations of valuetypes doesn't work in LLVM backend for Win32.....
+//  	if ((!mIsBeefBackend) && (type->IsValueType()))
+//  		wantsDIForwardDecl = false;
 	if (mModule->mExtensionCount != 0)
-		wantsForwardDecl = true;
+		wantsDIForwardDecl = true;
 
 	bool isPrimEnum = (type->IsEnum()) && (type->IsTypedPrimitive());
 
@@ -2144,7 +2148,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDefine)
 			else
 				curDIScope = CreateNamespaceScope(checkType, fileDIScope);
 			String typeName = GetDebugTypeName(typeInstance, false);
-			if (wantsForwardDecl)
+			if (wantsDIForwardDecl)
 			{					
 				if (type->IsInterface())
 				{
@@ -2169,10 +2173,14 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDefine)
 				int flags = 0;
 				diForwardDecl = DbgCreateReplaceableCompositeType(llvm::dwarf::DW_TAG_structure_type,
 					typeName, curDIScope, fileDIScope, 0, (int64)BF_ALIGN(typeInstance->mInstSize, typeInstance->mInstAlign) * 8, (int64)typeInstance->mInstAlign * 8, flags);
+				
+				mDITemporaryTypes.push_back(typeInstance);
 
-					
-
-				mDITemporaryTypes.push_back(typeInstance);				
+				if (!type->IsUnspecializedType())
+				{
+					BF_ASSERT(!mDeferredDbgTypeDefs.Contains(type));
+					mDeferredDbgTypeDefs.Add(type);
+				}
 			}			
 
 			DbgSetInstType(type, diForwardDecl);			
@@ -2257,8 +2265,10 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 
 	bool isGlobalContainer = typeDef->IsGlobalsContainer();
 	
-	bool isDefiningModule = true;
+	bool isDefiningModule = ((type->GetModule() == mModule) || (type->IsFunction()));
 	auto diForwardDecl = DbgGetTypeInst(typeInstance);
+
+	//BF_ASSERT(WantsDbgDefinition(type));
 	
 	llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;
 
@@ -2330,7 +2340,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 		{
 			if (fieldDef->mIsConst)
 			{
-				if (wantDIData)
+				if (isDefiningModule)
 				{
 					if ((isPayloadEnum) && (fieldDef->IsEnumCaseEntry()))
 					{
@@ -2464,7 +2474,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 			}
 			else if (fieldDef->mIsStatic)
 			{
-				if (wantDIData)
+				if (isDefiningModule)
 				{
 					int flags = 0;
 					auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldDef->mName, fileDIScope, 0,
@@ -2523,8 +2533,11 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 	if (type->IsBoxed())
 		wantsMethods = false; 
 
+	if (!isDefiningModule)
+		wantsMethods = false;
+
 	if (wantsMethods)
-	{			
+	{
 		for (int methodIdx = 0; methodIdx < (int)typeInstance->mMethodInstanceGroups.size(); methodIdx++)
 		{
 			auto& methodGroup = typeInstance->mMethodInstanceGroups[methodIdx];
@@ -2747,6 +2760,18 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 	}	
 }
 
+bool BfIRBuilder::WantsDbgDefinition(BfType* type)
+{
+	if ((type->GetModule() == mModule) || (type->IsFunction()))
+		return true;
+
+	// Forward declarations of valuetypes doesn't work in LLVM backend
+// 	if ((!mIsBeefBackend) && (type->IsValueType()))
+// 		return true;
+
+	return false;
+}
+
 void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
 {	
 	// This PopulateType is generally NOT needed, but here is a scenario in which it is:
@@ -2757,10 +2782,10 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
 	if (type->IsDataIncomplete())
 		mModule->PopulateType(type, BfPopulateType_Data);	
 
-	bool isDefiningModule = (type->GetModule() == mModule) || (type->IsFunction());
+	bool isDefiningModule = ((type->GetModule() == mModule) || (type->IsFunction()));
 	if (mModule->mExtensionCount != 0)
 		isDefiningModule = false;
-	
+ 	
 // 	if (mModule->mModuleName == "vdata")
 // 		isDefiningModule = true;
 
@@ -2771,8 +2796,7 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
 	{
 		DbgSetTypeSize(DbgGetType(type), BF_ALIGN(type->mSize, type->mAlign) * 8, type->mAlign * 8);
 	}
-
-	bool wantsForwardDecl = !isDefiningModule && !forceDefine;
+	
 	bool isPrimEnum = (type->IsEnum()) && (type->IsTypedPrimitive());
 				
 	auto typeInstance = type->ToTypeInstance();
@@ -2780,13 +2804,7 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
 		return;		
 
 	auto typeDef = typeInstance->mTypeDef;	
-	if (DbgHasInfo() && (!type->IsUnspecializedType()) && (!wantsForwardDecl))
-	{
-		BF_ASSERT(!mDeferredDbgTypeDefs.Contains(type));
-		mDeferredDbgTypeDefs.Add(type);
-	}
-
-	
+		
 #ifdef BFIR_RENTRY_CHECK
 	ReEntryCheck reEntryCheck(&mDefReentrySet, type);
 #endif
@@ -3007,12 +3025,17 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
 
 void BfIRBuilder::ReplaceDITemporaryTypes()
 {
-	for (auto typeInstance : mDITemporaryTypes)
+	//for (auto typeInstance : mDITemporaryTypes)
+	for (int i = 0; i < (int)mDITemporaryTypes.size(); i++)
 	{
-		if (mTypeMap[typeInstance] == BfIRPopulateType_Full)
+		auto typeInstance = mDITemporaryTypes[i];
+		auto populateType = mTypeMap[typeInstance];
+		if (populateType == BfIRPopulateType_Full)
 			continue;
 
+		mTypeMap[typeInstance] = BfIRPopulateType_Eventually_Full;
 		CreateTypeDefinition(typeInstance, false);
+		mTypeMap[typeInstance] = BfIRPopulateType_Full;
 	}
 	mDITemporaryTypes.Clear();
 }
@@ -4510,8 +4533,9 @@ void BfIRBuilder::DbgFinalize()
 {	
 	while ((!mDeferredDbgTypeDefs.IsEmpty()) || (!mDITemporaryTypes.IsEmpty()))
 	{		
-		for (auto deferredType : mDeferredDbgTypeDefs)
-			CreateDbgTypeDefinition(deferredType);
+		//for (auto deferredType : mDeferredDbgTypeDefs)
+		for (int i = 0; i < (int)mDeferredDbgTypeDefs.size(); i++)
+			CreateDbgTypeDefinition(mDeferredDbgTypeDefs[i]);
 		mDeferredDbgTypeDefs.Clear();
 
 		ReplaceDITemporaryTypes();

+ 2 - 0
IDEHelper/Compiler/BfIRBuilder.h

@@ -849,6 +849,7 @@ public:
 	bool mDbgVerifyCodeGen;
 	int mCurFakeId;
 	bool mHasGlobalDefs;
+	bool mIsBeefBackend;
 	int mNumFunctionsWithBodies;	
 	int mBlockCount;
 	bool mHasStarted;		
@@ -938,6 +939,7 @@ public:
 	BfIRMDNode CreateNamespaceScope(BfType* type, BfIRMDNode fileDIScope);
 	String GetDebugTypeName(BfTypeInstance* typeInstance, bool includeOuterTypeName);
 	void CreateDbgTypeDefinition(BfType* type);
+	bool WantsDbgDefinition(BfType * type);
 	void CreateTypeDeclaration(BfType* type, bool forceDefine);
 	void CreateTypeDefinition(BfType* type, bool forceDefine);	
 	void ReplaceDITemporaryTypes();

+ 1 - 1
IDEHelper/DbgModule.cpp

@@ -7265,4 +7265,4 @@ DbgType* DbgModule::GetSizedArrayType(DbgType * elementType, int count)
 		*sizedArrayTypePtr = sizedArrayType;
 	}
 	return *sizedArrayTypePtr;
-}
+}

+ 1 - 1
IDEHelper/DbgModule.h

@@ -351,7 +351,7 @@ public:
 	enum LocalBaseRegKind : uint8
 	{
 		LocalBaseRegKind_None,
-		LocalBaseRegKind_ESP,
+		LocalBaseRegKind_VFRAME,
 		LocalBaseRegKind_EBP,
 		LocalBaseRegKind_EBX
 	};

+ 2 - 2
IDEHelper/DebugTarget.cpp

@@ -2150,8 +2150,8 @@ int DebugTarget::GetFrameBaseRegister(DbgSubprogram* dwSubprogram)
 	}
 
 #ifdef BF_DBG_32 
-	if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_ESP)
-		return X86Reg_ESP;
+	if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_VFRAME)
+		return X86Reg_EBP;
 	else if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_EBX)
 		return X86Reg_EBX;
 	return X86Reg_EBP;