diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 53d90e1f..8e7aa5c7 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -6910,16 +6910,22 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) { if ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference)) - { - queuedMoreMethods = true; + { if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mIsForeignMethodDef)) { mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodInstGroup.mDefault->mMethodDef, BfTypeVector(), (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass)); + queuedMoreMethods = true; } else - mContext->mUnreifiedModule->GetMethodInstance(typeInst, typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx], BfTypeVector(), + { + auto methodDef = typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx]; + if (methodDef->mMethodType == BfMethodType_Init) + continue; + mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodDef, BfTypeVector(), (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass)); + queuedMoreMethods = true; + } } } } diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 9dda3c7b..aa36c9f4 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -479,11 +479,19 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio if (auto ctorDeclaration = BfNodeDynCast(methodDeclaration)) { methodDef->mIsMutating = true; - methodDef->mMethodType = BfMethodType_Ctor; - if (methodDef->mIsStatic) - methodDef->mName = "__BfStaticCtor"; + if (methodDeclaration->mOpenParen != NULL) + { + methodDef->mMethodType = BfMethodType_Ctor; + if (methodDef->mIsStatic) + methodDef->mName = "__BfStaticCtor"; + else + methodDef->mName = "__BfCtor"; + } else - methodDef->mName = "__BfCtor"; + { + methodDef->mMethodType = BfMethodType_Init; + methodDef->mName = "__BfInit"; + } } else if (methodDeclaration->IsA()) { @@ -1133,6 +1141,10 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType methodDef->mName = "__BfCtorClear"; methodDef->mIsNoReflect = true; } + else if (methodType == BfMethodType_Init) + { + methodDef->mName = "__BfInit"; + } else if (methodType == BfMethodType_Dtor) { if (isStatic) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index d2ddfc62..e118be87 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -12058,6 +12058,9 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance) BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType) { + if (methodDef->mMethodType == BfMethodType_Init) + return BfModuleMethodInstance(); + if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (mCompiler->mIsResolveOnly)) { // Don't bother inlining for resolve-only @@ -12679,11 +12682,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM if ((prevIRFunc) && (!prevIRFunc.IsFake())) methodInstance->mIRFunction = prevIRFunc; // Take it over } - - /*// 24 bits for typeid, 20 for method id, 20 for specialization index - methodInstance->mMethodId = ((int64)typeInst->mTypeId) + ((int64)methodInstGroup->mMethodIdx << 24); - if (methodInstGroup->mMethodSpecializationMap != NULL) - methodInstance->mMethodId += ((int64)methodInstGroup->mMethodSpecializationMap->size() << 44);*/ + methodInstance->mMethodDef = methodDef; methodInstance->mAlwaysInline = methodDef->mAlwaysInline; methodInstance->mMethodInstanceGroup = methodInstGroup; @@ -12711,10 +12710,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM } } - if (methodDef->mDeclaringType->mTypeDeclaration != typeInst->mTypeDef->mTypeDeclaration) + if (methodDef->mMethodType == BfMethodType_Init) { - // With extensions we can have multiple definitions of the same method - //methodInstance->mMangleWithIdx = true; + methodInstance->mMangleWithIdx = true; } BfModule* declareModule = GetOrCreateMethodModule(methodInstance); @@ -15574,6 +15572,8 @@ void BfModule::EmitCtorBody(bool& skipBody) { // If we had a 'this' initializer, that other ctor will have initialized our fields + //auto + if ((!mCompiler->mIsResolveOnly) || (mCompiler->mResolvePassData->mAutoComplete == NULL) || (mCompiler->mResolvePassData->mAutoComplete->mResolveType == BfResolveType_ShowFileSymbolReferences)) @@ -15581,6 +15581,61 @@ void BfModule::EmitCtorBody(bool& skipBody) bool hadInlineInitBlock = false; BfScopeData scopeData; + auto _CheckInitBlock = [&](BfAstNode* node) + { + if (!hadInlineInitBlock) + { + if ((mBfIRBuilder->DbgHasInfo()) && (!mCurTypeInstance->IsUnspecializedType()) && (mHasFullDebugInfo)) + { + UpdateSrcPos(baseCtorNode); + + if (methodDef->mBody == NULL) + SetIllegalSrcPos(); + + // NOP so we step onto the open paren of the method so we can choose to set into the field initializers or step over them + EmitEnsureInstructionAt(); + + BfType* thisType = mCurTypeInstance; + if (thisType->IsValueType()) + thisType = CreateRefType(thisType); + + SizedArray diParamTypes; + BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes); + + mCurMethodState->AddScope(&scopeData); + NewScopeState(); + + int flags = 0; + mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation(); + BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt); + // mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor + mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", "", mCurFilePosition.mFileInstance->mDIFile, + mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue()); + + UpdateSrcPos(node); + + auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope, + "this", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(thisType)); + + // + { + auto loadedThis = GetThis(); + + // LLVM can't handle two variables pointing to the same value + BfIRValue copiedThisPtr; + copiedThisPtr = CreateAlloca(thisType); + auto storeInst = mBfIRBuilder->CreateStore(loadedThis.mValue, copiedThisPtr); + mBfIRBuilder->ClearDebugLocation(storeInst); + mBfIRBuilder->DbgInsertDeclare(copiedThisPtr, diVariable); + } + + hadInlineInitBlock = true; + } + } + + UpdateSrcPos(node); + }; + for (auto fieldDef : typeDef->mFields) { // For extensions, only handle these fields in the appropriate extension @@ -15613,57 +15668,7 @@ void BfModule::EmitCtorBody(bool& skipBody) if (fieldDef->mInitializer != NULL) { - if (!hadInlineInitBlock) - { - if ((mBfIRBuilder->DbgHasInfo()) && (!mCurTypeInstance->IsUnspecializedType()) && (mHasFullDebugInfo)) - { - UpdateSrcPos(baseCtorNode); - - if (methodDef->mBody == NULL) - SetIllegalSrcPos(); - - // NOP so we step onto the open paren of the method so we can choose to set into the field initializers or step over them - EmitEnsureInstructionAt(); - - BfType* thisType = mCurTypeInstance; - if (thisType->IsValueType()) - thisType = CreateRefType(thisType); - - SizedArray diParamTypes; - BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes); - - mCurMethodState->AddScope(&scopeData); - NewScopeState(); - - int flags = 0; - mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation(); - BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt); - // mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor - mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", "", mCurFilePosition.mFileInstance->mDIFile, - mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue()); - - UpdateSrcPos(fieldDef->mInitializer); - - auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope, - "this", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(thisType)); - - // - { - auto loadedThis = GetThis(); - - // LLVM can't handle two variables pointing to the same value - BfIRValue copiedThisPtr; - copiedThisPtr = CreateAlloca(thisType); - auto storeInst = mBfIRBuilder->CreateStore(loadedThis.mValue, copiedThisPtr); - mBfIRBuilder->ClearDebugLocation(storeInst); - mBfIRBuilder->DbgInsertDeclare(copiedThisPtr, diVariable); - } - - hadInlineInitBlock = true; - } - } - - UpdateSrcPos(fieldDef->mInitializer); + _CheckInitBlock(fieldDef->mInitializer); } BfIRValue fieldAddr; @@ -15688,6 +15693,30 @@ void BfModule::EmitCtorBody(bool& skipBody) } } + mCurTypeInstance->mTypeDef->PopulateMemberSets(); + BfMemberSetEntry* entry = NULL; + BfMethodDef* initMethodDef = NULL; + mCurTypeInstance->mTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry); + if (entry != NULL) + initMethodDef = (BfMethodDef*)entry->mMemberDef; + + SizedArray initBodies; + + for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName) + { + if (initMethodDef->mDeclaringType != methodDef->mDeclaringType) + continue; + if (initMethodDef->mMethodType != BfMethodType_Init) + continue; + initBodies.Insert(0, initMethodDef->mBody); + } + + for (auto body : initBodies) + { + _CheckInitBlock(body); + VisitEmbeddedStatement(body); + } + if (hadInlineInitBlock) { RestoreScopeState(); @@ -15718,6 +15747,22 @@ void BfModule::EmitCtorBody(bool& skipBody) CreateValueFromExpression(fieldDef->mInitializer, wantType, BfEvalExprFlags_FieldInitializer); } } + + tempTypeDef->PopulateMemberSets(); + BfMemberSetEntry* entry = NULL; + BfMethodDef* initMethodDef = NULL; + tempTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry); + if (entry != NULL) + initMethodDef = (BfMethodDef*)entry->mMemberDef; + SizedArray initBodies; + for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName) + { + if (initMethodDef->mMethodType != BfMethodType_Init) + continue; + initBodies.Insert(0, initMethodDef->mBody); + } + for (auto body : initBodies) + VisitEmbeddedStatement(body); } } @@ -15731,7 +15776,7 @@ void BfModule::EmitCtorBody(bool& skipBody) MarkFieldInitialized(fieldInst); } } - } + } } // Call base ctor (if applicable) @@ -18996,7 +19041,6 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { if ((skipEndChecks) || (methodDef->mBody == NULL)) break; - LocalVariableDone(localVar, true); } @@ -21410,7 +21454,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) && (!methodDef->mIsLocalMethod)) { - if (!methodInstance->mIsForeignMethodDef) + if ((!methodInstance->mIsForeignMethodDef) && (methodDef->mMethodType != BfMethodType_Init)) { typeDef->PopulateMemberSets(); BfMethodDef* nextMethod = NULL; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 5d99b92b..856b1b3f 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -4318,6 +4318,12 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) declRequired = false; } + if (methodDef->mMethodType == BfMethodType_Init) + { + declRequired = false; + implRequired = false; + } + if (!implRequired) { if (!mIsScratchModule) @@ -4350,6 +4356,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) continue; } + if (methodDef->mMethodType == BfMethodType_Init) + continue; + int prevWorklistSize = (int)mContext->mMethodWorkList.size(); auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 31878c9d..7ee91121 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -5774,8 +5774,19 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, int depth, BfAstNod ctorDecl->mReturnType = NULL; ReplaceNode(tokenNode, ctorDecl); MEMBER_SET(ctorDecl, mThisToken, tokenNode); + if (auto block = BfNodeDynCast(mVisitorPos.GetNext())) + { + mVisitorPos.MoveNext(); + MEMBER_SET(ctorDecl, mBody, block); - ParseMethod(ctorDecl, ¶ms, &commas); + if (IsNodeRelevant(ctorDecl)) + { + SetAndRestoreValue prevMethodDeclaration(mCurMethodDecl, ctorDecl); + HandleBlock(block); + } + } + else + ParseMethod(ctorDecl, ¶ms, &commas); return ctorDecl; } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 23234fe1..d892b757 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -635,13 +635,14 @@ public: enum BfMethodType : uint8 { BfMethodType_Ignore, - BfMethodType_Normal, + BfMethodType_Normal, BfMethodType_PropertyGetter, BfMethodType_PropertySetter, BfMethodType_CtorCalcAppend, BfMethodType_Ctor, BfMethodType_CtorNoBody, BfMethodType_CtorClear, + BfMethodType_Init, BfMethodType_Dtor, BfMethodType_Operator, BfMethodType_Mixin,