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 else
return llvm::Type::getInt64Ty(*mLLVMContext);*/ return llvm::Type::getInt64Ty(*mLLVMContext);*/
case BfTypeCode_Float: case BfTypeCode_Float:
isSigned = true;
beTypeCode = BeTypeCode_Float; beTypeCode = BeTypeCode_Float;
break; break;
case BfTypeCode_Double: case BfTypeCode_Double:
isSigned = true;
beTypeCode = BeTypeCode_Double; beTypeCode = BeTypeCode_Double;
break; break;
} }
@ -2330,6 +2332,13 @@ void BeIRCodeGen::HandleNextCmd()
SetResult(curId, mBeModule->CreateRet(val)); SetResult(curId, mBeModule->CreateRet(val));
} }
break; break;
case BfIRCmd_CreateSetRet:
{
CMD_PARAM(BeValue*, val);
CMD_PARAM(int, returnTypeId);
SetResult(curId, mBeModule->CreateSetRet(val, returnTypeId));
}
break;
case BfIRCmd_CreateRetVoid: case BfIRCmd_CreateRetVoid:
{ {
mBeModule->CreateRetVoid(); mBeModule->CreateRetVoid();
@ -2433,7 +2442,9 @@ void BeIRCodeGen::HandleNextCmd()
} }
else else
{ {
if (attribute == BFIRAttribute_AlwaysInline) if (attribute == BfIRAttribute_VarRet)
func->mIsVarReturn = true;
else if (attribute == BFIRAttribute_AlwaysInline)
func->mAlwaysInline = true; func->mAlwaysInline = true;
else if (attribute == BFIRAttribute_NoUnwind) else if (attribute == BFIRAttribute_NoUnwind)
func->mNoUnwind = true; func->mNoUnwind = true;
@ -3483,3 +3494,33 @@ BeType* BeIRCodeGen::GetBeTypeById(int id)
{ {
return GetTypeEntry(id).mBeType; 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> template <typename T>
class CmdParamVec : public SizedArray<T, 8> class CmdParamVec : public SizedArray<T, 8>
@ -139,6 +152,9 @@ public:
BeMDNode* GetBeMetadata(int streamId); BeMDNode* GetBeMetadata(int streamId);
BeType* GetBeTypeById(int id); BeType* GetBeTypeById(int id);
BeState GetState();
void SetState(const BeState& state);
}; };
NS_BF_END NS_BF_END

View file

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

View file

@ -518,6 +518,7 @@ public:
String mName; String mName;
#endif #endif
BfIRLinkageType mLinkageType; BfIRLinkageType mLinkageType;
bool mIsVarReturn;
bool mAlwaysInline; bool mAlwaysInline;
bool mNoUnwind; bool mNoUnwind;
bool mUWTable; bool mUWTable;
@ -539,6 +540,7 @@ public:
mLinkageType = BfIRLinkageType_External; mLinkageType = BfIRLinkageType_External;
mModule = NULL; mModule = NULL;
mDbgFunction = NULL; mDbgFunction = NULL;
mIsVarReturn = false;
mAlwaysInline = false; mAlwaysInline = false;
mDidInlinePass = false; mDidInlinePass = false;
mNoUnwind = 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 class BeCallInst : public BeInst
{ {
public: public:
@ -2311,6 +2322,7 @@ public:
BeCondBrInst* CreateCondBr(BeValue* cond, BeBlock* trueBlock, BeBlock* falseBlock); BeCondBrInst* CreateCondBr(BeValue* cond, BeBlock* trueBlock, BeBlock* falseBlock);
BeRetInst* CreateRetVoid(); BeRetInst* CreateRetVoid();
BeRetInst* CreateRet(BeValue* value); BeRetInst* CreateRet(BeValue* value);
BeSetRetInst* CreateSetRet(BeValue* value, int returnTypeId);
BeCallInst* CreateCall(BeValue* func, const SizedArrayImpl<BeValue*>& args); 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->mCompiler->mCEMachine != NULL)
{ {
if (mModule->mIsConstModule) if ((mModule->mIsConstModule) && (!methodInstance->mReturnType->IsVar()))
{ {
mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func); mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func);
} }
@ -5045,10 +5045,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
CeEvalFlags evalFlags = CeEvalFlags_None; CeEvalFlags evalFlags = CeEvalFlags_None;
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType); auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
if (constRet) if (constRet)
{
BF_ASSERT(!constRet.mType->IsVar());
return constRet; return constRet;
} }
} }
} }
}
if (!forceBind) if (!forceBind)
{ {

View file

@ -730,6 +730,13 @@ BfIRValue BfIRConstHolder::CreateConstStructZero(BfIRType aggType)
BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values) BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values)
{ {
#ifdef _DEBUG
for (auto& val : values)
{
BF_ASSERT(val);
}
#endif
BfConstantAgg* constant = mTempAlloc.Alloc<BfConstantAgg>(); BfConstantAgg* constant = mTempAlloc.Alloc<BfConstantAgg>();
constant->mConstType = BfConstType_Agg; constant->mConstType = BfConstType_Agg;
constant->mType = type = type; constant->mType = type = type;
@ -4766,6 +4773,13 @@ BfIRValue BfIRBuilder::CreateRet(BfIRValue val)
return retVal; return retVal;
} }
BfIRValue BfIRBuilder::CreateSetRet(BfIRValue val, int returnTypeId)
{
BfIRValue retVal = WriteCmd(BfIRCmd_CreateSetRet, val, returnTypeId);
NEW_CMD_INSERTED;
return retVal;
}
void BfIRBuilder::CreateRetVoid() void BfIRBuilder::CreateRetVoid()
{ {
WriteCmd(BfIRCmd_CreateRetVoid); WriteCmd(BfIRCmd_CreateRetVoid);
@ -5391,4 +5405,22 @@ void BfIRBuilder::DbgCreateAnnotation(BfIRMDNode scope, const StringImpl& name,
NEW_CMD_INSERTED; 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_SetTailCall,
BfIRCmd_SetCallAttribute, BfIRCmd_SetCallAttribute,
BfIRCmd_CreateRet, BfIRCmd_CreateRet,
BfIRCmd_CreateSetRet,
BfIRCmd_CreateRetVoid, BfIRCmd_CreateRetVoid,
BfIRCmd_CreateUnreachable, BfIRCmd_CreateUnreachable,
BfIRCmd_Call_AddAttribute, BfIRCmd_Call_AddAttribute,
@ -627,6 +628,7 @@ enum BfIRAttribute
BfIRAttribute_NoAlias, BfIRAttribute_NoAlias,
BfIRAttribute_NoCapture, BfIRAttribute_NoCapture,
BfIRAttribute_StructRet, BfIRAttribute_StructRet,
BfIRAttribute_VarRet,
BfIRAttribute_ZExt, BfIRAttribute_ZExt,
BfIRAttribute_ByVal, BfIRAttribute_ByVal,
BfIRAttribute_Dereferencable, BfIRAttribute_Dereferencable,
@ -916,6 +918,15 @@ enum BfIRPopulateType
BfIRPopulateType_Full_ForceDefinition 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 class BfIRBuilder : public BfIRConstHolder
{ {
public: public:
@ -1227,6 +1238,7 @@ public:
void SetTailCall(BfIRValue callInst); void SetTailCall(BfIRValue callInst);
void SetCallAttribute(BfIRValue callInst, int paramIdx, BfIRAttribute attribute); void SetCallAttribute(BfIRValue callInst, int paramIdx, BfIRAttribute attribute);
BfIRValue CreateRet(BfIRValue val); BfIRValue CreateRet(BfIRValue val);
BfIRValue CreateSetRet(BfIRValue val, int returnTypeId);
void CreateRetVoid(); void CreateRetVoid();
void CreateUnreachable(); void CreateUnreachable();
void Call_AddAttribute(BfIRValue callInst, int argIdx, BfIRAttribute attr); void Call_AddAttribute(BfIRValue callInst, int argIdx, BfIRAttribute attr);
@ -1315,6 +1327,9 @@ public:
BfIRMDNode type, bool isLocalToUnit, BfIRValue val, BfIRMDNode Decl = BfIRMDNode()); BfIRMDNode type, bool isLocalToUnit, BfIRValue val, BfIRMDNode Decl = BfIRMDNode());
BfIRMDNode DbgCreateLexicalBlock(BfIRMDNode scope, BfIRMDNode file, int line, int col); BfIRMDNode DbgCreateLexicalBlock(BfIRMDNode scope, BfIRMDNode file, int line, int col);
void DbgCreateAnnotation(BfIRMDNode scope, const StringImpl& name, BfIRValue value); void DbgCreateAnnotation(BfIRMDNode scope, const StringImpl& name, BfIRValue value);
BfIRState GetState();
void SetState(const BfIRState& state);
}; };
NS_BF_END NS_BF_END

View file

@ -3522,7 +3522,11 @@ void BfIRCodeGen::HandleNextCmd()
NULL, llvm::GlobalValue::NotThreadLocal); NULL, llvm::GlobalValue::NotThreadLocal);
} }
else else
func->addAttribute(argIdx, LLVMMapAttribute(attribute)); {
auto attr = LLVMMapAttribute(attribute);
if (attr != llvm::Attribute::None)
func->addAttribute(argIdx, attr);
}
} }
break; break;
case BfIRCmd_Func_AddAttribute1: 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) void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAliasValue, BfIRValue declareBefore, BfIRInitType initType)
{ {
if (localVarDef->mResolvedType->IsVar())
return;
if ((mBfIRBuilder->DbgHasInfo()) && if ((mBfIRBuilder->DbgHasInfo()) &&
((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecialized)) && ((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecialized)) &&
(mHasFullDebugInfo) && (mHasFullDebugInfo) &&
@ -14460,19 +14463,31 @@ void BfModule::CreateReturn(BfIRValue val)
mBfIRBuilder->CreateRet(val); mBfIRBuilder->CreateRet(val);
} }
void BfModule::EmitReturn(BfIRValue val) void BfModule::EmitReturn(const BfTypedValue& val)
{ {
if (mCurMethodState->mIRExitBlock) if (mCurMethodState->mIRExitBlock)
{ {
if (!mCurMethodInstance->mReturnType->IsValuelessType()) 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 (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; BfIRValue retVal = mCurMethodState->mRetVal.mValue;
if (!mCurMethodState->mRetVal) if (!mCurMethodState->mRetVal)
retVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetValAddr); 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); EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
@ -14486,7 +14501,7 @@ void BfModule::EmitReturn(BfIRValue val)
if (mCurMethodInstance->mReturnType->IsValuelessType()) if (mCurMethodInstance->mReturnType->IsValuelessType())
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
else else
mBfIRBuilder->CreateRet(val); mBfIRBuilder->CreateRet(val.mValue);
} }
} }
@ -15609,6 +15624,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
if (methodInstance == NULL) if (methodInstance == NULL)
return; return;
if (methodInstance->mReturnType->IsVar())
mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_VarRet);
if (methodDef->mImportKind == BfImportKind_Export) if (methodDef->mImportKind == BfImportKind_Export)
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport); mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport);
if (methodDef->mIsNoReturn) if (methodDef->mIsNoReturn)
@ -19279,6 +19296,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{ {
bool isEmptyBodied = BfNodeDynCast<BfTokenNode>(methodDef->mBody) != NULL; 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)) if ((!mCurMethodInstance->mReturnType->IsValuelessType()) && (!isEmptyBodied))
{ {
mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType); mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType);
@ -19291,7 +19314,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->ClearDebugLocation(storeInst); mBfIRBuilder->ClearDebugLocation(storeInst);
mCurMethodState->mRetValAddr = allocaInst; mCurMethodState->mRetValAddr = allocaInst;
} }
else else if (wantsRetVal)
{ {
auto allocaInst = AllocLocalVariable(mCurMethodInstance->mReturnType, "__return", false); auto allocaInst = AllocLocalVariable(mCurMethodInstance->mReturnType, "__return", false);
mCurMethodState->mRetVal = BfTypedValue(allocaInst, mCurMethodInstance->mReturnType, true); mCurMethodState->mRetVal = BfTypedValue(allocaInst, mCurMethodInstance->mReturnType, true);
@ -19414,7 +19437,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{ {
mCurMethodState->mHadReturn = true; mCurMethodState->mHadReturn = true;
retVal = LoadOrAggregateValue(retVal); retVal = LoadOrAggregateValue(retVal);
EmitReturn(retVal.mValue); EmitReturn(retVal);
} }
} }
} }
@ -21211,14 +21234,13 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
(methodDef->mReturnTypeRef != NULL)) (methodDef->mReturnTypeRef != NULL))
{ {
SetAndRestoreValue<bool> prevIngoreErrors(mIgnoreErrors, mIgnoreErrors || (methodDef->GetPropertyDeclaration() != 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)) BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
{
Fail("Cannot declare var return types", methodDef->mReturnTypeRef); if ((methodDef->mIsConstEval) && (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var); resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
} else
resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags);
if (resolvedReturnType == NULL) if (resolvedReturnType == NULL)
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var); resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);

View file

@ -1552,7 +1552,7 @@ public:
// Util // Util
void CreateReturn(BfIRValue val); void CreateReturn(BfIRValue val);
void EmitReturn(BfIRValue val); void EmitReturn(const BfTypedValue& val);
void EmitDefaultReturn(); void EmitDefaultReturn();
void EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags = BfDeferredBlockFlag_None); void EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags = BfDeferredBlockFlag_None);
bool AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scope); 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); auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2);
returnType = irReturnType; returnType = irReturnType;
} }
else if (mReturnType->IsValuelessType()) else if ((mReturnType->IsValuelessType()) || (mReturnType->IsVar()))
{ {
auto voidType = module->GetPrimitiveType(BfTypeCode_None); auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType); returnType = module->mBfIRBuilder->MapType(voidType);

View file

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

View file

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

View file

@ -65,6 +65,7 @@ enum CeOp : int16
{ {
CeOp_InvalidOp, CeOp_InvalidOp,
CeOp_Ret, CeOp_Ret,
CeOp_SetRetType,
CeOp_Jmp, CeOp_Jmp,
CeOp_JmpIf, CeOp_JmpIf,
CeOp_JmpIfNot, CeOp_JmpIfNot,
@ -331,8 +332,10 @@ public:
CeInnerFunctionInfo* mCeInnerFunctionInfo; CeInnerFunctionInfo* mCeInnerFunctionInfo;
BfMethodInstance* mMethodInstance; BfMethodInstance* mMethodInstance;
CeFunctionKind mFunctionKind; CeFunctionKind mFunctionKind;
bool mGenerating;
bool mInitialized; bool mInitialized;
bool mFailed; bool mFailed;
bool mIsVarReturn;
Array<uint8> mCode; Array<uint8> mCode;
Array<String> mFiles; Array<String> mFiles;
Array<CeEmitEntry> mEmitTable; Array<CeEmitEntry> mEmitTable;
@ -344,6 +347,7 @@ public:
Array<CeFunction*> mInnerFunctions; Array<CeFunction*> mInnerFunctions;
String mGenError; String mGenError;
int mFrameSize; int mFrameSize;
int mMaxReturnSize;
int mId; int mId;
public: public:
@ -352,10 +356,13 @@ public:
mCeFunctionInfo = NULL; mCeFunctionInfo = NULL;
mCeInnerFunctionInfo = NULL; mCeInnerFunctionInfo = NULL;
mFunctionKind = CeFunctionKind_Normal; mFunctionKind = CeFunctionKind_Normal;
mGenerating = false;
mInitialized = false; mInitialized = false;
mMethodInstance = NULL; mMethodInstance = NULL;
mFailed = false; mFailed = false;
mIsVarReturn = false;
mFrameSize = 0; mFrameSize = 0;
mMaxReturnSize = 0;
mId = -1; mId = -1;
} }
@ -559,6 +566,7 @@ public:
addr_ce mStackAddr; addr_ce mStackAddr;
addr_ce mFrameAddr; addr_ce mFrameAddr;
uint8* mInstPtr; uint8* mInstPtr;
BfType* mReturnType;
public: public:
CeFrame() CeFrame()
@ -567,6 +575,7 @@ public:
mStackAddr = 0; mStackAddr = 0;
mFrameAddr = 0; mFrameAddr = 0;
mInstPtr = NULL; mInstPtr = NULL;
mReturnType = NULL;
} }
}; };
@ -648,7 +657,7 @@ public:
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal); CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal);
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL); BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); 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 PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
void MapFunctionId(CeFunction* ceFunction); 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]; 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] [Test]
public static void TestBasics() public static void TestBasics()
{ {
Test.Assert(ClassA.cVal0 == 123);
Test.Assert(ClassA.cVal0 == 1.23);
const int fac = Factorial(8); const int fac = Factorial(8);
Test.Assert(fac == 40320); Test.Assert(fac == 40320);
const int fib = Fibonacci(27); const int fib = Fibonacci(27);