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:
parent
585e2575e8
commit
706fe9e04b
15 changed files with 292 additions and 60 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue