diff --git a/BeefLibs/corlib/src/Attribute.bf b/BeefLibs/corlib/src/Attribute.bf index 72dcdf2f..f626b041 100644 --- a/BeefLibs/corlib/src/Attribute.bf +++ b/BeefLibs/corlib/src/Attribute.bf @@ -102,7 +102,7 @@ namespace System } } - [AttributeUsage(.Method /*1*/ | .Invocation)] + [AttributeUsage(.Method | .Constructor | .Invocation | .Property)] public struct InlineAttribute : Attribute { diff --git a/BeefLibs/corlib/src/Internal.bf b/BeefLibs/corlib/src/Internal.bf index 1d1e6de2..24eafddf 100644 --- a/BeefLibs/corlib/src/Internal.bf +++ b/BeefLibs/corlib/src/Internal.bf @@ -13,7 +13,9 @@ namespace System [AlwaysInclude] static class Internal { + [Intrinsic("cast")] public static extern Object UnsafeCastToObject(void* ptr); + [Intrinsic("cast")] public static extern void* UnsafeCastToPtr(Object obj); [NoReturn] public static extern void ThrowIndexOutOfRange(int stackOffset = 0); diff --git a/BeefLibs/corlib/src/Nullable.bf b/BeefLibs/corlib/src/Nullable.bf index 769076a3..7ecc7d18 100644 --- a/BeefLibs/corlib/src/Nullable.bf +++ b/BeefLibs/corlib/src/Nullable.bf @@ -78,7 +78,10 @@ namespace System [Inline] public static implicit operator Nullable(T value) { - return Nullable(value); + Nullable result; + result.mHasValue = true; + result.mValue = value; + return result; } [Inline] diff --git a/IDE/mintest/minlib/src/System/Attribute.bf b/IDE/mintest/minlib/src/System/Attribute.bf index b448f6ca..3574932d 100644 --- a/IDE/mintest/minlib/src/System/Attribute.bf +++ b/IDE/mintest/minlib/src/System/Attribute.bf @@ -102,7 +102,7 @@ namespace System } } - [AttributeUsage(.Method /*1*/ | .Invocation | .Property)] + [AttributeUsage(.Method | .Constructor | .Invocation | .Property)] public struct InlineAttribute : Attribute { diff --git a/IDE/mintest/minlib/src/System/Internal.bf b/IDE/mintest/minlib/src/System/Internal.bf index 1d1e6de2..24eafddf 100644 --- a/IDE/mintest/minlib/src/System/Internal.bf +++ b/IDE/mintest/minlib/src/System/Internal.bf @@ -13,7 +13,9 @@ namespace System [AlwaysInclude] static class Internal { + [Intrinsic("cast")] public static extern Object UnsafeCastToObject(void* ptr); + [Intrinsic("cast")] public static extern void* UnsafeCastToPtr(Object obj); [NoReturn] public static extern void ThrowIndexOutOfRange(int stackOffset = 0); diff --git a/IDE/mintest/minlib/src/System/Nullable.bf b/IDE/mintest/minlib/src/System/Nullable.bf index bb04ff28..2d14726d 100644 --- a/IDE/mintest/minlib/src/System/Nullable.bf +++ b/IDE/mintest/minlib/src/System/Nullable.bf @@ -70,7 +70,10 @@ namespace System [Inline] public static implicit operator Nullable(T value) { - return Nullable(value); + Nullable result; + result.mHasValue = true; + result.mValue = value; + return result; } [Inline] diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 80b60491..5d6ec320 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -1902,7 +1902,9 @@ void BeIRCodeGen::HandleNextCmd() case BfIRCmd_GetIntrinsic: { CMD_PARAM(int, intrinId); + CMD_PARAM(BeType*, returnType); CMD_PARAM(CmdParamVec, paramTypes); + auto intrin = mBeModule->mAlloc.Alloc(); intrin->mKind = (BfIRIntrinsic)intrinId; @@ -1933,6 +1935,9 @@ void BeIRCodeGen::HandleNextCmd() case BfIRIntrinsic_AtomicCmpStore: case BfIRIntrinsic_AtomicCmpStore_Weak: intrin->mReturnType = mBeContext->GetPrimitiveType(BeTypeCode_Boolean); + break; + case BfIRIntrinsic_Cast: + intrin->mReturnType = returnType; break; } diff --git a/IDEHelper/Backend/BeMCContext.cpp b/IDEHelper/Backend/BeMCContext.cpp index 67f15575..f627168e 100644 --- a/IDEHelper/Backend/BeMCContext.cpp +++ b/IDEHelper/Backend/BeMCContext.cpp @@ -16209,6 +16209,15 @@ void BeMCContext::Generate(BeFunction* function) result = scratchReg; } break; + case BfIRIntrinsic_Cast: + { + result = AllocVirtualReg(intrin->mReturnType); + CreateDefineVReg(result); + auto vregInfo = GetVRegInfo(result); + vregInfo->mRelTo = GetOperand(castedInst->mArgs[0].mValue); + vregInfo->mIsExpr = true; + } + break; case BfIRIntrinsic_MemSet: { if (auto constVal = BeValueDynCast(castedInst->mArgs[1].mValue)) diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 1fd7ec05..5e9fd064 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -4232,9 +4232,9 @@ void BfIRBuilder::AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comin NEW_CMD_INSERTED; } -BfIRFunction BfIRBuilder::GetIntrinsic(int intrinId, const BfSizedArray& paramTypes) +BfIRFunction BfIRBuilder::GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray& paramTypes) { - BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinId, paramTypes); + BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinId, returnType, paramTypes); NEW_CMD_INSERTED; return retVal; } diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index e244445e..562a2a5c 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -403,6 +403,7 @@ enum BfIRIntrinsic : uint8 BfIRIntrinsic_AtomicXChg, BfIRIntrinsic_AtomicXor, BfIRIntrinsic_BSwap, + BfIRIntrinsic_Cast, BfIRIntrinsic_Cos, BfIRIntrinsic_Floor, BfIRIntrinsic_Free, @@ -1136,7 +1137,7 @@ public: BfIRValue CreatePhi(BfIRType type, int incomingCount); void AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comingFrom); - BfIRFunction GetIntrinsic(int intrinId, const BfSizedArray& paramTypes); + BfIRFunction GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray& paramTypes); BfIRFunctionType MapMethod(BfMethodInstance* methodInstance); BfIRFunctionType CreateFunctionType(BfIRType resultType, const BfSizedArray& paramTypes, bool isVarArg = false); BfIRFunction CreateFunction(BfIRFunctionType funcType, BfIRLinkageType linkageType, const StringImpl& name); diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 1569b202..9fb721b7 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -143,6 +143,7 @@ static const BuiltinEntry gIntrinEntries[] = {"atomic_xchg"}, {"atomic_xor"}, {"bswap"}, + {"cast"}, {"cos"}, {"floor"}, {"free"}, @@ -1815,18 +1816,24 @@ void BfIRCodeGen::HandleNextCmd() case BfIRCmd_GetIntrinsic: { CMD_PARAM(int, intrinId); + CMD_PARAM(llvm::Type*, returnType); CMD_PARAM(CmdParamVec, paramTypes); - + bool isFakeIntrinsic = false; - if ((intrinId >= BfIRIntrinsic_Atomic_FIRST) && (intrinId <= BfIRIntrinsic_Atomic_LAST)) + if (((intrinId >= BfIRIntrinsic_Atomic_FIRST) && (intrinId <= BfIRIntrinsic_Atomic_LAST)) || + (intrinId == BfIRIntrinsic_Cast)) { isFakeIntrinsic = true; } if (isFakeIntrinsic) - { + { + auto intrinsicData = mAlloc.Alloc(); + intrinsicData->mIntrinsic = (BfIRIntrinsic)intrinId; + intrinsicData->mReturnType = returnType; + BfIRCodeGenEntry entry; - entry.mKind = BfIRCodeGenEntryKind_FakeIntrinsic; - entry.mIntrinsic = (BfIRIntrinsic)intrinId; + entry.mKind = BfIRCodeGenEntryKind_IntrinsicData; + entry.mIntrinsicData = intrinsicData; mResults.TryAdd(curId, entry); break; } @@ -1863,6 +1870,7 @@ void BfIRCodeGen::HandleNextCmd() { (llvm::Intrinsic::ID)-1, -1}, // AtomicXChg, { (llvm::Intrinsic::ID)-1, -1}, // AtomicXor, { llvm::Intrinsic::bswap, -1}, + { (llvm::Intrinsic::ID) - 1, -1}, // cast, { llvm::Intrinsic::cos, -1}, { llvm::Intrinsic::floor, -1}, { (llvm::Intrinsic::ID)-1, -1}, // free @@ -2005,9 +2013,11 @@ void BfIRCodeGen::HandleNextCmd() Read(func, &codeGenEntry); CMD_PARAM(CmdParamVec, args); - if ((func == NULL) && (codeGenEntry != NULL) && (codeGenEntry->mKind == BfIRCodeGenEntryKind_FakeIntrinsic)) + if ((func == NULL) && (codeGenEntry != NULL) && (codeGenEntry->mKind == BfIRCodeGenEntryKind_IntrinsicData)) { - switch (codeGenEntry->mIntrinsic) + auto intrinsicData = codeGenEntry->mIntrinsicData; + + switch (intrinsicData->mIntrinsic) { case BfIRIntrinsic_AtomicCmpStore: case BfIRIntrinsic_AtomicCmpStore_Weak: @@ -2077,11 +2087,11 @@ void BfIRCodeGen::HandleNextCmd() } auto inst = mIRBuilder->CreateAtomicCmpXchg(args[0], args[1], args[2], successOrdering, failOrdering); - if (codeGenEntry->mIntrinsic == BfIRIntrinsic_AtomicCmpStore_Weak) + if (intrinsicData->mIntrinsic == BfIRIntrinsic_AtomicCmpStore_Weak) inst->setWeak(true); if ((memoryKind & BfIRAtomicOrdering_Volatile) != 0) inst->setVolatile(true); - if (codeGenEntry->mIntrinsic == BfIRIntrinsic_AtomicCmpXChg) + if (intrinsicData->mIntrinsic == BfIRIntrinsic_AtomicCmpXChg) { auto prevVal = mIRBuilder->CreateExtractValue(inst, 0); SetResult(curId, prevVal); @@ -2218,7 +2228,7 @@ void BfIRCodeGen::HandleNextCmd() bool isFloat = args[1]->getType()->isFloatingPointTy(); auto op = llvm::AtomicRMWInst::BinOp::Add; - switch (codeGenEntry->mIntrinsic) + switch (intrinsicData->mIntrinsic) { case BfIRIntrinsic_AtomicAdd: op = llvm::AtomicRMWInst::BinOp::Add; @@ -2293,7 +2303,7 @@ void BfIRCodeGen::HandleNextCmd() llvm::Value* result = atomicRMW; if ((memoryKind & BfIRAtomicOrdering_ReturnModified) != 0) { - switch (codeGenEntry->mIntrinsic) + switch (intrinsicData->mIntrinsic) { case BfIRIntrinsic_AtomicAdd: if (isFloat) @@ -2310,7 +2320,7 @@ void BfIRCodeGen::HandleNextCmd() case BfIRIntrinsic_AtomicUMin: { llvm::Value* cmpVal = NULL; - switch (codeGenEntry->mIntrinsic) + switch (intrinsicData->mIntrinsic) { case BfIRIntrinsic_AtomicMax: if (isFloat) @@ -2360,6 +2370,11 @@ void BfIRCodeGen::HandleNextCmd() SetResult(curId, result); } break; + case BfIRIntrinsic_Cast: + { + SetResult(curId, mIRBuilder->CreateBitCast(args[0], intrinsicData->mReturnType)); + } + break; default: Fail("Unhandled intrinsic"); } diff --git a/IDEHelper/Compiler/BfIRCodeGen.h b/IDEHelper/Compiler/BfIRCodeGen.h index 526f20c2..6b86c705 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.h +++ b/IDEHelper/Compiler/BfIRCodeGen.h @@ -13,7 +13,14 @@ enum BfIRCodeGenEntryKind BfIRCodeGenEntryKind_LLVMType, BfIRCodeGenEntryKind_LLVMBasicBlock, BfIRCodeGenEntryKind_LLVMMetadata, - BfIRCodeGenEntryKind_FakeIntrinsic, + BfIRCodeGenEntryKind_IntrinsicData, +}; + +class BfIRIntrinsicData +{ +public: + BfIRIntrinsic mIntrinsic; + llvm::Type* mReturnType; }; struct BfIRCodeGenEntry @@ -25,7 +32,7 @@ struct BfIRCodeGenEntry llvm::Type* mLLVMType; llvm::BasicBlock* mLLVMBlock; llvm::MDNode* mLLVMMetadata; - BfIRIntrinsic mIntrinsic; + BfIRIntrinsicData* mIntrinsicData; }; }; @@ -54,6 +61,7 @@ class BfIRCodeGen : public BfIRCodeGenBase public: BfIRBuilder* mBfIRBuilder; + BumpAllocator mAlloc; BfTargetTriple mTargetTriple; String mModuleName; llvm::LLVMContext* mLLVMContext; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 022acb91..cd76a011 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6096,7 +6096,7 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor SizedArray paramTypes; for (auto& param : methodInstance->mParams) paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType)); - return mBfIRBuilder->GetIntrinsic(intrinId, paramTypes); + return mBfIRBuilder->GetIntrinsic(intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes); } else if (reportFailure) error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str()); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index f81ade7d..b0a4ef7a 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -6281,6 +6281,11 @@ void BfModule::Visit(BfDeferStatement* deferStmt) else scope = mCurMethodState->mCurScope; + if ((scope == mCurMethodState->mCurScope) && (scope->mCloseNode == NULL)) + { + Warn(0, "This defer will immediately execute. Consider specifying a wider scope target such as 'defer::'", deferStmt->mDeferToken); + } + if (auto block = BfNodeDynCast(deferStmt->mTargetNode)) { if (deferStmt->mBind != NULL)