1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Expanding CTFE

This commit is contained in:
Brian Fiete 2020-12-14 03:50:28 -08:00
parent 577e199dcd
commit 6d058ba59c
9 changed files with 662 additions and 263 deletions

View file

@ -1009,7 +1009,7 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& test
} }
BfExprEvaluator exprEvaluator(bfModule); BfExprEvaluator exprEvaluator(bfModule);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
bfModule->mBfIRBuilder->CreateBr(testHeadBlock); bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
} }

View file

@ -645,6 +645,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
dupMethodInstance.mMethodProcessRequest = NULL; dupMethodInstance.mMethodProcessRequest = NULL;
dupMethodInstance.mIsReified = true; dupMethodInstance.mIsReified = true;
dupMethodInstance.mHotMethod = NULL; dupMethodInstance.mHotMethod = NULL;
dupMethodInstance.mInCEMachine = false; // Only have the original one
BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules
{ {

View file

@ -4801,7 +4801,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc); mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
} }
BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, bool isTailCall) BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, bool isTailCall)
{ {
// static int sCallIdx = 0; // static int sCallIdx = 0;
// if (!mModule->mCompiler->mIsResolveOnly) // if (!mModule->mCompiler->mIsResolveOnly)
@ -4990,7 +4990,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
} }
else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0) 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) if (constRet)
return constRet; return constRet;
} }
@ -6632,7 +6632,7 @@ SplatArgs(lookupVal, irArgs);
} }
auto func = moduleMethodInstance.mFunc; 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)) if ((result.mType != NULL) && (result.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
mModule->Fail("Method return type reference failed to resolve", targetSrc); mModule->Fail("Method return type reference failed to resolve", targetSrc);
return result; return result;
@ -9144,7 +9144,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, NULL); exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, NULL);
if (addFunctionBindResult.mMethodInstance != NULL) if (addFunctionBindResult.mMethodInstance != NULL)
CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs); CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs);
isFirstAdd = false; isFirstAdd = false;
} }
@ -9162,7 +9162,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
PushArg(argValue, irArgs); PushArg(argValue, irArgs);
for (int argIdx = (int)irArgs.size(); argIdx < (int)addFunctionBindResult.mIRArgs.size(); argIdx++) for (int argIdx = (int)irArgs.size(); argIdx < (int)addFunctionBindResult.mIRArgs.size(); argIdx++)
irArgs.Add(addFunctionBindResult.mIRArgs[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); 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)); BF_ASSERT(appendSizeTypedValue.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr));
} }
appendSizeValue = appendSizeTypedValue.mValue; appendSizeValue = appendSizeTypedValue.mValue;
@ -13187,7 +13187,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
SizedArray<BfIRValue, 1> irArgs; SizedArray<BfIRValue, 1> irArgs;
irArgs.push_back(mResult.mValue); 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()) if (!typeInstance->IsValuelessType())
bindResult.mIRArgs.Insert(0, mResult.mValue); 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 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 != NULL)
{ {
if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly)) if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
@ -16794,7 +16794,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
PushArg(convVal, args); PushArg(convVal, args);
if (methodInstance) if (methodInstance)
CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args); CreateCall(assignExpr, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
mPropDef = NULL; mPropDef = NULL;
mResult = convVal; mResult = convVal;
@ -16868,7 +16868,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
exprEvaluator.PushThis(assignExpr->mLeft, leftValue, moduleMethodInstance.mMethodInstance, args); exprEvaluator.PushThis(assignExpr->mLeft, leftValue, moduleMethodInstance.mMethodInstance, args);
exprEvaluator.PushArg(rightValue, args); exprEvaluator.PushArg(rightValue, args);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args); exprEvaluator.CreateCall(assignExpr, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args);
convVal = leftValue; convVal = leftValue;
handled = true; handled = true;
break; break;
@ -19068,7 +19068,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
} }
PushArg(writeToProp, args); PushArg(writeToProp, args);
CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, false, args); CreateCall(opToken, methodInstance.mMethodInstance, methodInstance.mFunc, false, args);
} }
} }

View file

@ -420,7 +420,7 @@ public:
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL); BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
void AddCallDependencies(BfMethodInstance* methodInstance); void AddCallDependencies(BfMethodInstance* methodInstance);
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc); void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
BfTypedValue CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false); BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false);
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, bool skipThis = false); BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, bool skipThis = false);
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target); BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
void MakeBaseConcrete(BfTypedValue& typedValue); void MakeBaseConcrete(BfTypedValue& typedValue);

View file

@ -694,7 +694,7 @@ public:
{ {
BF_ASSERT(calcAppendMethodModule.mFunc); 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)); BF_ASSERT(subDependSize.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr));
} }
if (subDependSize) if (subDependSize)
@ -9211,7 +9211,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
SizedArray<BfIRValue, 4> irArgs; SizedArray<BfIRValue, 4> irArgs;
irArgs.push_back(objectParam); irArgs.push_back(objectParam);
irArgs.push_back(GetConstValue32(targetType->mTypeId)); 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 resultType = ResolveTypeDef(mSystem->mTypeBool);
auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType)); auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType));
irb->CreateCondBr(cmpResult, trueBlock, falseBlock); irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
@ -14788,7 +14788,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
calcAppendArgs = bindResult.mIRArgs; calcAppendArgs = bindResult.mIRArgs;
} }
BF_ASSERT(calcAppendMethodModule.mFunc); 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)); BF_ASSERT(appendSizeTypedValue.mType == GetPrimitiveType(BfTypeCode_IntPtr));
@ -15648,7 +15648,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
SizedArray<BfIRValue, 1> irArgs; SizedArray<BfIRValue, 1> irArgs;
exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, 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; calledCtorNoBody = true;
} }
@ -16131,7 +16131,7 @@ void BfModule::EmitEnumToStringBody()
SizedArray<BfIRValue, 2> args; SizedArray<BfIRValue, 2> args;
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
args.Add(caseStr); 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(); auto payloadType = fieldInstance.mResolvedType->ToTypeInstance();
BF_ASSERT(payloadType->IsTuple()); BF_ASSERT(payloadType->IsTuple());
@ -16150,7 +16150,7 @@ void BfModule::EmitEnumToStringBody()
exprEvaluator.PushThis(NULL, payload, toStringMethod.mMethodInstance, irArgs); exprEvaluator.PushThis(NULL, payload, toStringMethod.mMethodInstance, irArgs);
stringDestVal = LoadValue(stringDestAddr); stringDestVal = LoadValue(stringDestAddr);
irArgs.Add(stringDestVal.mValue); irArgs.Add(stringDestVal.mValue);
exprEvaluator.CreateCall(toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs); exprEvaluator.CreateCall(NULL, toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs);
} }
mBfIRBuilder->CreateBr(endBlock); mBfIRBuilder->CreateBr(endBlock);
@ -16186,7 +16186,7 @@ void BfModule::EmitEnumToStringBody()
auto stringDestVal = LoadValue(stringDestAddr); auto stringDestVal = LoadValue(stringDestAddr);
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
args.Add(mBfIRBuilder->CreateLoad(strVal)); 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->CreateBr(endBlock);
mBfIRBuilder->AddBlock(noMatchBlock); mBfIRBuilder->AddBlock(noMatchBlock);
@ -16197,7 +16197,7 @@ void BfModule::EmitEnumToStringBody()
args.Add(int64Val); args.Add(int64Val);
stringDestVal = LoadValue(stringDestAddr); stringDestVal = LoadValue(stringDestAddr);
args.Add(stringDestVal.mValue); 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->CreateBr(endBlock);
mBfIRBuilder->AddBlock(endBlock); mBfIRBuilder->AddBlock(endBlock);
@ -16226,7 +16226,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef); auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
args.Add(mBfIRBuilder->CreateConst(BfTypeCode_Char8, (int)c)); 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; int fieldIdx = 0;
@ -16254,7 +16254,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef); auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
args.Add(commaStr); args.Add(commaStr);
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
} }
fieldIdx++; fieldIdx++;
@ -16300,7 +16300,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]); auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
stringDestVal = LoadValue(stringDestVal); stringDestVal = LoadValue(stringDestVal);
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
exprEvaluator.CreateCall(toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args); exprEvaluator.CreateCall(NULL, toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args);
continue; continue;
} }
@ -16324,7 +16324,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef); auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue); args.Add(stringDestVal.mValue);
args.Add(strVal); args.Add(strVal);
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args); exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
continue; continue;
} }
@ -16389,7 +16389,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark
val = mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(mContext->mBfObjectType)); val = mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(mContext->mBfObjectType));
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
args.push_back(val); 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())) else if ((fieldTypeInst->IsComposite()) && (!fieldTypeInst->IsTypedPrimitive()))
{ {
@ -16403,7 +16403,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark
markVal = Cast(NULL, markVal, methodOwner); markVal = Cast(NULL, markVal, methodOwner);
exprEvaluator.PushThis(NULL, markVal, markMemberMethodInstance.mMethodInstance, args); 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); BfExprEvaluator exprEvaluator(this);
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
exprEvaluator.PushThis(chainedMethodInst->mMethodDef->GetRefNode(), GetThis(), chainedMethodInst, 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); mBfIRBuilder->PopulateType(methodInstance->mReturnType);
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true); auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
exprEvaluator.mReceivingValue = &returnType; 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 BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
} }
else else
{ {
mBfIRBuilder->PopulateType(methodInstance->mReturnType); 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()) if (mCurMethodInstance->mReturnType->IsValueType())
retVal = LoadValue(retVal); retVal = LoadValue(retVal);
CreateReturn(retVal.mValue); CreateReturn(retVal.mValue);
@ -21680,107 +21680,109 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
auto checkMethod = nextMethod; auto checkMethod = nextMethod;
nextMethod = nextMethod->mNextWithSameName; nextMethod = nextMethod->mNextWithSameName;
if ((checkMethod != methodDef) && (typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault != NULL)) if (checkMethod == methodDef)
{ continue;
auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) && auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
(checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) && if (checkMethodInstance == NULL)
(checkMethod->mIsMutating == methodDef->mIsMutating) && continue;
(CompareMethodSignatures(checkMethodInstance, mCurMethodInstance)))
{
bool canChain = false;
if ((methodDef->mParams.empty()) && if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) &&
(checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic)) (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; 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; methodInstance->mChainType = BfMethodChainType_ChainHead;
bool isWorse; checkMethodInstance->mChainType = BfMethodChainType_ChainMember;
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;
}
} }
else else
{ {
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType)) checkMethodInstance->mChainType = BfMethodChainType_ChainHead;
continue; methodInstance->mChainType = BfMethodChainType_ChainMember;
}
bool silentlyAllow = false; }
bool extensionWarn = false; else
if (checkMethod->mDeclaringType != methodDef->mDeclaringType) {
{ if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
if (typeInstance->IsInterface()) continue;
{
if (methodDef->mIsOverride) 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; silentlyAllow = true;
else if (methodDef->mIsNew)
silentlyAllow = true;
else
extensionWarn = true;
} }
else else
{ silentlyAllow = true;
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;
}
} }
}
if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse)) if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
silentlyAllow = true; silentlyAllow = true;
if (!silentlyAllow) if (!silentlyAllow)
{
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
{ {
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator)) auto refNode = methodDef->GetRefNode();
{ BfError* bfError;
auto refNode = methodDef->GetRefNode(); if (extensionWarn)
BfError* bfError; bfError = Warn(BfWarning_CS0114_MethodHidesInherited,
if (extensionWarn) 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'.",
bfError = Warn(BfWarning_CS0114_MethodHidesInherited, checkMethod->mDeclaringType->mProject->mName.c_str()), refNode);
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'.", else
checkMethod->mDeclaringType->mProject->mName.c_str()), refNode); bfError = Fail("Method already declared with the same parameter types", refNode, true);
else if (bfError != NULL)
bfError = Fail("Method already declared with the same parameter types", refNode, true); mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
}
} }
} }
} }
} }
} }
} }

View file

@ -4370,103 +4370,109 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount);
// Pass 2 // Def passes. First non-overrides then overrides (for in-place overrides in methods)
for (auto methodDef : typeDef->mMethods) 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) && auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx];
(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl))
{
BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind);
continue;
}
if (methodDef->mMethodType == BfMethodType_Init) if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
continue; (methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl))
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) BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind);
{ continue;
auto attrTypeInst = attr.mType->ToTypeInstance(); }
auto attrCustomAttributes = attrTypeInst->mCustomAttributes;
if (attrCustomAttributes == NULL)
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.mType->ToTypeInstance()->mTypeDef == mCompiler->mAttributeUsageAttributeTypeDef)
if (attrAttr.mCtorArgs.size() < 2) {
continue; // Check for Flags arg
auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]); if (attrAttr.mCtorArgs.size() < 2)
if (constant == NULL) continue;
continue; auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]);
if (constant->mTypeCode == BfTypeCode_Boolean) if (constant == NULL)
continue; continue;
if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0) if (constant->mTypeCode == BfTypeCode_Boolean)
forceMethodImpl = true; continue;
if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0)
forceMethodImpl = true;
}
} }
} }
} }
}
if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest) if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest)
{
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef)))
{ {
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()) if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf()))
mContext->mScratchModule->PopulateType(typeInstance, BfPopulateType_Data); SlotInterfaceMethod(methodInstance);
// Reify method }
mContext->mScratchModule->GetMethodInstance(typeInstance, methodDef, BfTypeVector()); else if (!methodDef->IsEmptyPartial())
BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingReference); {
methodUsedVirtually = SlotVirtualMethod(methodInstance, &ambiguityContext);
} }
}
// This is important for reducing latency of autocomplete popup, but it's important we don't allow the autocomplete
bool methodUsedVirtually = false; // thread to cause any reentry issues by re-populating a type at an "inopportune time". We do allow certain
if (typeInstance->IsInterface()) // reentries in PopulateType, but not when we're resolving fields (for example)
{ if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField))
if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf())) {
SlotInterfaceMethod(methodInstance); disableYield.Release();
} mSystem->CheckLockYield();
else if (!methodDef->IsEmptyPartial()) disableYield.Acquire();
{ }
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();
} }
} }
@ -11031,7 +11037,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
exprEvaluator.PushArg(castedFromValue, 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())) if ((operatorOut.mType != NULL) && (operatorOut.mType->IsSelf()))
{ {
BF_ASSERT(IsInGeneric()); BF_ASSERT(IsInGeneric());

View file

@ -760,7 +760,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz
} }
BfExprEvaluator expressionEvaluator(this); 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) if ((flags & BfDeferredBlockFlag_DoNullChecks) != 0)
{ {
@ -3956,7 +3956,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
BF_ASSERT(methodInstance->mMethodDef->mName == "~this"); BF_ASSERT(methodInstance->mMethodDef->mName == "~this");
SizedArray<BfIRValue, 4> llvmArgs; SizedArray<BfIRValue, 4> llvmArgs;
llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType))); 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)) if ((deleteStmt->mTargetTypeToken != NULL) && (!isAppendDelete))
@ -5998,7 +5998,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner()); auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner());
exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args); 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);
} }
} }

View file

@ -16,6 +16,13 @@ struct CeOpInfo
CeOperandInfoKind mOperandC; 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) \ #define CEOPINFO_SIZED_2(OPNAME, OPINFOA, OPINFOB) \
{OPNAME##"_8", OPINFOA, OPINFOB}, \ {OPNAME##"_8", OPINFOA, OPINFOB}, \
{OPNAME##"_16", OPINFOA, OPINFOB}, \ {OPNAME##"_16", OPINFOA, OPINFOB}, \
@ -43,6 +50,11 @@ struct CeOpInfo
{OPNAME##"_I64", OPINFOA, OPINFOB}, \ {OPNAME##"_I64", OPINFOA, OPINFOB}, \
{OPNAME##"_F32", OPINFOA, OPINFOB}, \ {OPNAME##"_F32", OPINFOA, OPINFOB}, \
{OPNAME##"_F64", 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) \ #define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \
@ -60,6 +72,7 @@ static CeOpInfo gOpInfo[] =
{"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef}, {"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
{"FrameAddr32", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr32", CEOI_FrameRef, CEOI_FrameRef},
{"FrameAddr64", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr64", CEOI_FrameRef, CEOI_FrameRef},
{"Zero", CEOI_FrameRef, CEOI_IMM32},
{"Const_8", CEOI_FrameRef, CEOI_IMM8}, {"Const_8", CEOI_FrameRef, CEOI_IMM8},
{"Const_16", CEOI_FrameRef, CEOI_IMM16}, {"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("Store", CEOI_None, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_3("Move", 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_2("Push", CEOI_None, CEOI_FrameRef),
CEOPINFO_SIZED_1("Pop", CEOI_FrameRef),
{"AdjustSP", CEOI_None, CEOI_FrameRef}, {"AdjustSP", CEOI_None, CEOI_FrameRef},
{"Call", CEOI_None, CEOI_IMM32}, {"Call", CEOI_None, CEOI_IMM32},
{"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef}, {"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("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_EQ", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLT", 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}, //{"Cmp_SLT_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef},
CEOPINFO_SIZED_NUMERIC_PLUSF_2("Neg", 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); Emit(op);
if (outResult != NULL)
{
*outResult = FrameAlloc(operand.mType);
EmitFrameOffset(*outResult);
}
if (!isStdSize) if (!isStdSize)
{ {
if (!allowNonStdSize) if (!allowNonStdSize)
@ -454,6 +479,12 @@ void CeBuilder::EmitSizedOp(CeOp baseOp, const CeOperand& operand, CeOperand* ou
Emit((int32)operand.mType->mSize); Emit((int32)operand.mType->mSize);
} }
if (outResult != NULL)
{
*outResult = FrameAlloc(operand.mType);
EmitFrameOffset(*outResult);
}
EmitFrameOffset(operand); EmitFrameOffset(operand);
} }
@ -468,7 +499,7 @@ CeOperand CeBuilder::FrameAlloc(BeType* type)
return result; return result;
} }
CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca) CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImmediate)
{ {
if (value == NULL) if (value == NULL)
return CeOperand(); return CeOperand();
@ -530,11 +561,20 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
CeOperand mcOperand; CeOperand mcOperand;
switch (constant->mType->mTypeCode) switch (constant->mType->mTypeCode)
{ {
case BeTypeCode_Boolean:
case BeTypeCode_Int8: case BeTypeCode_Int8:
case BeTypeCode_Int16: case BeTypeCode_Int16:
case BeTypeCode_Int32: 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: case BeTypeCode_Double:
dataPtr = &constant->mUInt64; dataPtr = &constant->mUInt64;
dataSize = constant->mType->mSize; dataSize = constant->mType->mSize;
@ -572,17 +612,25 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
} }
} }
break; break;
// case BeTypeCode_Struct: case BeTypeCode_Struct:
// case BeTypeCode_SizedArray: case BeTypeCode_SizedArray:
// case BeTypeCode_Vector: case BeTypeCode_Vector:
// mcOperand.mImmediate = constant->mInt64; {
// mcOperand.mKind = CeOperandKind_Immediate_i64; auto beType = constant->mType;
// break; 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: // default:
// Fail("Unhandled constant type"); // Fail("Unhandled constant type");
} }
if (dataPtr != NULL) if (dataSize != 0)
{ {
auto beType = constant->mType; auto beType = constant->mType;
auto result = FrameAlloc(beType); auto result = FrameAlloc(beType);
@ -592,7 +640,13 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
EmitFrameOffset(result); EmitFrameOffset(result);
if (sizeClass == CeSizeClass_X) if (sizeClass == CeSizeClass_X)
Emit((int32)dataSize); 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; return result;
} }
@ -952,6 +1006,7 @@ void CeBuilder::Build()
dupMethodInstance.mMethodProcessRequest = NULL; dupMethodInstance.mMethodProcessRequest = NULL;
dupMethodInstance.mIsReified = true; dupMethodInstance.mIsReified = true;
dupMethodInstance.mHotMethod = NULL; dupMethodInstance.mHotMethod = NULL;
dupMethodInstance.mInCEMachine = false; // Only have the original one
mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true); mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true);
@ -1147,6 +1202,24 @@ void CeBuilder::Build()
case BeBinaryOpKind_Add: case BeBinaryOpKind_Add:
EmitBinaryOp(CeOp_Add_I8, CeOp_Add_F32, ceLHS, ceRHS, result); EmitBinaryOp(CeOp_Add_I8, CeOp_Add_F32, ceLHS, ceRHS, result);
break; 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: default:
Fail("Invalid binary op"); Fail("Invalid binary op");
} }
@ -1274,6 +1347,16 @@ void CeBuilder::Build()
iOp = CeOp_Cmp_SLT_I8; iOp = CeOp_Cmp_SLT_I8;
fOp = CeOp_Cmp_SLT_F32; fOp = CeOp_Cmp_SLT_F32;
break; 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) if (iOp == CeOp_InvalidOp)
@ -1299,6 +1382,128 @@ void CeBuilder::Build()
// mcInst->mResult = result; // mcInst->mResult = result;
} }
break; 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: case BeBrInst::TypeId:
{ {
auto castedInst = (BeBrInst*)inst; auto castedInst = (BeBrInst*)inst;
@ -1373,7 +1578,7 @@ void CeBuilder::Build()
bool isVarArg = false; bool isVarArg = false;
bool useAltArgs = false; bool useAltArgs = false;
SizedArray<BeValue*, 6> args; //SizedArray<BeValue*, 6> args;
int callIdx = -1; int callIdx = -1;
@ -1394,6 +1599,13 @@ void CeBuilder::Build()
callIdx = *callIdxPtr; 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; int stackAdjust = 0;
auto beFuncType = beFunction->GetFuncType(); auto beFuncType = beFunction->GetFuncType();
@ -1407,6 +1619,12 @@ void CeBuilder::Build()
Emit(CeOp_Call); Emit(CeOp_Call);
Emit((int32)callIdx); Emit((int32)callIdx);
if (beFuncType->mReturnType->mSize > 0)
{
result = FrameAlloc(beFuncType->mReturnType);
EmitSizedOp(CeOp_Pop_8, result, NULL, true);
}
if (stackAdjust > 0) if (stackAdjust > 0)
{ {
Emit(CeOp_AdjustSP); Emit(CeOp_AdjustSP);
@ -1497,6 +1715,8 @@ CeMachine::CeMachine(BfCompiler* compiler)
mCeModule = NULL; mCeModule = NULL;
mStackMin = NULL; mStackMin = NULL;
mRevision = 0; mRevision = 0;
mCurTargetSrc = NULL;
mCurModule = NULL;
} }
CeMachine::~CeMachine() CeMachine::~CeMachine()
@ -1504,6 +1724,11 @@ CeMachine::~CeMachine()
delete mCeModule; delete mCeModule;
} }
void CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{
mCurModule->Fail(str, mCurTargetSrc);
}
void CeMachine::Init() void CeMachine::Init()
{ {
mCeModule = new BfModule(mCompiler->mContext, "__constEval"); mCeModule = new BfModule(mCompiler->mContext, "__constEval");
@ -1535,8 +1760,12 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
{ {
auto itr = mFunctions.Find(methodInstance); auto itr = mFunctions.Find(methodInstance);
auto ceFunction = itr->mValue; auto ceFunction = itr->mValue;
mNamedFunctionMap.Remove(ceFunction->mName); BF_ASSERT(itr != mFunctions.end());
mFunctions.Remove(itr); if (itr != mFunctions.end())
{
mNamedFunctionMap.Remove(ceFunction->mName);
mFunctions.Remove(itr);
}
} }
int CeMachine::GetConstantSize(BfConstant* constant) int CeMachine::GetConstantSize(BfConstant* constant)
@ -1607,6 +1836,12 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
return; return;
} }
} }
#define CE_CHECKSTACK() \
if (stackPtr < mStackMin) \
{ \
_Fail("Stack overflow"); \
return false; \
}
#define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1) #define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1)
#define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 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); \ auto val = CE_GETFRAME(TFROM); \
result = (TTO)val; \ result = (TTO)val; \
} }
#define CE_MOVE(T) \ #define CEOP_MOVE(T) \
{ \ { \
auto val = CE_GETFRAME(T); \ auto val = CE_GETFRAME(T); \
auto& ptr = CE_GETFRAME(T); \ auto& ptr = CE_GETFRAME(T); \
ptr = val; \ ptr = val; \
} }
#define CEOP_PUSH(T) \
bool CeMachine::Execute() { \
{ stackPtr -= sizeof(T); \
uint8* memStart = &mMemory[0]; auto val = CE_GETFRAME(T); \
uint8* framePtr; *((T*)stackPtr) = val; \
uint8* instPtr; CE_CHECKSTACK(); \
uint8* stackPtr;
//
{
auto& ceFrame = mCallStack.back();
instPtr = ceFrame.mInstPtr;
stackPtr = ceFrame.mStackPtr;
framePtr = ceFrame.mFramePtr;
framePtr = mCallStack.back().mFramePtr;
} }
#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) while (true)
{ {
@ -1665,15 +1923,16 @@ bool CeMachine::Execute()
{ {
case CeOp_Ret: case CeOp_Ret:
{ {
if (mCallStack.mSize == 0)
return true;
auto& ceFrame = mCallStack.back(); auto& ceFrame = mCallStack.back();
ceFunction = ceFrame.mFunction;
instPtr = ceFrame.mInstPtr; instPtr = ceFrame.mInstPtr;
stackPtr = ceFrame.mStackPtr; stackPtr = ceFrame.mStackPtr;
framePtr = ceFrame.mFramePtr; framePtr = ceFrame.mFramePtr;
mCallStack.pop_back(); mCallStack.pop_back();
if (mCallStack.mSize == 0)
return true;
} }
break; break;
case CeOp_Jmp: case CeOp_Jmp:
@ -1705,6 +1964,13 @@ bool CeMachine::Execute()
result = addr - memStart; result = addr - memStart;
} }
break; break;
case CeOp_Zero:
{
auto resultPtr = &CE_GETFRAME(uint8);
int32 constSize = CE_GETINST(int32);
memset(resultPtr, 0, constSize);
}
break;
case CeOp_Const_8: case CeOp_Const_8:
{ {
auto& result = CE_GETFRAME(int8); auto& result = CE_GETFRAME(int8);
@ -1749,18 +2015,93 @@ bool CeMachine::Execute()
} }
result = *(uint32*)(memStart + ceAddr); result = *(uint32*)(memStart + ceAddr);
} }
break; break;
case CeOp_Move_8: case CeOp_Move_8:
CE_MOVE(int8); CEOP_MOVE(int8);
break; break;
case CeOp_Move_16: case CeOp_Move_16:
CE_MOVE(int16); CEOP_MOVE(int16);
break; break;
case CeOp_Move_32: case CeOp_Move_32:
CE_MOVE(int32); CEOP_MOVE(int32);
break; break;
case CeOp_Move_64: 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; break;
case CeOp_Conv_I32_I64: case CeOp_Conv_I32_I64:
CE_CAST(int32, int64); CE_CAST(int32, int64);
@ -1771,12 +2112,36 @@ bool CeMachine::Execute()
case CeOp_Add_I64: case CeOp_Add_I64:
CEOP_BIN(+, int64); CEOP_BIN(+, int64);
break; 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: case CeOp_Cmp_EQ_I32:
CEOP_CMP(==, int32); CEOP_CMP(==, int32);
break; break;
case CeOp_Cmp_SLT_I32: case CeOp_Cmp_SLT_I32:
CEOP_CMP(<, int32); CEOP_CMP(<, int32);
break; 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: case CeOp_Neg_I32:
CEOP_UNARY(-, int32); CEOP_UNARY(-, int32);
break; break;
@ -1784,7 +2149,7 @@ bool CeMachine::Execute()
CEOP_UNARY(-, int64); CEOP_UNARY(-, int64);
break; break;
default: default:
BF_FATAL("CeMachine op failure"); _Fail("Unhandled op");
return false; 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** functionValuePtr = NULL;
CeFunction* ceFunction = NULL; CeFunction* ceFunction = NULL;
if (mFunctions.TryAdd(methodInstance, NULL, &functionValuePtr)) if (mFunctions.TryAdd(methodInstance, NULL, &functionValuePtr))
{ {
added = true;
auto module = methodInstance->GetOwner()->mModule; auto module = methodInstance->GetOwner()->mModule;
BF_ASSERT(!methodInstance->mInCEMachine); BF_ASSERT(!methodInstance->mInCEMachine);
@ -1852,12 +2218,13 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance)
void CeMachine::QueueMethod(BfMethodInstance* methodInstance) void CeMachine::QueueMethod(BfMethodInstance* methodInstance)
{ {
auto ceFunction = GetFunction(methodInstance); bool added = false;
if (!ceFunction->mInitialized) auto ceFunction = GetFunction(methodInstance, added);
if (added)
mWorkQueue.Add(ceFunction); mWorkQueue.Add(ceFunction);
} }
BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags) BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags)
{ {
// for (int argIdx = 0; argIdx < (int)args.size(); argIdx++) // for (int argIdx = 0; argIdx < (int)args.size(); argIdx++)
// { // {
@ -1869,6 +2236,9 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
// DISABLED // DISABLED
return BfTypedValue(); return BfTypedValue();
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
BF_ASSERT(mCallStack.IsEmpty()); BF_ASSERT(mCallStack.IsEmpty());
auto methodDef = methodInstance->mMethodDef; auto methodDef = methodInstance->mMethodDef;
@ -1878,7 +2248,8 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
return BfTypedValue(); return BfTypedValue();
} }
CeFunction* ceFunction = GetFunction(methodInstance); bool added = false;
CeFunction* ceFunction = GetFunction(methodInstance, added);
if (!ceFunction->mInitialized) if (!ceFunction->mInitialized)
{ {
PrepareFunction(ceFunction); PrepareFunction(ceFunction);
@ -1914,14 +2285,7 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
retPtr = stackPtr; retPtr = stackPtr;
} }
CeFrame ceFrame; bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr);
ceFrame.mFunction = ceFunction;
ceFrame.mFramePtr = stackPtr;
ceFrame.mStackPtr = stackPtr - ceFunction->mFrameSize;
ceFrame.mInstPtr = &ceFunction->mCode[0];
mCallStack.Add(ceFrame);
bool success = Execute();
mCallStack.Clear(); mCallStack.Clear();

View file

@ -49,20 +49,32 @@ enum CeOp : int16
CeOp_FrameAddr32, CeOp_FrameAddr32,
CeOp_FrameAddr64, CeOp_FrameAddr64,
CeOp_Zero,
CEOP_SIZED(Const), CEOP_SIZED(Const),
CEOP_SIZED(Load), CEOP_SIZED(Load),
CEOP_SIZED(Store), CEOP_SIZED(Store),
CEOP_SIZED(Move), CEOP_SIZED(Move),
CEOP_SIZED(Push), CEOP_SIZED(Push),
CEOP_SIZED(Pop),
CeOp_AdjustSP, CeOp_AdjustSP,
CeOp_Call, CeOp_Call,
CeOp_Conv_I32_I64, 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_EQ),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT), 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), CEOP_SIZED_NUMERIC_PLUSF(Neg),
@ -127,6 +139,7 @@ enum CeOperandKind
CeOperandKind_FrameOfs, CeOperandKind_FrameOfs,
CeOperandKind_AllocaAddr, CeOperandKind_AllocaAddr,
CeOperandKind_Block, CeOperandKind_Block,
CeOperandKind_Immediate
}; };
class CeOperand class CeOperand
@ -137,6 +150,7 @@ public:
{ {
int mFrameOfs; int mFrameOfs;
int mBlockIdx; int mBlockIdx;
int mImmediate;
}; };
BeType* mType; BeType* mType;
@ -152,6 +166,11 @@ public:
{ {
return mKind != CeOperandKind_None; return mKind != CeOperandKind_None;
} }
bool IsImmediate()
{
return mKind == CeOperandKind_Immediate;
}
}; };
#define BF_CE_STACK_SIZE 1024*1024 #define BF_CE_STACK_SIZE 1024*1024
@ -164,6 +183,8 @@ enum CeOperandInfoKind
CEOI_IMM16, CEOI_IMM16,
CEOI_IMM32, CEOI_IMM32,
CEOI_IMM64, CEOI_IMM64,
CEOI_IMMF32,
CEOI_IMMF64,
CEOI_IMM_VAR, CEOI_IMM_VAR,
CEOI_JMPREL CEOI_JMPREL
}; };
@ -254,7 +275,7 @@ public:
void Fail(const StringImpl& error); void Fail(const StringImpl& error);
CeOperand FrameAlloc(BeType* type); 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); CeSizeClass GetSizeClass(int size);
int GetCodePos(); int GetCodePos();
@ -309,25 +330,30 @@ public:
uint8* mStackMin; uint8* mStackMin;
Array<CeFunction*> mWorkQueue; Array<CeFunction*> mWorkQueue;
BfAstNode* mCurTargetSrc;
BfModule* mCurModule;
public: public:
CeMachine(BfCompiler* compiler); CeMachine(BfCompiler* compiler);
~CeMachine(); ~CeMachine();
void Fail(const CeFrame& curFrame, const StringImpl& error);
void Init(); void Init();
void RemoveMethod(BfMethodInstance* methodInstance); void RemoveMethod(BfMethodInstance* methodInstance);
int GetConstantSize(BfConstant* constant); int GetConstantSize(BfConstant* constant);
void WriteConstant(uint8* ptr, BfConstant* constant); void WriteConstant(uint8* ptr, BfConstant* constant);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
bool Execute(); bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
void PrepareFunction(CeFunction* methodInstance); void PrepareFunction(CeFunction* methodInstance);
void ProcessWorkQueue(); void ProcessWorkQueue();
CeFunction* GetFunction(BfMethodInstance* methodInstance); CeFunction* GetFunction(BfMethodInstance* methodInstance, bool& added);
public: public:
void CompileStarted(); void CompileStarted();
void QueueMethod(BfMethodInstance* methodInstance); void QueueMethod(BfMethodInstance* methodInstance);
BfTypedValue Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags); BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
}; };
NS_BF_END NS_BF_END