From 25f44ae133e9606ba0dc4da94efe85e87aa7c022 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 4 Sep 2020 08:09:04 -0700 Subject: [PATCH] Added System.Compiler compile-time values --- BeefLibs/corlib/src/Compiler.bf | 29 ++++++ BeefLibs/corlib/src/Diagnostics/Debug.bf | 21 ++--- BeefLibs/corlib/src/Runtime.bf | 23 +++-- IDEHelper/Compiler/BfCompiler.cpp | 2 +- IDEHelper/Compiler/BfConstResolver.cpp | 26 +++--- IDEHelper/Compiler/BfConstResolver.h | 3 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 110 +++++++++++++++++++++-- IDEHelper/Compiler/BfIRBuilder.cpp | 35 +++++--- IDEHelper/Compiler/BfMangler.cpp | 31 ++++++- IDEHelper/Compiler/BfModule.cpp | 88 ++++++++++++++---- IDEHelper/Compiler/BfModule.h | 1 + 11 files changed, 294 insertions(+), 75 deletions(-) create mode 100644 BeefLibs/corlib/src/Compiler.bf diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf new file mode 100644 index 00000000..4d921117 --- /dev/null +++ b/BeefLibs/corlib/src/Compiler.bf @@ -0,0 +1,29 @@ +namespace System +{ + static class Compiler + { + [LinkName("#CallerLineNum")] + public static extern int CallerLineNum; + + [LinkName("#CallerFilePath")] + public static extern String CallerFilePath; + + [LinkName("#CallerFileName")] + public static extern String CallerFileName; + + [LinkName("#CallerFileDir")] + public static extern String CallerFileDir; + + [LinkName("#CallerMemberName")] + public static extern String CallerMemberName; + + [LinkName("#CallerProject")] + public static extern String CallerProject; + + [LinkName("#CallerExpression")] + public static extern String[Int32.MaxValue] CallerExpression; + + [LinkName("#TimeLocal")] + public static extern String TimeLocal; + } +} diff --git a/BeefLibs/corlib/src/Diagnostics/Debug.bf b/BeefLibs/corlib/src/Diagnostics/Debug.bf index 43802e78..aa204426 100644 --- a/BeefLibs/corlib/src/Diagnostics/Debug.bf +++ b/BeefLibs/corlib/src/Diagnostics/Debug.bf @@ -5,27 +5,22 @@ namespace System.Diagnostics #if !DEBUG [SkipCall] #endif - public static void Assert(bool condition) - { - if (!condition) - Internal.FatalError("Assert failed", 1); - } - -#if !DEBUG - [SkipCall] -#endif - public static void Assert(bool condition, String error) + public static void Assert(bool condition, String error = Compiler.CallerExpression[0], String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) { if (!condition) - Internal.FatalError(error, 1); + { + String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath); + Internal.FatalError(failStr, 1); + } } #if !DEBUG [SkipCall] #endif - public static void FatalError(String msg = "Fatal error encountered") + public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) { - Internal.FatalError(msg, 1); + String failStr = scope .()..AppendF("{} at line {} in {}", msg, line, filePath); + Internal.FatalError(failStr, 1); } #if !DEBUG diff --git a/BeefLibs/corlib/src/Runtime.bf b/BeefLibs/corlib/src/Runtime.bf index d5cd3b77..778a36cf 100644 --- a/BeefLibs/corlib/src/Runtime.bf +++ b/BeefLibs/corlib/src/Runtime.bf @@ -306,27 +306,26 @@ namespace System } [NoReturn] - public static void FatalError(String msg = "Fatal error encountered") + public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) { - Internal.FatalError(msg, 1); + String failStr = scope .()..AppendF("{} at line {} in {}", msg, line, filePath); + Internal.FatalError(failStr, 1); } [NoReturn] - public static void NotImplemented() + public static void NotImplemented(String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) { - Internal.FatalError("Not Implemented", 1); + String failStr = scope .()..AppendF("Not Implemented at line {} in {}", line, filePath); + Internal.FatalError(failStr, 1); } - public static void Assert(bool condition) + public static void Assert(bool condition, String error = Compiler.CallerExpression[0], String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) { if (!condition) - Internal.FatalError("Assert failed", 1); - } - - public static void Assert(bool condition, String error) - { - if (!condition) - Internal.FatalError(error, 1); + { + String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath); + Internal.FatalError(failStr, 1); + } } } } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index acfa2ac2..21de1e78 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -4129,7 +4129,7 @@ void BfCompiler::ProcessAutocompleteTempType() if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL)) { - auto customAttrs = module->GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Field); + auto customAttrs = module->GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field); delete customAttrs; } diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index b415dc1b..bc0c8df8 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -89,9 +89,8 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo if (wantType != NULL) mExpectingType = wantType; VisitChildNoRef(expr); + mResult = GetResult(); - if (mResult) - mResult = mModule->LoadValue(mResult); if ((mResult) && (wantType != NULL)) { auto typeInst = mResult.mType->ToTypeInstance(); @@ -113,17 +112,18 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo } else { - int stringId = mModule->GetStringPoolIdx(mResult.mValue); - BF_ASSERT(stringId >= 0); - - if ((flags & BfConstResolveFlag_RemapFromStringId) != 0) + int stringId = mModule->GetStringPoolIdx(mResult.mValue); + if (stringId != -1) { - ignoreWrites.Restore(); - mModule->mBfIRBuilder->PopulateType(mResult.mType); - return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType); - } + if ((flags & BfConstResolveFlag_RemapFromStringId) != 0) + { + ignoreWrites.Restore(); + mModule->mBfIRBuilder->PopulateType(mResult.mType); + return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType); + } - return BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId), toType); + return BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId), toType); + } } } } @@ -180,10 +180,10 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo if (isConst) { auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue); - if (constant->mConstType == BfConstType_GlobalVar) + if ((constant->mConstType == BfConstType_GlobalVar) && ((mBfEvalExprFlags & BfConstResolveFlag_AllowGlobalVariable) != 0)) isConst = false; } - + if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0)) { mModule->Fail("Expression does not evaluate to a constant value", expr); diff --git a/IDEHelper/Compiler/BfConstResolver.h b/IDEHelper/Compiler/BfConstResolver.h index c7a8be32..19a6b0bf 100644 --- a/IDEHelper/Compiler/BfConstResolver.h +++ b/IDEHelper/Compiler/BfConstResolver.h @@ -16,7 +16,8 @@ enum BfConstResolveFlags BfConstResolveFlag_NoCast = 2, BfConstResolveFlag_AllowSoftFail = 4, BfConstResolveFlag_RemapFromStringId = 8, - BfConstResolveFlag_ArrayInitSize = 0x10 + BfConstResolveFlag_ArrayInitSize = 0x10, + BfConstResolveFlag_AllowGlobalVariable = 0x20, }; class BfConstResolver : public BfExprEvaluator diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index e70ee8de..12940761 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -21,6 +21,7 @@ #include "BfFixits.h" #pragma warning(pop) +#pragma warning(disable:4996) #include "BeefySysLib/util/AllocDebug.h" @@ -5840,6 +5841,88 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu argValue = mModule->GetDefaultTypedValue(wantType, false, BfDefaultValueKind_Addr); } } + else if (foreignConst->mConstType == BfConstType_GlobalVar) + { + auto globalVar = (BfGlobalVar*)foreignConst; + if (globalVar->mName[0] == '#') + { + if (strcmp(globalVar->mName, "#CallerLineNum") == 0) + { + argValue = BfTypedValue(mModule->GetConstValue(mModule->mCurFilePosition.mCurLine + 1), mModule->GetPrimitiveType(BfTypeCode_Int32)); + } + else if (strcmp(globalVar->mName, "#CallerFilePath") == 0) + { + String filePath = ""; + if (mModule->mCurFilePosition.mFileInstance != NULL) + filePath = mModule->mCurFilePosition.mFileInstance->mParser->mFileName; + argValue = BfTypedValue(mModule->GetStringObjectValue(filePath), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else if (strcmp(globalVar->mName, "#CallerFileName") == 0) + { + String filePath = ""; + if (mModule->mCurFilePosition.mFileInstance != NULL) + filePath = mModule->mCurFilePosition.mFileInstance->mParser->mFileName; + argValue = BfTypedValue(mModule->GetStringObjectValue(GetFileName(filePath)), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else if (strcmp(globalVar->mName, "#CallerFileDir") == 0) + { + String filePath = ""; + if (mModule->mCurFilePosition.mFileInstance != NULL) + filePath = mModule->mCurFilePosition.mFileInstance->mParser->mFileName; + argValue = BfTypedValue(mModule->GetStringObjectValue(GetFileDir(filePath)), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else if (strcmp(globalVar->mName, "#CallerMemberName") == 0) + { + String memberName = ""; + if (mModule->mCurMethodInstance != NULL) + memberName = mModule->MethodToString(mModule->mCurMethodInstance); + argValue = BfTypedValue(mModule->GetStringObjectValue(memberName), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else if (strcmp(globalVar->mName, "#CallerProject") == 0) + { + String projectName = ""; + if (mModule->mCurMethodInstance != NULL) + projectName = mModule->mCurMethodInstance->mMethodDef->mDeclaringType->mProject->mName; + argValue = BfTypedValue(mModule->GetStringObjectValue(projectName), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else + { + argValue = mModule->GetCompilerFieldValue(globalVar->mName); + } + } + } + else if (foreignConst->mConstType == BfConstType_GEP32_2) + { + auto constGep32_2 = (BfConstantGEP32_2*)foreignConst; + auto gepTarget = methodInstance->GetOwner()->mConstHolder->GetConstantById(constGep32_2->mTarget); + if (gepTarget->mConstType == BfConstType_GlobalVar) + { + auto globalVar = (BfGlobalVar*)gepTarget; + if (globalVar->mName[0] == '#') + { + if (strcmp(globalVar->mName, "#CallerExpression") == 0) + { + int exprIdx = constGep32_2->mIdx1; + if ((exprIdx >= 0) && (exprIdx <= (int)argValues.size())) + { + argValue = BfTypedValue(mModule->GetStringObjectValue(argValues[exprIdx].mExpression->ToString()), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + else + { + mModule->Fail("CallerExpression index out of bounds", targetSrc); + argValue = BfTypedValue(mModule->GetStringObjectValue(""), + mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef)); + } + } + } + } + } if (!argValue) { @@ -17516,9 +17599,12 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr) { if (target.mType->IsSizeAligned()) { - auto ptrType = mModule->CreatePointerType(underlyingType); - auto ptrValue = mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)); - auto gepResult = mModule->mBfIRBuilder->CreateInBoundsGEP(ptrValue, indexArgument.mValue); +// auto ptrType = mModule->CreatePointerType(underlyingType); +// auto ptrValue = mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)); +// auto gepResult = mModule->mBfIRBuilder->CreateInBoundsGEP(ptrValue, indexArgument.mValue); +// mResult = BfTypedValue(gepResult, underlyingType, target.IsReadOnly() ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr); + + auto gepResult = mModule->mBfIRBuilder->CreateInBoundsGEP(target.mValue, mModule->GetConstValue(0), indexArgument.mValue); mResult = BfTypedValue(gepResult, underlyingType, target.IsReadOnly() ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr); } else @@ -18942,13 +19028,19 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod skipOpOverload = true; else if (BfBinOpEqualityCheck(binaryOp)) { - auto leftConstant = mModule->mBfIRBuilder->GetConstant(leftValue.mValue); - auto rightConstant = mModule->mBfIRBuilder->GetConstant(rightValue.mValue); + if (!leftValue.IsAddr()) + { + auto leftConstant = mModule->mBfIRBuilder->GetConstant(leftValue.mValue); + if ((leftConstant != NULL) && (leftConstant->IsNull())) + skipOpOverload = true; + } - if ((leftConstant != NULL) && (leftConstant->IsNull())) - skipOpOverload = true; - if ((rightConstant != NULL) && (rightConstant->IsNull())) - skipOpOverload = true; + if (!rightValue.IsAddr()) + { + auto rightConstant = mModule->mBfIRBuilder->GetConstant(rightValue.mValue); + if ((rightConstant != NULL) && (rightConstant->IsNull())) + skipOpOverload = true; + } } if (!skipOpOverload) diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 206b38a7..ef51580e 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -2675,9 +2675,12 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type) StringT<128> staticVarName; BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); - String fieldName = DbgGetStaticFieldName(fieldInstance); - DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, - constDIType, false, staticValue, memberType); + if (!staticVarName.StartsWith("#")) + { + String fieldName = DbgGetStaticFieldName(fieldInstance); + DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, + constDIType, false, staticValue, memberType); + } } else if (resolvedFieldType->IsValuelessType()) { @@ -2788,14 +2791,17 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type) resolvedFieldDIType, flags, BfIRValue()); diFieldTypes.push_back(memberType); - auto staticValue = mModule->ReferenceStaticField(fieldInstance); - if (staticValue.mValue) + StringT<128> staticVarName; + BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); + if (!staticVarName.StartsWith('#')) { - StringT<128> staticVarName; - BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); - String fieldName = DbgGetStaticFieldName(fieldInstance); - DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, - resolvedFieldDIType, false, staticValue.mValue, memberType); + auto staticValue = mModule->ReferenceStaticField(fieldInstance); + if (staticValue.mValue) + { + String fieldName = DbgGetStaticFieldName(fieldInstance); + DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, + resolvedFieldDIType, false, staticValue.mValue, memberType); + } } } } @@ -4101,6 +4107,15 @@ BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, BfIRValue idx0) BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, BfIRValue idx0, BfIRValue idx1) { + if ((val.IsConst()) && (idx0.IsConst()) && (idx1.IsConst())) + { + auto idx0Constant = GetConstant(idx0); + auto idx1Constant = GetConstant(idx1); + + if ((IsInt(idx0Constant->mTypeCode)) && (IsInt(idx1Constant->mTypeCode))) + return CreateInBoundsGEP(val, idx0Constant->mInt32, idx1Constant->mInt32); + } + BfIRValue retVal = WriteCmd(BfIRCmd_InBoundsGEP2, val, idx0, idx1); NEW_CMD_INSERTED_IRVALUE; return retVal; diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index f0363f04..12f8f926 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -2243,7 +2243,36 @@ void BfMangler::Mangle(StringImpl& outStr, MangleKind mangleKind, BfMethodInstan } void BfMangler::Mangle(StringImpl& outStr, MangleKind mangleKind, BfFieldInstance* fieldInstance) -{ +{ + if (fieldInstance->mCustomAttributes != NULL) + { + auto module = fieldInstance->mOwner->mModule; + auto linkNameAttr = fieldInstance->mCustomAttributes->Get(module->mCompiler->mLinkNameAttributeTypeDef); + if (linkNameAttr != NULL) + { + if (linkNameAttr->mCtorArgs.size() == 1) + { + if (module->TryGetConstString(fieldInstance->mOwner->mConstHolder, linkNameAttr->mCtorArgs[0], outStr)) + if (!outStr.IsWhitespace()) + return; + + auto constant = fieldInstance->mOwner->mConstHolder->GetConstant(linkNameAttr->mCtorArgs[0]); + if (constant != NULL) + { + if (constant->mInt32 == 1) // C + { + outStr += fieldInstance->GetFieldDef()->mName; + return; + } + else if (constant->mInt32 == 2) // CPP + { + //mangleContext.mCPPMangle = true; + } + } + } + } + } + if (mangleKind == BfMangler::MangleKind_GNU) outStr += BfGNUMangler::MangleStaticFieldName(fieldInstance->mOwner, fieldInstance->GetFieldDef()->mName); else diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 9d52c7be..a72b1817 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2,8 +2,8 @@ #include "BeefySysLib/util/AllocDebug.h" -#pragma warning(push) // 6 #pragma warning(disable:4996) +#pragma warning(push) // 6 #include "BfCompiler.h" #include "BfSystem.h" @@ -1097,7 +1097,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) // code as we walk the AST //mBfIRBuilder->mDbgVerifyCodeGen = true; if ( - (mModuleName == "-") + (mModuleName == "BeefTest_TestProgram") //|| (mModuleName == "BeefTest2_ClearColorValue") //|| (mModuleName == "Tests_FuncRefs") ) @@ -3381,6 +3381,7 @@ BfCheckedKind BfModule::GetDefaultCheckedKind() void BfModule::AddFailType(BfTypeInstance* typeInstance) { + BF_ASSERT(typeInstance != NULL); mContext->mFailTypes.Add(typeInstance); } @@ -3454,7 +3455,7 @@ void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLo BfLogSysM("Creating static field Module:%p Type:%p\n", this, fieldType); StringT<128> staticVarName; BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), fieldInstance); - if (!fieldType->IsValuelessType()) + if ((!fieldType->IsValuelessType()) && (!staticVarName.StartsWith("#"))) { BfIRValue globalVar = mBfIRBuilder->CreateGlobalVariable( mBfIRBuilder->MapType(fieldType, BfIRPopulateType_Eventually_Full), @@ -3538,11 +3539,13 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance* { if (!fieldDef->mTypeRef->IsA()) { + SetAndRestoreValue prevTypeInstance(mCurTypeInstance, typeInstance); Fail("Extern consts must be pointer types", fieldDef->mFieldDeclaration->mTypeRef); } if (fieldDef->mInitializer != NULL) { + SetAndRestoreValue prevTypeInstance(mCurTypeInstance, typeInstance); Fail("Extern consts cannot have initializers", fieldDef->mFieldDeclaration->mNameNode); } } @@ -9995,7 +9998,7 @@ void BfModule::ClearConstData() } BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType) -{ +{ switch (constant->mTypeCode) { case BfTypeCode_StringId: @@ -10057,12 +10060,20 @@ BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConst } break; default: break; - } - + } BfIRValue irValue = ConstantToCurrent(constant, constHolder, wantType); BF_ASSERT(irValue); if (!irValue) return BfTypedValue(); + + if (constant->mConstType == BfConstType_GlobalVar) + { + auto result = BfTypedValue(irValue, wantType, true); + if (!wantType->IsComposite()) + result = LoadValue(result); + return result; + } + return BfTypedValue(irValue, wantType, false); } @@ -10839,6 +10850,25 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo if ((typedValue.mType->IsValuelessType()) || (typedValue.mType->IsVar())) return BfTypedValue(mBfIRBuilder->GetFakeVal(), typedValue.mType, false); + if (typedValue.mValue.IsConst()) + { + auto constantValue = mBfIRBuilder->GetConstant(typedValue.mValue); + if (constantValue != NULL) + { + if (constantValue->mConstType == BfConstType_GlobalVar) + { + auto globalVar = (BfGlobalVar*)constantValue; + if (globalVar->mName[0] == '#') + { + BfTypedValue result = GetCompilerFieldValue(globalVar->mName); + if (result) + return result; + return GetDefaultTypedValue(typedValue.mType); + } + } + } + } + BfIRValue loadedVal = typedValue.mValue; if (loadedVal) { @@ -12603,14 +12633,28 @@ void BfModule::HadSlotCountDependency() mUsedSlotCount = BF_MAX(mCompiler->mMaxInterfaceSlots, 0); } +BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str) +{ + if (str == "#TimeLocal") + { + time_t rawtime; + time(&rawtime); + tm* timeinfo = localtime(&rawtime); + char result[32]; + sprintf(result, "%d/%.2d/%.2d %.2d:%.2d:%.2d", + 1900 + timeinfo->tm_year, + timeinfo->tm_mon, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec); + return BfTypedValue(GetStringObjectValue(result), ResolveTypeDef(mCompiler->mStringTypeDef)); + } + return BfTypedValue(); +} + BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) { - if (mIsScratchModule) - { - // Just fake it for the extern and unspecialized modules - return BfTypedValue(mBfIRBuilder->GetFakeVal(), fieldInstance->GetResolvedType(), true); - } - BfIRValue globalValue; auto fieldDef = fieldInstance->GetFieldDef(); @@ -12626,7 +12670,13 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) { return GetDefaultTypedValue(fieldInstance->GetResolvedType()); } - } + } + + if (mIsScratchModule) + { + // Just fake it for the extern and unspecialized modules + return BfTypedValue(mBfIRBuilder->CreateConstNull(), fieldInstance->GetResolvedType(), true); + } BfIRValue* globalValuePtr = NULL; if (mStaticFieldRefs.TryGetValue(fieldInstance, &globalValuePtr)) @@ -12648,8 +12698,12 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) PopulateType(typeType); if ((typeType != NULL) && (!typeType->IsValuelessType())) { + BfIRType irType = mBfIRBuilder->MapType(typeType); + + SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || staticVarName.StartsWith('#')); + globalValue = mBfIRBuilder->CreateGlobalVariable( - mBfIRBuilder->MapType(typeType), + irType, false, BfIRLinkageType_External, BfIRValue(), @@ -16601,6 +16655,10 @@ void BfModule::EmitGCMarkMembers() if ((fieldDef->mIsStatic) && (!fieldDef->mIsConst)) { + StringT<128> staticVarName; + BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), &fieldInst); + if (staticVarName.StartsWith('#')) + continue; markVal = ReferenceStaticField(&fieldInst); } else if (!fieldDef->mIsStatic) @@ -20368,7 +20426,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool else { BfConstResolver constResolver(this); - defaultValue = constResolver.Resolve(paramDef->mParamDeclaration->mInitializer, resolvedParamType, BfConstResolveFlag_NoCast); + defaultValue = constResolver.Resolve(paramDef->mParamDeclaration->mInitializer, resolvedParamType, (BfConstResolveFlags)(BfConstResolveFlag_NoCast | BfConstResolveFlag_AllowGlobalVariable)); if ((defaultValue) && (defaultValue.mType != resolvedParamType)) { SetAndRestoreValue prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 1a8ade29..8e87f3aa 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1548,6 +1548,7 @@ public: bool CheckModifyValue(BfTypedValue& typedValue, BfAstNode* refNode, const char* modifyType = NULL); BfIRValue GetInterfaceSlotNum(BfTypeInstance* ifaceType); void HadSlotCountDependency(); + BfTypedValue GetCompilerFieldValue(const StringImpl& str); BfTypedValue ReferenceStaticField(BfFieldInstance* fieldInstance); BfTypedValue GetThis(); BfLocalVariable* GetThisVariable();