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

var-return support for const eval methods

This commit is contained in:
Brian Fiete 2020-12-30 13:24:13 -08:00
parent 585e2575e8
commit 706fe9e04b
15 changed files with 292 additions and 60 deletions

View file

@ -379,9 +379,11 @@ BeType* BeIRCodeGen::GetBeType(BfTypeCode typeCode, bool& isSigned)
else
return llvm::Type::getInt64Ty(*mLLVMContext);*/
case BfTypeCode_Float:
isSigned = true;
beTypeCode = BeTypeCode_Float;
break;
case BfTypeCode_Double:
isSigned = true;
beTypeCode = BeTypeCode_Double;
break;
}
@ -2330,6 +2332,13 @@ void BeIRCodeGen::HandleNextCmd()
SetResult(curId, mBeModule->CreateRet(val));
}
break;
case BfIRCmd_CreateSetRet:
{
CMD_PARAM(BeValue*, val);
CMD_PARAM(int, returnTypeId);
SetResult(curId, mBeModule->CreateSetRet(val, returnTypeId));
}
break;
case BfIRCmd_CreateRetVoid:
{
mBeModule->CreateRetVoid();
@ -2433,7 +2442,9 @@ void BeIRCodeGen::HandleNextCmd()
}
else
{
if (attribute == BFIRAttribute_AlwaysInline)
if (attribute == BfIRAttribute_VarRet)
func->mIsVarReturn = true;
else if (attribute == BFIRAttribute_AlwaysInline)
func->mAlwaysInline = true;
else if (attribute == BFIRAttribute_NoUnwind)
func->mNoUnwind = true;
@ -3483,3 +3494,33 @@ BeType* BeIRCodeGen::GetBeTypeById(int id)
{
return GetTypeEntry(id).mBeType;
}
BeState BeIRCodeGen::GetState()
{
BeState state;
state.mActiveFunction = mActiveFunction;
state.mSavedDebugLocs = mSavedDebugLocs;
state.mHasDebugLoc = mHasDebugLoc;
state.mActiveBlock = mBeModule->mActiveBlock;
state.mInsertPos = mBeModule->mInsertPos;
state.mCurDbgLoc = mBeModule->mCurDbgLoc;
state.mPrevDbgLocInline = mBeModule->mPrevDbgLocInline;
state.mLastDbgLoc = mBeModule->mLastDbgLoc;
return state;
}
void BeIRCodeGen::SetState(const BeState& state)
{
mActiveFunction = state.mActiveFunction;
mBeModule->mActiveFunction = mActiveFunction;
mSavedDebugLocs = state.mSavedDebugLocs;
mHasDebugLoc = state.mHasDebugLoc;
mBeModule->mActiveBlock = state.mActiveBlock;
mBeModule->mInsertPos = state.mInsertPos;
mBeModule->mCurDbgLoc = state.mCurDbgLoc;
mBeModule->mPrevDbgLocInline = state.mPrevDbgLocInline;
mBeModule->mLastDbgLoc = state.mLastDbgLoc;
}

View file

@ -53,6 +53,19 @@ public:
}
};
class BeState
{
public:
BeFunction* mActiveFunction;
Array<BeDbgLoc*> mSavedDebugLocs;
bool mHasDebugLoc;
BeBlock* mActiveBlock;
int mInsertPos;
BeDbgLoc* mCurDbgLoc;
BeDbgLoc* mPrevDbgLocInline;
BeDbgLoc* mLastDbgLoc;
};
template <typename T>
class CmdParamVec : public SizedArray<T, 8>
@ -139,6 +152,9 @@ public:
BeMDNode* GetBeMetadata(int streamId);
BeType* GetBeTypeById(int id);
BeState GetState();
void SetState(const BeState& state);
};
NS_BF_END

View file

@ -2349,6 +2349,7 @@ String BeModule::ToString(BeFunction* wantFunc)
str += " void";
}
break;
DISPLAY_INST2(BeSetRetInst, "setret", mRetValue, mReturnTypeId);
case BeCallInst::TypeId:
{
auto castedInst = (BeCallInst*)inst;
@ -3383,6 +3384,15 @@ BeRetInst* BeModule::CreateRet(BeValue* value)
return inst;
}
BeSetRetInst* BeModule::CreateSetRet(BeValue* value, int returnTypeId)
{
auto inst = mAlloc.Alloc<BeSetRetInst>();
inst->mRetValue = value;
inst->mReturnTypeId = returnTypeId;
AddInst(inst);
return inst;
}
BeCallInst* BeModule::CreateCall(BeValue* func, const SizedArrayImpl<BeValue*>& args)
{
auto inst = mOwnedValues.Alloc<BeCallInst>();

View file

@ -518,6 +518,7 @@ public:
String mName;
#endif
BfIRLinkageType mLinkageType;
bool mIsVarReturn;
bool mAlwaysInline;
bool mNoUnwind;
bool mUWTable;
@ -539,6 +540,7 @@ public:
mLinkageType = BfIRLinkageType_External;
mModule = NULL;
mDbgFunction = NULL;
mIsVarReturn = false;
mAlwaysInline = false;
mDidInlinePass = false;
mNoUnwind = false;
@ -1265,6 +1267,15 @@ public:
}
};
class BeSetRetInst : public BeRetInst
{
public:
BE_VALUE_TYPE(BeSetRetInst, BeRetInst);
public:
int32 mReturnTypeId;
};
class BeCallInst : public BeInst
{
public:
@ -2311,6 +2322,7 @@ public:
BeCondBrInst* CreateCondBr(BeValue* cond, BeBlock* trueBlock, BeBlock* falseBlock);
BeRetInst* CreateRetVoid();
BeRetInst* CreateRet(BeValue* value);
BeSetRetInst* CreateSetRet(BeValue* value, int returnTypeId);
BeCallInst* CreateCall(BeValue* func, const SizedArrayImpl<BeValue*>& args);

View file

@ -5026,7 +5026,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (mModule->mCompiler->mCEMachine != NULL)
{
if (mModule->mIsConstModule)
if ((mModule->mIsConstModule) && (!methodInstance->mReturnType->IsVar()))
{
mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func);
}
@ -5045,10 +5045,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
CeEvalFlags evalFlags = CeEvalFlags_None;
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
if (constRet)
{
BF_ASSERT(!constRet.mType->IsVar());
return constRet;
}
}
}
}
if (!forceBind)
{

View file

@ -730,6 +730,13 @@ BfIRValue BfIRConstHolder::CreateConstStructZero(BfIRType aggType)
BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values)
{
#ifdef _DEBUG
for (auto& val : values)
{
BF_ASSERT(val);
}
#endif
BfConstantAgg* constant = mTempAlloc.Alloc<BfConstantAgg>();
constant->mConstType = BfConstType_Agg;
constant->mType = type = type;
@ -4766,6 +4773,13 @@ BfIRValue BfIRBuilder::CreateRet(BfIRValue val)
return retVal;
}
BfIRValue BfIRBuilder::CreateSetRet(BfIRValue val, int returnTypeId)
{
BfIRValue retVal = WriteCmd(BfIRCmd_CreateSetRet, val, returnTypeId);
NEW_CMD_INSERTED;
return retVal;
}
void BfIRBuilder::CreateRetVoid()
{
WriteCmd(BfIRCmd_CreateRetVoid);
@ -5391,4 +5405,22 @@ void BfIRBuilder::DbgCreateAnnotation(BfIRMDNode scope, const StringImpl& name,
NEW_CMD_INSERTED;
}
BfIRState BfIRBuilder::GetState()
{
BfIRState state;
state.mActualInsertBlock = mActualInsertBlock;
state.mInsertBlock = mInsertBlock;
state.mActiveFunction = mActiveFunction;
state.mActiveFunctionHasBody = mActiveFunctionHasBody;
state.mSavedDebugLocs = mSavedDebugLocs;
return state;
}
void BfIRBuilder::SetState(const BfIRState& state)
{
mActualInsertBlock = state.mActualInsertBlock;
mInsertBlock = state.mInsertBlock;
mActiveFunction = state.mActiveFunction;
mActiveFunctionHasBody = state.mActiveFunctionHasBody;
mSavedDebugLocs = state.mSavedDebugLocs;
}

View file

@ -270,6 +270,7 @@ enum BfIRCmd : uint8
BfIRCmd_SetTailCall,
BfIRCmd_SetCallAttribute,
BfIRCmd_CreateRet,
BfIRCmd_CreateSetRet,
BfIRCmd_CreateRetVoid,
BfIRCmd_CreateUnreachable,
BfIRCmd_Call_AddAttribute,
@ -627,6 +628,7 @@ enum BfIRAttribute
BfIRAttribute_NoAlias,
BfIRAttribute_NoCapture,
BfIRAttribute_StructRet,
BfIRAttribute_VarRet,
BfIRAttribute_ZExt,
BfIRAttribute_ByVal,
BfIRAttribute_Dereferencable,
@ -916,6 +918,15 @@ enum BfIRPopulateType
BfIRPopulateType_Full_ForceDefinition
};
struct BfIRState
{
BfIRBlock mActualInsertBlock; // Only when not ignoring writes
BfIRBlock mInsertBlock;
BfIRFunction mActiveFunction;
bool mActiveFunctionHasBody;
Array<BfFilePosition> mSavedDebugLocs;
};
class BfIRBuilder : public BfIRConstHolder
{
public:
@ -1227,6 +1238,7 @@ public:
void SetTailCall(BfIRValue callInst);
void SetCallAttribute(BfIRValue callInst, int paramIdx, BfIRAttribute attribute);
BfIRValue CreateRet(BfIRValue val);
BfIRValue CreateSetRet(BfIRValue val, int returnTypeId);
void CreateRetVoid();
void CreateUnreachable();
void Call_AddAttribute(BfIRValue callInst, int argIdx, BfIRAttribute attr);
@ -1315,6 +1327,9 @@ public:
BfIRMDNode type, bool isLocalToUnit, BfIRValue val, BfIRMDNode Decl = BfIRMDNode());
BfIRMDNode DbgCreateLexicalBlock(BfIRMDNode scope, BfIRMDNode file, int line, int col);
void DbgCreateAnnotation(BfIRMDNode scope, const StringImpl& name, BfIRValue value);
BfIRState GetState();
void SetState(const BfIRState& state);
};
NS_BF_END

View file

@ -3522,7 +3522,11 @@ void BfIRCodeGen::HandleNextCmd()
NULL, llvm::GlobalValue::NotThreadLocal);
}
else
func->addAttribute(argIdx, LLVMMapAttribute(attribute));
{
auto attr = LLVMMapAttribute(attribute);
if (attr != llvm::Attribute::None)
func->addAttribute(argIdx, attr);
}
}
break;
case BfIRCmd_Func_AddAttribute1:

View file

@ -13639,6 +13639,9 @@ void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAliasValue, BfIRValue declareBefore, BfIRInitType initType)
{
if (localVarDef->mResolvedType->IsVar())
return;
if ((mBfIRBuilder->DbgHasInfo()) &&
((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecialized)) &&
(mHasFullDebugInfo) &&
@ -14460,19 +14463,31 @@ void BfModule::CreateReturn(BfIRValue val)
mBfIRBuilder->CreateRet(val);
}
void BfModule::EmitReturn(BfIRValue val)
void BfModule::EmitReturn(const BfTypedValue& val)
{
if (mCurMethodState->mIRExitBlock)
{
if (!mCurMethodInstance->mReturnType->IsValuelessType())
{
if (val) // We allow for val to be empty if we know we've already written the value to mRetVal
{
if ((mCurMethodState->mRetValAddr) || (mCurMethodState->mRetVal))
{
BfIRValue retVal = mCurMethodState->mRetVal.mValue;
if (!mCurMethodState->mRetVal)
retVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetValAddr);
mBfIRBuilder->CreateStore(val, retVal);
mBfIRBuilder->CreateStore(val.mValue, retVal);
}
else if (mIsConstModule)
{
mBfIRBuilder->CreateSetRet(val.mValue, val.mType->mTypeId);
}
else
{
// Just ignore
BF_ASSERT(mCurMethodInstance->mReturnType->IsVar());
}
}
}
EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
@ -14486,7 +14501,7 @@ void BfModule::EmitReturn(BfIRValue val)
if (mCurMethodInstance->mReturnType->IsValuelessType())
mBfIRBuilder->CreateRetVoid();
else
mBfIRBuilder->CreateRet(val);
mBfIRBuilder->CreateRet(val.mValue);
}
}
@ -15609,6 +15624,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
if (methodInstance == NULL)
return;
if (methodInstance->mReturnType->IsVar())
mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_VarRet);
if (methodDef->mImportKind == BfImportKind_Export)
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport);
if (methodDef->mIsNoReturn)
@ -19279,6 +19296,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
bool isEmptyBodied = BfNodeDynCast<BfTokenNode>(methodDef->mBody) != NULL;
bool wantsRetVal = true;
if ((mIsConstModule) && (methodDef->mMethodType != BfMethodType_CtorCalcAppend))
wantsRetVal = false;
else if (mCurMethodInstance->mReturnType->IsVar())
wantsRetVal = false;
if ((!mCurMethodInstance->mReturnType->IsValuelessType()) && (!isEmptyBodied))
{
mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType);
@ -19291,7 +19314,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->ClearDebugLocation(storeInst);
mCurMethodState->mRetValAddr = allocaInst;
}
else
else if (wantsRetVal)
{
auto allocaInst = AllocLocalVariable(mCurMethodInstance->mReturnType, "__return", false);
mCurMethodState->mRetVal = BfTypedValue(allocaInst, mCurMethodInstance->mReturnType, true);
@ -19414,7 +19437,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
mCurMethodState->mHadReturn = true;
retVal = LoadOrAggregateValue(retVal);
EmitReturn(retVal.mValue);
EmitReturn(retVal);
}
}
}
@ -21211,14 +21234,13 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
(methodDef->mReturnTypeRef != NULL))
{
SetAndRestoreValue<bool> prevIngoreErrors(mIgnoreErrors, mIgnoreErrors || (methodDef->GetPropertyDeclaration() != NULL));
resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration,
(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric));
if ((resolvedReturnType != NULL) && (resolvedReturnType->IsVar()) && (methodDef->mMethodType != BfMethodType_Mixin))
{
Fail("Cannot declare var return types", methodDef->mReturnTypeRef);
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
if ((methodDef->mIsConstEval) && (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
}
else
resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags);
if (resolvedReturnType == NULL)
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);

View file

@ -1552,7 +1552,7 @@ public:
// Util
void CreateReturn(BfIRValue val);
void EmitReturn(BfIRValue val);
void EmitReturn(const BfTypedValue& val);
void EmitDefaultReturn();
void EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags = BfDeferredBlockFlag_None);
bool AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scope);

View file

@ -1148,7 +1148,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2);
returnType = irReturnType;
}
else if (mReturnType->IsValuelessType())
else if ((mReturnType->IsValuelessType()) || (mReturnType->IsVar()))
{
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);

View file

@ -3787,9 +3787,9 @@ void BfModule::Visit(BfThrowStatement* throwStmt)
Fail("Exceptions are not supported", throwStmt->mThrowToken);
if (mCurMethodInstance->mReturnType->IsVoid())
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
else
EmitReturn(GetDefaultValue(mCurMethodInstance->mReturnType));
EmitReturn(GetDefaultTypedValue(mCurMethodInstance->mReturnType));
}
void BfModule::Visit(BfDeleteStatement* deleteStmt)
@ -4927,7 +4927,7 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
MarkScopeLeft(&mCurMethodState->mHeadScope);
if (retType->IsVoid())
{
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
return;
}
@ -4937,11 +4937,13 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
return;
}
EmitReturn(GetDefaultValue(retType));
EmitReturn(GetDefaultTypedValue(retType));
return;
}
BfType* expectingReturnType = retType;
if ((expectingReturnType != NULL) && (expectingReturnType->IsVar()))
expectingReturnType = NULL;
BfType* origType;
BfExprEvaluator exprEvaluator(this);
@ -4964,21 +4966,21 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
}
else
{
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
return;
}
}
if (retValue.mType->IsVar())
{
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
}
else if (retValue.mType->IsVoid())
{
if (retType->IsVoid())
{
Warn(0, "Returning void value", returnStmt->mReturnToken);
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
}
}
else
@ -4987,7 +4989,7 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
{
expectingReturnType = NULL;
Fail("Attempting to return value from void method", returnStmt->mExpression);
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
return;
}
@ -4997,9 +4999,9 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
}
if (!alreadyWritten)
EmitReturn(LoadOrAggregateValue(retValue).mValue);
EmitReturn(LoadOrAggregateValue(retValue));
else
EmitReturn(BfIRValue());
EmitReturn(BfTypedValue());
}
}

View file

@ -83,6 +83,7 @@ static CeOpInfo gOpInfo[] =
{
{"InvalidOp"},
{"Ret"},
{"SetRet", CEOI_None, CEOI_IMM32},
{"Jmp", CEOI_None, CEOI_JMPREL},
{"JmpIf", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
{"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
@ -1123,13 +1124,11 @@ void CeBuilder::HandleParams()
int frameOffset = 0;
if (retType->mSize > 0)
if (mCeFunction->mMaxReturnSize > 0)
{
mReturnVal.mKind = CeOperandKind_AllocaAddr;
mReturnVal.mFrameOfs = frameOffset;
mReturnVal.mType = retType;
frameOffset += retType->mSize;
frameOffset += mCeFunction->mMaxReturnSize;
}
int paramOfs = 0;
@ -1157,6 +1156,7 @@ void CeBuilder::HandleParams()
void CeBuilder::Build()
{
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
auto beModule = irCodeGen->mBeModule;
mCeFunction->mFailed = true;
@ -1169,15 +1169,17 @@ void CeBuilder::Build()
BfMethodInstance dupMethodInstance;
dupMethodInstance.CopyFrom(methodInstance);
//dupMethodInstance.mIRFunction = workItem.mFunc;
dupMethodInstance.mIsReified = true;
dupMethodInstance.mInCEMachine = false; // Only have the original one
int startFunctionCount = (int)beModule->mFunctions.size();
//int startGlobalVariableCount = (int)beModule->mGlobalVariables.size();
mCeMachine->mCeModule->mHadBuildError = false;
auto irState = irBuilder->GetState();
auto beState = irCodeGen->GetState();
mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true);
irCodeGen->SetState(beState);
irBuilder->SetState(irState);
if (!dupMethodInstance.mIRFunction)
{
@ -1197,6 +1199,7 @@ void CeBuilder::Build()
continue;
CeFunction* innerFunction = new CeFunction();
innerFunction->mIsVarReturn = beFunction->mIsVarReturn;
innerFunction->mCeInnerFunctionInfo = new CeInnerFunctionInfo();
innerFunction->mCeInnerFunctionInfo->mName = beFunction->mName;
innerFunction->mCeInnerFunctionInfo->mBeFunction = beFunction;
@ -1294,6 +1297,17 @@ void CeBuilder::Build()
}
}
break;
case BeRetInst::TypeId:
case BeSetRetInst::TypeId:
{
auto castedInst = (BeRetInst*)inst;
if (castedInst->mRetValue != NULL)
{
auto retType = castedInst->mRetValue->GetType();
mCeFunction->mMaxReturnSize = BF_MAX(retType->mSize, mCeFunction->mMaxReturnSize);
}
}
break;
}
}
}
@ -1788,6 +1802,7 @@ void CeBuilder::Build()
}
break;
case BeRetInst::TypeId:
case BeSetRetInst::TypeId:
{
auto castedInst = (BeRetInst*)inst;
if (castedInst->mRetValue != NULL)
@ -1797,7 +1812,15 @@ void CeBuilder::Build()
EmitSizedOp(CeOp_Move_8, mcVal, NULL, true);
Emit((int32)mReturnVal.mFrameOfs);
}
if (instType == BeRetInst::TypeId)
Emit(CeOp_Ret);
else
{
auto setRetInst = (BeSetRetInst*)inst;
Emit(CeOp_SetRetType);
Emit((int32)setRetInst->mReturnTypeId);
}
}
break;
case BeCmpInst::TypeId:
@ -3483,6 +3506,9 @@ BfIRValue CeMachine::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
{
auto typeInst = bfType->ToTypeInstance();
if (typeInst->mIsUnion)
return BfIRValue();
uint8* instData = ptr;
// if ((typeInst->IsObject()) && (!isBaseType))
// {
@ -3744,11 +3770,12 @@ BfIRValue CeMachine::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
instPtr = &ceFunction->mCode[0]; \
CE_CHECKSTACK();
bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr)
bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType)
{
mExecuteId++;
CeFunction* ceFunction = startFunction;
returnType = startFunction->mMethodInstance->mReturnType;
uint8* memStart = &mMemory[0];
int memSize = mMemory.mSize;
uint8* instPtr = (ceFunction->mCode.IsEmpty()) ? NULL : &ceFunction->mCode[0];
@ -3758,11 +3785,11 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
volatile bool* cancelPtr = &mCompiler->mCanceling;
auto _GetCurFrame = [&]()
{
CeFrame ceFrame;
ceFrame.mFunction = ceFunction;
ceFrame.mReturnType = returnType;
ceFrame.mFrameAddr = framePtr - memStart;
ceFrame.mStackAddr = stackPtr - memStart;
ceFrame.mInstPtr = instPtr;
@ -4027,6 +4054,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
return false;
}
if (!checkFunction->mFailed)
return true;
auto error = Fail(_GetCurFrame(), "Method call failed");
@ -4070,10 +4098,18 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
instPtr = ceFrame.mInstPtr;
stackPtr = memStart + ceFrame.mStackAddr;
framePtr = memStart + ceFrame.mFrameAddr;
returnType = ceFrame.mReturnType;
mCallStack.pop_back();
}
break;
case CeOp_SetRetType:
{
int typeId = CE_GETINST(int32);
returnType = GetBfType(typeId);
BF_ASSERT(returnType != NULL);
}
break;
case CeOp_Jmp:
{
auto relOfs = CE_GETINST(int32);
@ -4666,6 +4702,8 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
bool handled = false;
if (!_CheckFunction(callFunction, handled))
return false;
if (callFunction->mIsVarReturn)
_Fail("Illegal call to method with 'var' return.");
if (handled)
break;
@ -5284,6 +5322,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
BF_ASSERT(!ceFunction->mInitialized);
ceFunction->mInitialized = true;
ceFunction->mGenerating = true;
CeBuilder ceBuilder;
ceBuilder.mParentBuilder = parentBuilder;
@ -5292,6 +5331,8 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
ceBuilder.mCeFunction = ceFunction;
ceBuilder.Build();
ceFunction->mGenerating = false;
/*if (!ceFunction->mCode.IsEmpty())
{
CeDumpContext dumpCtx;
@ -5375,6 +5416,7 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
BF_ASSERT(ceFunctionInfo->mCeFunction == NULL);
ceFunction = new CeFunction();
ceFunction->mIsVarReturn = methodInstance->mReturnType->IsVar();
ceFunction->mCeFunctionInfo = ceFunctionInfo;
ceFunction->mMethodInstance = methodInstance;
@ -5505,6 +5547,13 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
bool added = false;
CeFunction* ceFunction = GetFunction(methodInstance, BfIRValue(), added);
if (ceFunction->mGenerating)
{
Fail("Recursive var-inference");
return BfTypedValue();
}
if (!ceFunction->mInitialized)
PrepareFunction(ceFunction, NULL);
@ -5631,15 +5680,15 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
}
addr_ce retAddr = 0;
auto returnType = methodInstance->mReturnType;
if (!returnType->IsValuelessType())
if (ceFunction->mMaxReturnSize > 0)
{
int retSize = methodInstance->mReturnType->mSize;
int retSize = ceFunction->mMaxReturnSize;
stackPtr -= retSize;
retAddr = stackPtr - memStart;
}
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr);
BfType* returnType = NULL;
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr, returnType);
memStart = &mMemory[0];
addr_ce retInstAddr = retAddr;

View file

@ -65,6 +65,7 @@ enum CeOp : int16
{
CeOp_InvalidOp,
CeOp_Ret,
CeOp_SetRetType,
CeOp_Jmp,
CeOp_JmpIf,
CeOp_JmpIfNot,
@ -331,8 +332,10 @@ public:
CeInnerFunctionInfo* mCeInnerFunctionInfo;
BfMethodInstance* mMethodInstance;
CeFunctionKind mFunctionKind;
bool mGenerating;
bool mInitialized;
bool mFailed;
bool mIsVarReturn;
Array<uint8> mCode;
Array<String> mFiles;
Array<CeEmitEntry> mEmitTable;
@ -344,6 +347,7 @@ public:
Array<CeFunction*> mInnerFunctions;
String mGenError;
int mFrameSize;
int mMaxReturnSize;
int mId;
public:
@ -352,10 +356,13 @@ public:
mCeFunctionInfo = NULL;
mCeInnerFunctionInfo = NULL;
mFunctionKind = CeFunctionKind_Normal;
mGenerating = false;
mInitialized = false;
mMethodInstance = NULL;
mFailed = false;
mIsVarReturn = false;
mFrameSize = 0;
mMaxReturnSize = 0;
mId = -1;
}
@ -559,6 +566,7 @@ public:
addr_ce mStackAddr;
addr_ce mFrameAddr;
uint8* mInstPtr;
BfType* mReturnType;
public:
CeFrame()
@ -567,6 +575,7 @@ public:
mStackAddr = 0;
mFrameAddr = 0;
mInstPtr = NULL;
mReturnType = NULL;
}
};
@ -648,7 +657,7 @@ public:
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal);
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType);
void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
void MapFunctionId(CeFunction* ceFunction);

View file

@ -121,9 +121,26 @@ namespace Tests
return sa.mA + sa.mB + tup.0 + tup.1 + arr[0] + arr[1];
}
[ConstEval]
static var StrToValue(String str)
{
if (str.Contains('.'))
return float.Parse(str).Value;
return int.Parse(str).Value;
}
class ClassA
{
public const let cVal0 = StrToValue("123");
public const let cVal1 = StrToValue("1.23");
}
[Test]
public static void TestBasics()
{
Test.Assert(ClassA.cVal0 == 123);
Test.Assert(ClassA.cVal0 == 1.23);
const int fac = Factorial(8);
Test.Assert(fac == 40320);
const int fib = Fibonacci(27);