diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 1d46eaa0..5ffa7139 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -1009,7 +1009,7 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array& test } BfExprEvaluator exprEvaluator(bfModule); - exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); + exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); bfModule->mBfIRBuilder->CreateBr(testHeadBlock); } diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index fd149eb2..9b08023b 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -645,6 +645,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) dupMethodInstance.mMethodProcessRequest = NULL; dupMethodInstance.mIsReified = true; dupMethodInstance.mHotMethod = NULL; + dupMethodInstance.mInCEMachine = false; // Only have the original one BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules { diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 59e8ad22..a091b532 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4801,7 +4801,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc); } -BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl& irArgs, BfTypedValue* sret, bool isTailCall) +BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl& irArgs, BfTypedValue* sret, bool isTailCall) { // static int sCallIdx = 0; // if (!mModule->mCompiler->mIsResolveOnly) @@ -4990,7 +4990,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV } else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0) { - auto constRet = mModule->mCompiler->mCEMachine->Call(mModule, methodInstance, irArgs, CeEvalFlags_None); + auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, CeEvalFlags_None); if (constRet) return constRet; } @@ -6632,7 +6632,7 @@ SplatArgs(lookupVal, irArgs); } auto func = moduleMethodInstance.mFunc; - BfTypedValue result = CreateCall(methodInstance, func, bypassVirtual, irArgs); + BfTypedValue result = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs); if ((result.mType != NULL) && (result.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly)) mModule->Fail("Method return type reference failed to resolve", targetSrc); return result; @@ -9144,7 +9144,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, NULL); if (addFunctionBindResult.mMethodInstance != NULL) - CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs); + CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs); isFirstAdd = false; } @@ -9162,7 +9162,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) PushArg(argValue, irArgs); for (int argIdx = (int)irArgs.size(); argIdx < (int)addFunctionBindResult.mIRArgs.size(); argIdx++) irArgs.Add(addFunctionBindResult.mIRArgs[argIdx]); - CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs); + CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs); } } @@ -13100,7 +13100,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs { BF_ASSERT(calcAppendMethodModule.mFunc); - appendSizeTypedValue = CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, irArgs); + appendSizeTypedValue = CreateCall(objCreateExpr, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, irArgs); BF_ASSERT(appendSizeTypedValue.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr)); } appendSizeValue = appendSizeTypedValue.mValue; @@ -13187,7 +13187,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs { SizedArray irArgs; irArgs.push_back(mResult.mValue); - CreateCall(ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs); + CreateCall(objCreateExpr, ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs); } } @@ -13255,7 +13255,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } if (!typeInstance->IsValuelessType()) bindResult.mIRArgs.Insert(0, mResult.mValue); - CreateCall(bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs); + CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs); } } } @@ -15870,7 +15870,7 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp } } else - mResult = CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args); + mResult = CreateCall(mPropSrc, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args); if (mResult.mType != NULL) { if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly)) @@ -16794,7 +16794,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool PushArg(convVal, args); if (methodInstance) - CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args); + CreateCall(assignExpr, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args); mPropDef = NULL; mResult = convVal; @@ -16868,7 +16868,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool SizedArray args; exprEvaluator.PushThis(assignExpr->mLeft, leftValue, moduleMethodInstance.mMethodInstance, args); exprEvaluator.PushArg(rightValue, args); - exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(assignExpr, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args); convVal = leftValue; handled = true; break; @@ -19068,7 +19068,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, } PushArg(writeToProp, args); - CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, false, args); + CreateCall(opToken, methodInstance.mMethodInstance, methodInstance.mFunc, false, args); } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index a951c665..6a34e17c 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -420,7 +420,7 @@ public: BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL); void AddCallDependencies(BfMethodInstance* methodInstance); void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc); - BfTypedValue CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false); + BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false); BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl& argValues, bool skipThis = false); BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target); void MakeBaseConcrete(BfTypedValue& typedValue); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 823da7f7..1390006c 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -694,7 +694,7 @@ public: { BF_ASSERT(calcAppendMethodModule.mFunc); - subDependSize = exprEvaluator.CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs); + subDependSize = exprEvaluator.CreateCall(objCreateExpr, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs); BF_ASSERT(subDependSize.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr)); } if (subDependSize) @@ -9211,7 +9211,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar SizedArray irArgs; irArgs.push_back(objectParam); irArgs.push_back(GetConstValue32(targetType->mTypeId)); - auto callResult = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); + auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); auto resultType = ResolveTypeDef(mSystem->mTypeBool); auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType)); irb->CreateCondBr(cmpResult, trueBlock, falseBlock); @@ -14788,7 +14788,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly) calcAppendArgs = bindResult.mIRArgs; } BF_ASSERT(calcAppendMethodModule.mFunc); - appendSizeTypedValue = exprEvaluator.CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs); + appendSizeTypedValue = exprEvaluator.CreateCall(NULL, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs); BF_ASSERT(appendSizeTypedValue.mType == GetPrimitiveType(BfTypeCode_IntPtr)); @@ -15648,7 +15648,7 @@ void BfModule::EmitCtorBody(bool& skipBody) SizedArray irArgs; exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs); - exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); + exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); calledCtorNoBody = true; } @@ -16131,7 +16131,7 @@ void BfModule::EmitEnumToStringBody() SizedArray args; args.Add(stringDestVal.mValue); args.Add(caseStr); - exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); auto payloadType = fieldInstance.mResolvedType->ToTypeInstance(); BF_ASSERT(payloadType->IsTuple()); @@ -16150,7 +16150,7 @@ void BfModule::EmitEnumToStringBody() exprEvaluator.PushThis(NULL, payload, toStringMethod.mMethodInstance, irArgs); stringDestVal = LoadValue(stringDestAddr); irArgs.Add(stringDestVal.mValue); - exprEvaluator.CreateCall(toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs); + exprEvaluator.CreateCall(NULL, toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs); } mBfIRBuilder->CreateBr(endBlock); @@ -16186,7 +16186,7 @@ void BfModule::EmitEnumToStringBody() auto stringDestVal = LoadValue(stringDestAddr); args.Add(stringDestVal.mValue); args.Add(mBfIRBuilder->CreateLoad(strVal)); - exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); mBfIRBuilder->CreateBr(endBlock); mBfIRBuilder->AddBlock(noMatchBlock); @@ -16197,7 +16197,7 @@ void BfModule::EmitEnumToStringBody() args.Add(int64Val); stringDestVal = LoadValue(stringDestAddr); args.Add(stringDestVal.mValue); - exprEvaluator.CreateCall(toStringModuleMethodInstance.mMethodInstance, toStringModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, toStringModuleMethodInstance.mMethodInstance, toStringModuleMethodInstance.mFunc, false, args); mBfIRBuilder->CreateBr(endBlock); mBfIRBuilder->AddBlock(endBlock); @@ -16226,7 +16226,7 @@ void BfModule::EmitTupleToStringBody() auto stringDestVal = LoadValue(stringDestRef); args.Add(stringDestVal.mValue); args.Add(mBfIRBuilder->CreateConst(BfTypeCode_Char8, (int)c)); - exprEvaluator.CreateCall(appendCharModuleMethodInstance.mMethodInstance, appendCharModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, appendCharModuleMethodInstance.mMethodInstance, appendCharModuleMethodInstance.mFunc, false, args); }; int fieldIdx = 0; @@ -16254,7 +16254,7 @@ void BfModule::EmitTupleToStringBody() auto stringDestVal = LoadValue(stringDestRef); args.Add(stringDestVal.mValue); args.Add(commaStr); - exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); } fieldIdx++; @@ -16300,7 +16300,7 @@ void BfModule::EmitTupleToStringBody() auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]); stringDestVal = LoadValue(stringDestVal); args.Add(stringDestVal.mValue); - exprEvaluator.CreateCall(toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args); continue; } @@ -16324,7 +16324,7 @@ void BfModule::EmitTupleToStringBody() auto stringDestVal = LoadValue(stringDestRef); args.Add(stringDestVal.mValue); args.Add(strVal); - exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); continue; } @@ -16389,7 +16389,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark val = mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(mContext->mBfObjectType)); SizedArray args; args.push_back(val); - exprEvaluator.CreateCall(markFromGCThreadMethodInstance.mMethodInstance, markFromGCThreadMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, markFromGCThreadMethodInstance.mMethodInstance, markFromGCThreadMethodInstance.mFunc, false, args); } else if ((fieldTypeInst->IsComposite()) && (!fieldTypeInst->IsTypedPrimitive())) { @@ -16403,7 +16403,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark markVal = Cast(NULL, markVal, methodOwner); exprEvaluator.PushThis(NULL, markVal, markMemberMethodInstance.mMethodInstance, args); - exprEvaluator.CreateCall(markMemberMethodInstance.mMethodInstance, markMemberMethodInstance.mFunc, false, args); + exprEvaluator.CreateCall(NULL, markMemberMethodInstance.mMethodInstance, markMemberMethodInstance.mFunc, false, args); } } } @@ -16452,7 +16452,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse BfExprEvaluator exprEvaluator(this); SizedArray args; exprEvaluator.PushThis(chainedMethodInst->mMethodDef->GetRefNode(), GetThis(), chainedMethodInst, args); - exprEvaluator.CreateCall(moduleMethodInst.mMethodInstance, moduleMethodInst.mFunc, true, args); + exprEvaluator.CreateCall(NULL, moduleMethodInst.mMethodInstance, moduleMethodInst.mFunc, true, args); } } @@ -18617,14 +18617,14 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) mBfIRBuilder->PopulateType(methodInstance->mReturnType); auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true); exprEvaluator.mReceivingValue = &returnType; - auto retVal = exprEvaluator.CreateCall(innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true); + auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true); BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used mBfIRBuilder->CreateRetVoid(); } else { mBfIRBuilder->PopulateType(methodInstance->mReturnType); - auto retVal = exprEvaluator.CreateCall(innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true); + auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true); if (mCurMethodInstance->mReturnType->IsValueType()) retVal = LoadValue(retVal); CreateReturn(retVal.mValue); @@ -21680,107 +21680,109 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); auto checkMethod = nextMethod; nextMethod = nextMethod->mNextWithSameName; - if ((checkMethod != methodDef) && (typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault != NULL)) - { - auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault; + if (checkMethod == methodDef) + continue; - if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) && - (checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) && - (checkMethod->mIsMutating == methodDef->mIsMutating) && - (CompareMethodSignatures(checkMethodInstance, mCurMethodInstance))) - { - bool canChain = false; + auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault; + if (checkMethodInstance == NULL) + continue; - if ((methodDef->mParams.empty()) && - (checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic)) + if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) && + (checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) && + (checkMethod->mIsMutating == methodDef->mIsMutating) && + (CompareMethodSignatures(checkMethodInstance, mCurMethodInstance))) + { + bool canChain = false; + + if ((methodDef->mParams.empty()) && + (checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic)) + { + if ((methodDef->mMethodType == BfMethodType_CtorNoBody) || (methodDef->mMethodType == BfMethodType_Dtor)) + canChain = true; + else if (methodDef->mMethodType == BfMethodType_Normal) { - if ((methodDef->mMethodType == BfMethodType_CtorNoBody) || (methodDef->mMethodType == BfMethodType_Dtor)) + if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) || + (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) || + (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS)) canChain = true; - else if (methodDef->mMethodType == BfMethodType_Normal) - { - if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) || - (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) || - (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS)) - canChain = true; - } } - - if (canChain) + } + + if (canChain) + { + bool isBetter; + bool isWorse; + CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse); + if (isBetter && !isWorse) { - bool isBetter; - bool isWorse; - CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse); - if (isBetter && !isWorse) - { - methodInstance->mChainType = BfMethodChainType_ChainHead; - checkMethodInstance->mChainType = BfMethodChainType_ChainMember; - } - else - { - checkMethodInstance->mChainType = BfMethodChainType_ChainHead; - methodInstance->mChainType = BfMethodChainType_ChainMember; - } + methodInstance->mChainType = BfMethodChainType_ChainHead; + checkMethodInstance->mChainType = BfMethodChainType_ChainMember; } else { - if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType)) - continue; - - bool silentlyAllow = false; - bool extensionWarn = false; - if (checkMethod->mDeclaringType != methodDef->mDeclaringType) - { - if (typeInstance->IsInterface()) - { - if (methodDef->mIsOverride) + checkMethodInstance->mChainType = BfMethodChainType_ChainHead; + methodInstance->mChainType = BfMethodChainType_ChainMember; + } + } + else + { + if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType)) + continue; + + bool silentlyAllow = false; + bool extensionWarn = false; + if (checkMethod->mDeclaringType != methodDef->mDeclaringType) + { + if (typeInstance->IsInterface()) + { + if (methodDef->mIsOverride) + silentlyAllow = true; + } + else + { + if ((methodDef->mIsOverride) && (checkMethod->mIsExtern)) + { + silentlyAllow = true; + methodInstance->mIsInnerOverride = true; + CheckOverridenMethod(methodInstance, checkMethodInstance); + } + else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) && + (!checkMethod->mDeclaringType->IsExtension())) + { + foundHiddenMethod = true; + if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic)) silentlyAllow = true; + else if (methodDef->mIsNew) + silentlyAllow = true; + else + extensionWarn = true; } else - { - if ((methodDef->mIsOverride) && (checkMethod->mIsExtern)) - { - silentlyAllow = true; - methodInstance->mIsInnerOverride = true; - CheckOverridenMethod(methodInstance, checkMethodInstance); - } - else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) && - (!checkMethod->mDeclaringType->IsExtension())) - { - foundHiddenMethod = true; - if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic)) - silentlyAllow = true; - else if (methodDef->mIsNew) - silentlyAllow = true; - else - extensionWarn = true; - } - else - silentlyAllow = true; - } + silentlyAllow = true; } + } - if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse)) - silentlyAllow = true; - - if (!silentlyAllow) + if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse)) + silentlyAllow = true; + + if (!silentlyAllow) + { + if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator)) { - if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator)) - { - auto refNode = methodDef->GetRefNode(); - BfError* bfError; - if (extensionWarn) - bfError = Warn(BfWarning_CS0114_MethodHidesInherited, - StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.", - checkMethod->mDeclaringType->mProject->mName.c_str()), refNode); - else - bfError = Fail("Method already declared with the same parameter types", refNode, true); - if (bfError != NULL) - mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode()); - } + auto refNode = methodDef->GetRefNode(); + BfError* bfError; + if (extensionWarn) + bfError = Warn(BfWarning_CS0114_MethodHidesInherited, + StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.", + checkMethod->mDeclaringType->mProject->mName.c_str()), refNode); + else + bfError = Fail("Method already declared with the same parameter types", refNode, true); + if (bfError != NULL) + mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode()); } } } - } + } } } diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index ab166b98..29a859ba 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -4370,103 +4370,109 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); - // Pass 2 - for (auto methodDef : typeDef->mMethods) + // Def passes. First non-overrides then overrides (for in-place overrides in methods) + for (int pass = 0; pass < 2; pass++) { - auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx]; + for (auto methodDef : typeDef->mMethods) + { + if ((pass == 1) != (methodDef->mIsOverride)) + continue; - if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) && - (methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl)) - { - BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind); - continue; - } + auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx]; - 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); - - auto methodInstance = moduleMethodInstance.mMethodInstance; - if (methodInstance == NULL) - { - BF_ASSERT(typeInstance->IsGenericTypeInstance() && (typeInstance->mTypeDef->mIsCombinedPartial)); - continue; - } - - if ((!mCompiler->mIsResolveOnly) && - ((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || (!typeInstance->IsReified()))) - { - bool forceMethodImpl = false; - - BfCustomAttributes* customAttributes = methodInstance->GetCustomAttributes(); - if ((customAttributes != NULL) && (typeInstance->IsReified())) + if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) && + (methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl)) { - for (auto& attr : customAttributes->mAttributes) - { - auto attrTypeInst = attr.mType->ToTypeInstance(); - auto attrCustomAttributes = attrTypeInst->mCustomAttributes; - if (attrCustomAttributes == NULL) - continue; + BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind); + continue; + } - for (auto& attrAttr : attrCustomAttributes->mAttributes) + 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); + + auto methodInstance = moduleMethodInstance.mMethodInstance; + if (methodInstance == NULL) + { + BF_ASSERT(typeInstance->IsGenericTypeInstance() && (typeInstance->mTypeDef->mIsCombinedPartial)); + continue; + } + + if ((!mCompiler->mIsResolveOnly) && + ((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || (!typeInstance->IsReified()))) + { + bool forceMethodImpl = false; + + BfCustomAttributes* customAttributes = methodInstance->GetCustomAttributes(); + if ((customAttributes != NULL) && (typeInstance->IsReified())) + { + for (auto& attr : customAttributes->mAttributes) { - if (attrAttr.mType->ToTypeInstance()->mTypeDef == mCompiler->mAttributeUsageAttributeTypeDef) + auto attrTypeInst = attr.mType->ToTypeInstance(); + auto attrCustomAttributes = attrTypeInst->mCustomAttributes; + if (attrCustomAttributes == NULL) + continue; + + for (auto& attrAttr : attrCustomAttributes->mAttributes) { - // Check for Flags arg - if (attrAttr.mCtorArgs.size() < 2) - continue; - auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]); - if (constant == NULL) - continue; - if (constant->mTypeCode == BfTypeCode_Boolean) - continue; - if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0) - forceMethodImpl = true; + if (attrAttr.mType->ToTypeInstance()->mTypeDef == mCompiler->mAttributeUsageAttributeTypeDef) + { + // Check for Flags arg + if (attrAttr.mCtorArgs.size() < 2) + continue; + auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]); + if (constant == NULL) + continue; + if (constant->mTypeCode == BfTypeCode_Boolean) + continue; + if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0) + forceMethodImpl = true; + } } } } - } - if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest) - { - if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef))) + if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest) { - forceMethodImpl = true; + if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef))) + { + forceMethodImpl = true; + } + } + + if (forceMethodImpl) + { + if (!typeInstance->IsReified()) + mContext->mScratchModule->PopulateType(typeInstance, BfPopulateType_Data); + // Reify method + mContext->mScratchModule->GetMethodInstance(typeInstance, methodDef, BfTypeVector()); + BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingReference); } } - if (forceMethodImpl) + + bool methodUsedVirtually = false; + if (typeInstance->IsInterface()) { - if (!typeInstance->IsReified()) - mContext->mScratchModule->PopulateType(typeInstance, BfPopulateType_Data); - // Reify method - mContext->mScratchModule->GetMethodInstance(typeInstance, methodDef, BfTypeVector()); - BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingReference); + if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf())) + SlotInterfaceMethod(methodInstance); + } + else if (!methodDef->IsEmptyPartial()) + { + methodUsedVirtually = SlotVirtualMethod(methodInstance, &ambiguityContext); } - } - - bool methodUsedVirtually = false; - if (typeInstance->IsInterface()) - { - if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf())) - SlotInterfaceMethod(methodInstance); - } - else if (!methodDef->IsEmptyPartial()) - { - methodUsedVirtually = SlotVirtualMethod(methodInstance, &ambiguityContext); - } - - // This is important for reducing latency of autocomplete popup, but it's important we don't allow the autocomplete - // thread to cause any reentry issues by re-populating a type at an "inopportune time". We do allow certain - // reentries in PopulateType, but not when we're resolving fields (for example) - if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField)) - { - disableYield.Release(); - mSystem->CheckLockYield(); - disableYield.Acquire(); + // This is important for reducing latency of autocomplete popup, but it's important we don't allow the autocomplete + // thread to cause any reentry issues by re-populating a type at an "inopportune time". We do allow certain + // reentries in PopulateType, but not when we're resolving fields (for example) + if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField)) + { + disableYield.Release(); + mSystem->CheckLockYield(); + disableYield.Acquire(); + } } } @@ -11031,7 +11037,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp SizedArray args; exprEvaluator.PushArg(castedFromValue, args); - operatorOut = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args); + operatorOut = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args); if ((operatorOut.mType != NULL) && (operatorOut.mType->IsSelf())) { BF_ASSERT(IsInGeneric()); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 861be6a9..13f71f53 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -760,7 +760,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz } BfExprEvaluator expressionEvaluator(this); - expressionEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, ((flags & BfDeferredBlockFlag_BypassVirtual) != 0), llvmArgs); + expressionEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, ((flags & BfDeferredBlockFlag_BypassVirtual) != 0), llvmArgs); if ((flags & BfDeferredBlockFlag_DoNullChecks) != 0) { @@ -3956,7 +3956,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) BF_ASSERT(methodInstance->mMethodDef->mName == "~this"); SizedArray llvmArgs; llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType))); - expressionEvaluator.CreateCall(methodInstance, methodInstance->mIRFunction, false, llvmArgs); + expressionEvaluator.CreateCall(deleteStmt->mDeleteToken, methodInstance, methodInstance->mIRFunction, false, llvmArgs); } if ((deleteStmt->mTargetTypeToken != NULL) && (!isAppendDelete)) @@ -5998,7 +5998,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) SizedArray args; auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner()); exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args); - itr = exprEvaluator.CreateCall(getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args); + itr = exprEvaluator.CreateCall(forEachStmt->mCollectionExpression, getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args); } } diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 91ed4940..2bfdfd24 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -16,6 +16,13 @@ struct CeOpInfo CeOperandInfoKind mOperandC; }; +#define CEOPINFO_SIZED_1(OPNAME, OPINFOA) \ + {OPNAME##"_8", OPINFOA}, \ + {OPNAME##"_16", OPINFOA}, \ + {OPNAME##"_32", OPINFOA}, \ + {OPNAME##"_64", OPINFOA}, \ + {OPNAME##"_X", OPINFOA, CEOI_IMM32} + #define CEOPINFO_SIZED_2(OPNAME, OPINFOA, OPINFOB) \ {OPNAME##"_8", OPINFOA, OPINFOB}, \ {OPNAME##"_16", OPINFOA, OPINFOB}, \ @@ -43,6 +50,11 @@ struct CeOpInfo {OPNAME##"_I64", OPINFOA, OPINFOB}, \ {OPNAME##"_F32", OPINFOA, OPINFOB}, \ {OPNAME##"_F64", OPINFOA, OPINFOB} +#define CEOPINFO_SIZED_NUMERIC_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ + {OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ + {OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ + {OPNAME##"_I32", OPINFOA, OPINFOB, OPINFOC}, \ + {OPNAME##"_I64", OPINFOA, OPINFOB, OPINFOC} #define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ {OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ @@ -60,6 +72,7 @@ static CeOpInfo gOpInfo[] = {"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef}, {"FrameAddr32", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr64", CEOI_FrameRef, CEOI_FrameRef}, + {"Zero", CEOI_FrameRef, CEOI_IMM32}, {"Const_8", CEOI_FrameRef, CEOI_IMM8}, {"Const_16", CEOI_FrameRef, CEOI_IMM16}, @@ -71,15 +84,33 @@ static CeOpInfo gOpInfo[] = CEOPINFO_SIZED_3("Store", CEOI_None, CEOI_FrameRef, CEOI_FrameRef), CEOPINFO_SIZED_3("Move", CEOI_None, CEOI_FrameRef, CEOI_FrameRef), CEOPINFO_SIZED_2("Push", CEOI_None, CEOI_FrameRef), + CEOPINFO_SIZED_1("Pop", CEOI_FrameRef), {"AdjustSP", CEOI_None, CEOI_FrameRef}, {"Call", CEOI_None, CEOI_IMM32}, {"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef}, + {"AddConst_I8", CEOI_FrameRef, CEOI_IMM8}, + {"AddConst_I16", CEOI_FrameRef, CEOI_IMM16}, + {"AddConst_I32", CEOI_FrameRef, CEOI_IMM32}, + {"AddConst_I64", CEOI_FrameRef, CEOI_IMM64}, + {"AddConst_F32", CEOI_FrameRef, CEOI_IMMF32}, + {"AddConst_F64", CEOI_FrameRef, CEOI_IMMF64}, + CEOPINFO_SIZED_NUMERIC_PLUSF_3("Add", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("Sub", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("Mul", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("SDiv", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_3("UDiv", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("SMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_3("UMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_EQ", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_3("Cmp_ULT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), + CEOPINFO_SIZED_NUMERIC_3("Cmp_ULE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), //{"Cmp_SLT_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef}, CEOPINFO_SIZED_NUMERIC_PLUSF_2("Neg", CEOI_FrameRef, CEOI_FrameRef), @@ -441,12 +472,6 @@ void CeBuilder::EmitSizedOp(CeOp baseOp, const CeOperand& operand, CeOperand* ou Emit(op); - if (outResult != NULL) - { - *outResult = FrameAlloc(operand.mType); - EmitFrameOffset(*outResult); - } - if (!isStdSize) { if (!allowNonStdSize) @@ -454,6 +479,12 @@ void CeBuilder::EmitSizedOp(CeOp baseOp, const CeOperand& operand, CeOperand* ou Emit((int32)operand.mType->mSize); } + if (outResult != NULL) + { + *outResult = FrameAlloc(operand.mType); + EmitFrameOffset(*outResult); + } + EmitFrameOffset(operand); } @@ -468,7 +499,7 @@ CeOperand CeBuilder::FrameAlloc(BeType* type) return result; } -CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca) +CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImmediate) { if (value == NULL) return CeOperand(); @@ -530,11 +561,20 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca) CeOperand mcOperand; switch (constant->mType->mTypeCode) { - case BeTypeCode_Boolean: case BeTypeCode_Int8: case BeTypeCode_Int16: case BeTypeCode_Int32: - case BeTypeCode_Int64: + case BeTypeCode_Int64: + if (allowImmediate) + { + CeOperand result; + result.mKind = CeOperandKind_Immediate; + result.mImmediate = constant->mInt32; + result.mType = constant->mType; + return result; + } + + case BeTypeCode_Boolean: case BeTypeCode_Double: dataPtr = &constant->mUInt64; dataSize = constant->mType->mSize; @@ -572,17 +612,25 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca) } } break; -// case BeTypeCode_Struct: -// case BeTypeCode_SizedArray: -// case BeTypeCode_Vector: -// mcOperand.mImmediate = constant->mInt64; -// mcOperand.mKind = CeOperandKind_Immediate_i64; -// break; + case BeTypeCode_Struct: + case BeTypeCode_SizedArray: + case BeTypeCode_Vector: + { + auto beType = constant->mType; + auto result = FrameAlloc(beType); + Emit(CeOp_Zero); + EmitFrameOffset(result); + Emit((int32)beType->mSize); + return result; + } + //mcOperand.mImmediate = constant->mInt64; + //mcOperand.mKind = CeOperandKind_Immediate_i64; + break; // default: // Fail("Unhandled constant type"); } - if (dataPtr != NULL) + if (dataSize != 0) { auto beType = constant->mType; auto result = FrameAlloc(beType); @@ -592,7 +640,13 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca) EmitFrameOffset(result); if (sizeClass == CeSizeClass_X) Emit((int32)dataSize); - Emit(dataPtr, dataSize); + if (dataPtr != 0) + Emit(dataPtr, dataSize); + else + { + for (int i = 0; i < dataSize; i++) + Emit((uint8)0); + } return result; } @@ -952,6 +1006,7 @@ void CeBuilder::Build() dupMethodInstance.mMethodProcessRequest = NULL; dupMethodInstance.mIsReified = true; dupMethodInstance.mHotMethod = NULL; + dupMethodInstance.mInCEMachine = false; // Only have the original one mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true); @@ -1147,6 +1202,24 @@ void CeBuilder::Build() case BeBinaryOpKind_Add: EmitBinaryOp(CeOp_Add_I8, CeOp_Add_F32, ceLHS, ceRHS, result); break; + case BeBinaryOpKind_Subtract: + EmitBinaryOp(CeOp_Sub_I8, CeOp_Sub_F32, ceLHS, ceRHS, result); + break; + case BeBinaryOpKind_Multiply: + EmitBinaryOp(CeOp_Mul_I8, CeOp_Mul_F32, ceLHS, ceRHS, result); + break; + case BeBinaryOpKind_SDivide: + EmitBinaryOp(CeOp_SDiv_I8, CeOp_SDiv_F32, ceLHS, ceRHS, result); + break; + case BeBinaryOpKind_UDivide: + EmitBinaryOp(CeOp_UDiv_I8, CeOp_InvalidOp, ceLHS, ceRHS, result); + break; + case BeBinaryOpKind_SModulus: + EmitBinaryOp(CeOp_SMod_I8, CeOp_SMod_F32, ceLHS, ceRHS, result); + break; + case BeBinaryOpKind_UModulus: + EmitBinaryOp(CeOp_UMod_I8, CeOp_InvalidOp, ceLHS, ceRHS, result); + break; default: Fail("Invalid binary op"); } @@ -1274,6 +1347,16 @@ void CeBuilder::Build() iOp = CeOp_Cmp_SLT_I8; fOp = CeOp_Cmp_SLT_F32; break; + case BeCmpKind_ULT: + iOp = CeOp_Cmp_ULT_I8; + break; + case BeCmpKind_SLE: + iOp = CeOp_Cmp_SLE_I8; + fOp = CeOp_Cmp_SLE_F32; + break; + case BeCmpKind_ULE: + iOp = CeOp_Cmp_ULE_I8; + break; } if (iOp == CeOp_InvalidOp) @@ -1299,6 +1382,128 @@ void CeBuilder::Build() // mcInst->mResult = result; } break; + case BeGEPInst::TypeId: + { + auto castedInst = (BeGEPInst*)inst; + + auto mcVal = GetOperand(castedInst->mPtr); + auto mcIdx0 = GetOperand(castedInst->mIdx0, false, true); + + BePointerType* ptrType = (BePointerType*)mcVal.mType; + BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer); + + result = mcVal; + if (castedInst->mIdx1 != NULL) + { + // We assume we never do both an idx0 and idx1 at once. Fix if we change that. + BF_ASSERT(castedInst->mIdx0); + + auto mcIdx1 = GetOperand(castedInst->mIdx1); + if (!mcIdx1.IsImmediate()) + { + // This path is used when we have a const array that gets indexed by a non-const index value +// if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray) +// { +// auto arrayType = (BeSizedArrayType*)ptrType->mElementType; +// +// auto elementPtrType = mModule->mContext->GetPointerTo(arrayType->mElementType); +// +// auto ptrValue = AllocVirtualReg(elementPtrType); +// auto ptrInfo = GetVRegInfo(ptrValue); +// ptrInfo->mIsExpr = true; +// ptrInfo->mRelTo = result; +// CreateDefineVReg(ptrValue); +// result = ptrValue; +// +// BeMCOperand mcRelOffset; +// int relScale = 1; +// if (mcIdx1.IsImmediate()) +// { +// mcRelOffset = BeMCOperand::FromImmediate(mcIdx1.mImmediate * arrayType->mElementType->mSize); +// } +// else +// { +// mcRelOffset = mcIdx1; +// relScale = arrayType->mElementType->mSize; +// } +// +// result = AllocRelativeVirtualReg(elementPtrType, result, mcRelOffset, relScale); +// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use +// CreateDefineVReg(result); +// //TODO: Always correct? +// result.mKind = BeMCOperandKind_VReg; +// +// } +// else +// SoftFail("Invalid GEP", inst->mDbgLoc); + Fail("Invalid GEP"); + } + else + { + BF_ASSERT(mcIdx1.IsImmediate()); + int byteOffset = 0; + BeType* elementType = NULL; + if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct) + { + BeStructType* structType = (BeStructType*)ptrType->mElementType; + auto& structMember = structType->mMembers[mcIdx1.mImmediate]; + elementType = structMember.mType; + byteOffset = structMember.mByteOffset; + } + else if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray) + { + auto arrayType = (BeSizedArrayType*)ptrType->mElementType; + elementType = arrayType->mElementType; + byteOffset = mcIdx1.mImmediate * elementType->mSize; + } + else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector) + { + auto arrayType = (BeVectorType*)ptrType->mElementType; + elementType = arrayType->mElementType; + byteOffset = mcIdx1.mImmediate * elementType->mSize; + } + else + { + Fail("Invalid gep target"); + } + + auto elementPtrType = beModule->mContext->GetPointerTo(elementType); + + + + //result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1); + // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use + //CreateDefineVReg(result); + //result.mKind = BeMCOperandKind_VReg; + } + } + else + { + // It's temping to do a (IsNonZero) precondition, but if we make a reference to a VReg that is NOT in Addr form, + // then this will encode that so we will know we need to do a Load on that value at the Def during legalization + + Fail("Unhandled gep"); + +// BeMCOperand mcRelOffset; +// int relScale = 1; +// if (mcIdx0.IsImmediate()) +// { +// mcRelOffset = BeMCOperand::FromImmediate(mcIdx0.mImmediate * ptrType->mElementType->mSize); +// } +// else +// { +// mcRelOffset = mcIdx0; +// relScale = ptrType->mElementType->mSize; +// } +// +// result = AllocRelativeVirtualReg(ptrType, result, mcRelOffset, relScale); +// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use +// CreateDefineVReg(result); +// //TODO: Always correct? +// result.mKind = BeMCOperandKind_VReg; + } + } + break; case BeBrInst::TypeId: { auto castedInst = (BeBrInst*)inst; @@ -1373,7 +1578,7 @@ void CeBuilder::Build() bool isVarArg = false; bool useAltArgs = false; - SizedArray args; + //SizedArray args; int callIdx = -1; @@ -1394,6 +1599,13 @@ void CeBuilder::Build() callIdx = *callIdxPtr; + for (int argIdx = (int)castedInst->mArgs.size() - 1; argIdx >= 0; argIdx--) + { + auto& arg = castedInst->mArgs[argIdx]; + auto ceArg = GetOperand(arg.mValue); + EmitSizedOp(CeOp_Push_8, ceArg, NULL, true); + } + int stackAdjust = 0; auto beFuncType = beFunction->GetFuncType(); @@ -1407,6 +1619,12 @@ void CeBuilder::Build() Emit(CeOp_Call); Emit((int32)callIdx); + if (beFuncType->mReturnType->mSize > 0) + { + result = FrameAlloc(beFuncType->mReturnType); + EmitSizedOp(CeOp_Pop_8, result, NULL, true); + } + if (stackAdjust > 0) { Emit(CeOp_AdjustSP); @@ -1497,6 +1715,8 @@ CeMachine::CeMachine(BfCompiler* compiler) mCeModule = NULL; mStackMin = NULL; mRevision = 0; + mCurTargetSrc = NULL; + mCurModule = NULL; } CeMachine::~CeMachine() @@ -1504,6 +1724,11 @@ CeMachine::~CeMachine() delete mCeModule; } +void CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) +{ + mCurModule->Fail(str, mCurTargetSrc); +} + void CeMachine::Init() { mCeModule = new BfModule(mCompiler->mContext, "__constEval"); @@ -1535,8 +1760,12 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance) { auto itr = mFunctions.Find(methodInstance); auto ceFunction = itr->mValue; - mNamedFunctionMap.Remove(ceFunction->mName); - mFunctions.Remove(itr); + BF_ASSERT(itr != mFunctions.end()); + if (itr != mFunctions.end()) + { + mNamedFunctionMap.Remove(ceFunction->mName); + mFunctions.Remove(itr); + } } int CeMachine::GetConstantSize(BfConstant* constant) @@ -1607,6 +1836,12 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant) return; } } +#define CE_CHECKSTACK() \ + if (stackPtr < mStackMin) \ + { \ + _Fail("Stack overflow"); \ + return false; \ + } #define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1) #define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1)) @@ -1636,27 +1871,50 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant) auto val = CE_GETFRAME(TFROM); \ result = (TTO)val; \ } -#define CE_MOVE(T) \ +#define CEOP_MOVE(T) \ { \ auto val = CE_GETFRAME(T); \ auto& ptr = CE_GETFRAME(T); \ ptr = val; \ } - -bool CeMachine::Execute() -{ - uint8* memStart = &mMemory[0]; - uint8* framePtr; - uint8* instPtr; - uint8* stackPtr; - // - { - auto& ceFrame = mCallStack.back(); - instPtr = ceFrame.mInstPtr; - stackPtr = ceFrame.mStackPtr; - framePtr = ceFrame.mFramePtr; - framePtr = mCallStack.back().mFramePtr; +#define CEOP_PUSH(T) \ + { \ + stackPtr -= sizeof(T); \ + auto val = CE_GETFRAME(T); \ + *((T*)stackPtr) = val; \ + CE_CHECKSTACK(); \ } +#define CEOP_POP(T) \ + { \ + auto& result = CE_GETFRAME(T); \ + result = *((T*)stackPtr); \ + stackPtr += sizeof(T); \ + } + +bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr) +{ + CeFunction* ceFunction = startFunction; + uint8* memStart = &mMemory[0]; + uint8* instPtr = &ceFunction->mCode[0]; + uint8* stackPtr = startStackPtr; + uint8* framePtr = startFramePtr; + + auto _GetCurFrame = [&]() + { + CeFrame ceFrame; + ceFrame.mFunction = ceFunction; + ceFrame.mFramePtr = framePtr; + ceFrame.mStackPtr = stackPtr; + ceFrame.mInstPtr = instPtr; + return ceFrame; + }; + + auto _Fail = [&](const StringImpl& error) + { + Fail(_GetCurFrame(), error); + }; + + int callCount = 0; while (true) { @@ -1665,15 +1923,16 @@ bool CeMachine::Execute() { case CeOp_Ret: { + if (mCallStack.mSize == 0) + return true; + auto& ceFrame = mCallStack.back(); + ceFunction = ceFrame.mFunction; instPtr = ceFrame.mInstPtr; stackPtr = ceFrame.mStackPtr; framePtr = ceFrame.mFramePtr; - mCallStack.pop_back(); - - if (mCallStack.mSize == 0) - return true; + mCallStack.pop_back(); } break; case CeOp_Jmp: @@ -1705,6 +1964,13 @@ bool CeMachine::Execute() result = addr - memStart; } break; + case CeOp_Zero: + { + auto resultPtr = &CE_GETFRAME(uint8); + int32 constSize = CE_GETINST(int32); + memset(resultPtr, 0, constSize); + } + break; case CeOp_Const_8: { auto& result = CE_GETFRAME(int8); @@ -1749,18 +2015,93 @@ bool CeMachine::Execute() } result = *(uint32*)(memStart + ceAddr); } - break; + break; case CeOp_Move_8: - CE_MOVE(int8); + CEOP_MOVE(int8); break; case CeOp_Move_16: - CE_MOVE(int16); + CEOP_MOVE(int16); break; case CeOp_Move_32: - CE_MOVE(int32); + CEOP_MOVE(int32); break; case CeOp_Move_64: - CE_MOVE(int64); + CEOP_MOVE(int64); + break; + case CeOp_Move_X: + { + int32 size = CE_GETINST(int32); + auto valPtr = &CE_GETFRAME(uint8); + auto destPtr = &CE_GETFRAME(uint8); + memcpy(destPtr, valPtr, size); + } + break; + case CeOp_Push_8: + CEOP_PUSH(int8); + break; + case CeOp_Push_16: + CEOP_PUSH(int16); + break; + case CeOp_Push_32: + CEOP_PUSH(int32); + break; + case CeOp_Push_64: + CEOP_PUSH(int64); + break; + case CeOp_Pop_8: + CEOP_POP(int8); + break; + case CeOp_Pop_16: + CEOP_POP(int16); + break; + case CeOp_Pop_32: + CEOP_POP(int32); + break; + case CeOp_Pop_64: + CEOP_POP(int64); + break; + case CeOp_AdjustSP: + { + int32 adjust = CE_GETINST(int32); + stackPtr += adjust; + } + break; + case CeOp_Call: + { + callCount++; + + int32 callIdx = CE_GETINST(int32); + auto& callEntry = ceFunction->mCallTable[callIdx]; + if (callEntry.mBindRevision != mRevision) + { + callEntry.mFunction = NULL; + mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction); + callEntry.mBindRevision = mRevision; + } + + if (callEntry.mFunction == NULL) + { + _Fail("Unable to locate function entry"); + break; + } + +// if (callEntry.mFunction->mName.Contains("__static_dump")) +// { +// int32 val = *(int32*)(stackPtr); +// OutputDebugStrF("__static_dump: %d\n", val); +// } + + if (callEntry.mFunction != NULL) + { + mCallStack.Add(_GetCurFrame()); + + ceFunction = callEntry.mFunction; + framePtr = stackPtr; + stackPtr -= ceFunction->mFrameSize; + instPtr = &ceFunction->mCode[0]; + CE_CHECKSTACK(); + } + } break; case CeOp_Conv_I32_I64: CE_CAST(int32, int64); @@ -1771,12 +2112,36 @@ bool CeMachine::Execute() case CeOp_Add_I64: CEOP_BIN(+, int64); break; + case CeOp_Sub_I32: + CEOP_BIN(-, int32); + break; + case CeOp_Sub_I64: + CEOP_BIN(-, int64); + break; + case CeOp_Mul_I32: + CEOP_BIN(*, int32); + break; + case CeOp_Mul_I64: + CEOP_BIN(*, int64); + break; case CeOp_Cmp_EQ_I32: CEOP_CMP(==, int32); break; case CeOp_Cmp_SLT_I32: CEOP_CMP(<, int32); break; + case CeOp_Cmp_ULT_I32: + CEOP_CMP(<, uint32); + break; + case CeOp_Cmp_SLE_I32: + CEOP_CMP(<=, int32); + break; + case CeOp_Cmp_SLE_I64: + CEOP_CMP(<= , int64); + break; + case CeOp_Cmp_ULE_I32: + CEOP_CMP(<=, uint32); + break; case CeOp_Neg_I32: CEOP_UNARY(-, int32); break; @@ -1784,7 +2149,7 @@ bool CeMachine::Execute() CEOP_UNARY(-, int64); break; default: - BF_FATAL("CeMachine op failure"); + _Fail("Unhandled op"); return false; } } @@ -1829,12 +2194,13 @@ void CeMachine::ProcessWorkQueue() } } -CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance) +CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, bool& added) { CeFunction** functionValuePtr = NULL; CeFunction* ceFunction = NULL; if (mFunctions.TryAdd(methodInstance, NULL, &functionValuePtr)) { + added = true; auto module = methodInstance->GetOwner()->mModule; BF_ASSERT(!methodInstance->mInCEMachine); @@ -1852,12 +2218,13 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance) void CeMachine::QueueMethod(BfMethodInstance* methodInstance) { - auto ceFunction = GetFunction(methodInstance); - if (!ceFunction->mInitialized) + bool added = false; + auto ceFunction = GetFunction(methodInstance, added); + if (added) mWorkQueue.Add(ceFunction); } -BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags) +BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags) { // for (int argIdx = 0; argIdx < (int)args.size(); argIdx++) // { @@ -1869,6 +2236,9 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, // DISABLED return BfTypedValue(); + SetAndRestoreValue prevTargetSrc(mCurTargetSrc, targetSrc); + SetAndRestoreValue prevModule(mCurModule, module); + BF_ASSERT(mCallStack.IsEmpty()); auto methodDef = methodInstance->mMethodDef; @@ -1878,7 +2248,8 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, return BfTypedValue(); } - CeFunction* ceFunction = GetFunction(methodInstance); + bool added = false; + CeFunction* ceFunction = GetFunction(methodInstance, added); if (!ceFunction->mInitialized) { PrepareFunction(ceFunction); @@ -1914,14 +2285,7 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, retPtr = stackPtr; } - CeFrame ceFrame; - ceFrame.mFunction = ceFunction; - ceFrame.mFramePtr = stackPtr; - ceFrame.mStackPtr = stackPtr - ceFunction->mFrameSize; - ceFrame.mInstPtr = &ceFunction->mCode[0]; - mCallStack.Add(ceFrame); - - bool success = Execute(); + bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr); mCallStack.Clear(); diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 0ffb3e70..b3a579cb 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -49,20 +49,32 @@ enum CeOp : int16 CeOp_FrameAddr32, CeOp_FrameAddr64, + CeOp_Zero, CEOP_SIZED(Const), CEOP_SIZED(Load), - CEOP_SIZED(Store), + CEOP_SIZED(Store), CEOP_SIZED(Move), CEOP_SIZED(Push), - + CEOP_SIZED(Pop), + CeOp_AdjustSP, CeOp_Call, CeOp_Conv_I32_I64, - CEOP_SIZED_NUMERIC_PLUSF(Add), + CEOP_SIZED_NUMERIC_PLUSF(AddConst), + CEOP_SIZED_NUMERIC_PLUSF(Add), + CEOP_SIZED_NUMERIC_PLUSF(Sub), + CEOP_SIZED_NUMERIC_PLUSF(Mul), + CEOP_SIZED_NUMERIC_PLUSF(SDiv), + CEOP_SIZED_NUMERIC(UDiv), + CEOP_SIZED_NUMERIC_PLUSF(SMod), + CEOP_SIZED_NUMERIC(UMod), CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ), CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT), + CEOP_SIZED_NUMERIC(Cmp_ULT), + CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLE), + CEOP_SIZED_NUMERIC(Cmp_ULE), CEOP_SIZED_NUMERIC_PLUSF(Neg), @@ -127,6 +139,7 @@ enum CeOperandKind CeOperandKind_FrameOfs, CeOperandKind_AllocaAddr, CeOperandKind_Block, + CeOperandKind_Immediate }; class CeOperand @@ -137,6 +150,7 @@ public: { int mFrameOfs; int mBlockIdx; + int mImmediate; }; BeType* mType; @@ -152,6 +166,11 @@ public: { return mKind != CeOperandKind_None; } + + bool IsImmediate() + { + return mKind == CeOperandKind_Immediate; + } }; #define BF_CE_STACK_SIZE 1024*1024 @@ -164,6 +183,8 @@ enum CeOperandInfoKind CEOI_IMM16, CEOI_IMM32, CEOI_IMM64, + CEOI_IMMF32, + CEOI_IMMF64, CEOI_IMM_VAR, CEOI_JMPREL }; @@ -254,7 +275,7 @@ public: void Fail(const StringImpl& error); CeOperand FrameAlloc(BeType* type); - CeOperand GetOperand(BeValue* value, bool allowAlloca = false); + CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false); CeSizeClass GetSizeClass(int size); int GetCodePos(); @@ -309,25 +330,30 @@ public: uint8* mStackMin; Array mWorkQueue; + BfAstNode* mCurTargetSrc; + BfModule* mCurModule; + public: CeMachine(BfCompiler* compiler); ~CeMachine(); + void Fail(const CeFrame& curFrame, const StringImpl& error); + void Init(); void RemoveMethod(BfMethodInstance* methodInstance); int GetConstantSize(BfConstant* constant); void WriteConstant(uint8* ptr, BfConstant* constant); void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); - bool Execute(); + bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr); void PrepareFunction(CeFunction* methodInstance); - void ProcessWorkQueue(); - CeFunction* GetFunction(BfMethodInstance* methodInstance); + void ProcessWorkQueue(); + CeFunction* GetFunction(BfMethodInstance* methodInstance, bool& added); public: void CompileStarted(); void QueueMethod(BfMethodInstance* methodInstance); - BfTypedValue Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags); + BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags); }; NS_BF_END