1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Added a 'cast' intrinsic

This commit is contained in:
Brian Fiete 2020-02-19 13:16:33 -08:00
parent 660e7d8125
commit 1f20d76f94
14 changed files with 75 additions and 22 deletions

View file

@ -102,7 +102,7 @@ namespace System
} }
} }
[AttributeUsage(.Method /*1*/ | .Invocation)] [AttributeUsage(.Method | .Constructor | .Invocation | .Property)]
public struct InlineAttribute : Attribute public struct InlineAttribute : Attribute
{ {

View file

@ -13,7 +13,9 @@ namespace System
[AlwaysInclude] [AlwaysInclude]
static class Internal static class Internal
{ {
[Intrinsic("cast")]
public static extern Object UnsafeCastToObject(void* ptr); public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")]
public static extern void* UnsafeCastToPtr(Object obj); public static extern void* UnsafeCastToPtr(Object obj);
[NoReturn] [NoReturn]
public static extern void ThrowIndexOutOfRange(int stackOffset = 0); public static extern void ThrowIndexOutOfRange(int stackOffset = 0);

View file

@ -78,7 +78,10 @@ namespace System
[Inline] [Inline]
public static implicit operator Nullable<T>(T value) public static implicit operator Nullable<T>(T value)
{ {
return Nullable<T>(value); Nullable<T> result;
result.mHasValue = true;
result.mValue = value;
return result;
} }
[Inline] [Inline]

View file

@ -102,7 +102,7 @@ namespace System
} }
} }
[AttributeUsage(.Method /*1*/ | .Invocation | .Property)] [AttributeUsage(.Method | .Constructor | .Invocation | .Property)]
public struct InlineAttribute : Attribute public struct InlineAttribute : Attribute
{ {

View file

@ -13,7 +13,9 @@ namespace System
[AlwaysInclude] [AlwaysInclude]
static class Internal static class Internal
{ {
[Intrinsic("cast")]
public static extern Object UnsafeCastToObject(void* ptr); public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")]
public static extern void* UnsafeCastToPtr(Object obj); public static extern void* UnsafeCastToPtr(Object obj);
[NoReturn] [NoReturn]
public static extern void ThrowIndexOutOfRange(int stackOffset = 0); public static extern void ThrowIndexOutOfRange(int stackOffset = 0);

View file

@ -70,7 +70,10 @@ namespace System
[Inline] [Inline]
public static implicit operator Nullable<T>(T value) public static implicit operator Nullable<T>(T value)
{ {
return Nullable<T>(value); Nullable<T> result;
result.mHasValue = true;
result.mValue = value;
return result;
} }
[Inline] [Inline]

View file

@ -1902,7 +1902,9 @@ void BeIRCodeGen::HandleNextCmd()
case BfIRCmd_GetIntrinsic: case BfIRCmd_GetIntrinsic:
{ {
CMD_PARAM(int, intrinId); CMD_PARAM(int, intrinId);
CMD_PARAM(BeType*, returnType);
CMD_PARAM(CmdParamVec<BeType*>, paramTypes); CMD_PARAM(CmdParamVec<BeType*>, paramTypes);
auto intrin = mBeModule->mAlloc.Alloc<BeIntrinsic>(); auto intrin = mBeModule->mAlloc.Alloc<BeIntrinsic>();
intrin->mKind = (BfIRIntrinsic)intrinId; intrin->mKind = (BfIRIntrinsic)intrinId;
@ -1933,6 +1935,9 @@ void BeIRCodeGen::HandleNextCmd()
case BfIRIntrinsic_AtomicCmpStore: case BfIRIntrinsic_AtomicCmpStore:
case BfIRIntrinsic_AtomicCmpStore_Weak: case BfIRIntrinsic_AtomicCmpStore_Weak:
intrin->mReturnType = mBeContext->GetPrimitiveType(BeTypeCode_Boolean); intrin->mReturnType = mBeContext->GetPrimitiveType(BeTypeCode_Boolean);
break;
case BfIRIntrinsic_Cast:
intrin->mReturnType = returnType;
break; break;
} }

View file

@ -16209,6 +16209,15 @@ void BeMCContext::Generate(BeFunction* function)
result = scratchReg; result = scratchReg;
} }
break; 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: case BfIRIntrinsic_MemSet:
{ {
if (auto constVal = BeValueDynCast<BeConstant>(castedInst->mArgs[1].mValue)) if (auto constVal = BeValueDynCast<BeConstant>(castedInst->mArgs[1].mValue))

View file

@ -4232,9 +4232,9 @@ void BfIRBuilder::AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comin
NEW_CMD_INSERTED; NEW_CMD_INSERTED;
} }
BfIRFunction BfIRBuilder::GetIntrinsic(int intrinId, const BfSizedArray<BfIRType>& paramTypes) BfIRFunction BfIRBuilder::GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes)
{ {
BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinId, paramTypes); BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinId, returnType, paramTypes);
NEW_CMD_INSERTED; NEW_CMD_INSERTED;
return retVal; return retVal;
} }

View file

@ -403,6 +403,7 @@ enum BfIRIntrinsic : uint8
BfIRIntrinsic_AtomicXChg, BfIRIntrinsic_AtomicXChg,
BfIRIntrinsic_AtomicXor, BfIRIntrinsic_AtomicXor,
BfIRIntrinsic_BSwap, BfIRIntrinsic_BSwap,
BfIRIntrinsic_Cast,
BfIRIntrinsic_Cos, BfIRIntrinsic_Cos,
BfIRIntrinsic_Floor, BfIRIntrinsic_Floor,
BfIRIntrinsic_Free, BfIRIntrinsic_Free,
@ -1136,7 +1137,7 @@ public:
BfIRValue CreatePhi(BfIRType type, int incomingCount); BfIRValue CreatePhi(BfIRType type, int incomingCount);
void AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comingFrom); void AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comingFrom);
BfIRFunction GetIntrinsic(int intrinId, const BfSizedArray<BfIRType>& paramTypes); BfIRFunction GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes);
BfIRFunctionType MapMethod(BfMethodInstance* methodInstance); BfIRFunctionType MapMethod(BfMethodInstance* methodInstance);
BfIRFunctionType CreateFunctionType(BfIRType resultType, const BfSizedArray<BfIRType>& paramTypes, bool isVarArg = false); BfIRFunctionType CreateFunctionType(BfIRType resultType, const BfSizedArray<BfIRType>& paramTypes, bool isVarArg = false);
BfIRFunction CreateFunction(BfIRFunctionType funcType, BfIRLinkageType linkageType, const StringImpl& name); BfIRFunction CreateFunction(BfIRFunctionType funcType, BfIRLinkageType linkageType, const StringImpl& name);

View file

@ -143,6 +143,7 @@ static const BuiltinEntry gIntrinEntries[] =
{"atomic_xchg"}, {"atomic_xchg"},
{"atomic_xor"}, {"atomic_xor"},
{"bswap"}, {"bswap"},
{"cast"},
{"cos"}, {"cos"},
{"floor"}, {"floor"},
{"free"}, {"free"},
@ -1815,18 +1816,24 @@ void BfIRCodeGen::HandleNextCmd()
case BfIRCmd_GetIntrinsic: case BfIRCmd_GetIntrinsic:
{ {
CMD_PARAM(int, intrinId); CMD_PARAM(int, intrinId);
CMD_PARAM(llvm::Type*, returnType);
CMD_PARAM(CmdParamVec<llvm::Type*>, paramTypes); CMD_PARAM(CmdParamVec<llvm::Type*>, paramTypes);
bool isFakeIntrinsic = false; 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; isFakeIntrinsic = true;
} }
if (isFakeIntrinsic) if (isFakeIntrinsic)
{ {
auto intrinsicData = mAlloc.Alloc<BfIRIntrinsicData>();
intrinsicData->mIntrinsic = (BfIRIntrinsic)intrinId;
intrinsicData->mReturnType = returnType;
BfIRCodeGenEntry entry; BfIRCodeGenEntry entry;
entry.mKind = BfIRCodeGenEntryKind_FakeIntrinsic; entry.mKind = BfIRCodeGenEntryKind_IntrinsicData;
entry.mIntrinsic = (BfIRIntrinsic)intrinId; entry.mIntrinsicData = intrinsicData;
mResults.TryAdd(curId, entry); mResults.TryAdd(curId, entry);
break; break;
} }
@ -1863,6 +1870,7 @@ void BfIRCodeGen::HandleNextCmd()
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXChg, { (llvm::Intrinsic::ID)-1, -1}, // AtomicXChg,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXor, { (llvm::Intrinsic::ID)-1, -1}, // AtomicXor,
{ llvm::Intrinsic::bswap, -1}, { llvm::Intrinsic::bswap, -1},
{ (llvm::Intrinsic::ID) - 1, -1}, // cast,
{ llvm::Intrinsic::cos, -1}, { llvm::Intrinsic::cos, -1},
{ llvm::Intrinsic::floor, -1}, { llvm::Intrinsic::floor, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // free { (llvm::Intrinsic::ID)-1, -1}, // free
@ -2005,9 +2013,11 @@ void BfIRCodeGen::HandleNextCmd()
Read(func, &codeGenEntry); Read(func, &codeGenEntry);
CMD_PARAM(CmdParamVec<llvm::Value*>, args); CMD_PARAM(CmdParamVec<llvm::Value*>, 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:
case BfIRIntrinsic_AtomicCmpStore_Weak: case BfIRIntrinsic_AtomicCmpStore_Weak:
@ -2077,11 +2087,11 @@ void BfIRCodeGen::HandleNextCmd()
} }
auto inst = mIRBuilder->CreateAtomicCmpXchg(args[0], args[1], args[2], successOrdering, failOrdering); 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); inst->setWeak(true);
if ((memoryKind & BfIRAtomicOrdering_Volatile) != 0) if ((memoryKind & BfIRAtomicOrdering_Volatile) != 0)
inst->setVolatile(true); inst->setVolatile(true);
if (codeGenEntry->mIntrinsic == BfIRIntrinsic_AtomicCmpXChg) if (intrinsicData->mIntrinsic == BfIRIntrinsic_AtomicCmpXChg)
{ {
auto prevVal = mIRBuilder->CreateExtractValue(inst, 0); auto prevVal = mIRBuilder->CreateExtractValue(inst, 0);
SetResult(curId, prevVal); SetResult(curId, prevVal);
@ -2218,7 +2228,7 @@ void BfIRCodeGen::HandleNextCmd()
bool isFloat = args[1]->getType()->isFloatingPointTy(); bool isFloat = args[1]->getType()->isFloatingPointTy();
auto op = llvm::AtomicRMWInst::BinOp::Add; auto op = llvm::AtomicRMWInst::BinOp::Add;
switch (codeGenEntry->mIntrinsic) switch (intrinsicData->mIntrinsic)
{ {
case BfIRIntrinsic_AtomicAdd: case BfIRIntrinsic_AtomicAdd:
op = llvm::AtomicRMWInst::BinOp::Add; op = llvm::AtomicRMWInst::BinOp::Add;
@ -2293,7 +2303,7 @@ void BfIRCodeGen::HandleNextCmd()
llvm::Value* result = atomicRMW; llvm::Value* result = atomicRMW;
if ((memoryKind & BfIRAtomicOrdering_ReturnModified) != 0) if ((memoryKind & BfIRAtomicOrdering_ReturnModified) != 0)
{ {
switch (codeGenEntry->mIntrinsic) switch (intrinsicData->mIntrinsic)
{ {
case BfIRIntrinsic_AtomicAdd: case BfIRIntrinsic_AtomicAdd:
if (isFloat) if (isFloat)
@ -2310,7 +2320,7 @@ void BfIRCodeGen::HandleNextCmd()
case BfIRIntrinsic_AtomicUMin: case BfIRIntrinsic_AtomicUMin:
{ {
llvm::Value* cmpVal = NULL; llvm::Value* cmpVal = NULL;
switch (codeGenEntry->mIntrinsic) switch (intrinsicData->mIntrinsic)
{ {
case BfIRIntrinsic_AtomicMax: case BfIRIntrinsic_AtomicMax:
if (isFloat) if (isFloat)
@ -2360,6 +2370,11 @@ void BfIRCodeGen::HandleNextCmd()
SetResult(curId, result); SetResult(curId, result);
} }
break; break;
case BfIRIntrinsic_Cast:
{
SetResult(curId, mIRBuilder->CreateBitCast(args[0], intrinsicData->mReturnType));
}
break;
default: default:
Fail("Unhandled intrinsic"); Fail("Unhandled intrinsic");
} }

View file

@ -13,7 +13,14 @@ enum BfIRCodeGenEntryKind
BfIRCodeGenEntryKind_LLVMType, BfIRCodeGenEntryKind_LLVMType,
BfIRCodeGenEntryKind_LLVMBasicBlock, BfIRCodeGenEntryKind_LLVMBasicBlock,
BfIRCodeGenEntryKind_LLVMMetadata, BfIRCodeGenEntryKind_LLVMMetadata,
BfIRCodeGenEntryKind_FakeIntrinsic, BfIRCodeGenEntryKind_IntrinsicData,
};
class BfIRIntrinsicData
{
public:
BfIRIntrinsic mIntrinsic;
llvm::Type* mReturnType;
}; };
struct BfIRCodeGenEntry struct BfIRCodeGenEntry
@ -25,7 +32,7 @@ struct BfIRCodeGenEntry
llvm::Type* mLLVMType; llvm::Type* mLLVMType;
llvm::BasicBlock* mLLVMBlock; llvm::BasicBlock* mLLVMBlock;
llvm::MDNode* mLLVMMetadata; llvm::MDNode* mLLVMMetadata;
BfIRIntrinsic mIntrinsic; BfIRIntrinsicData* mIntrinsicData;
}; };
}; };
@ -54,6 +61,7 @@ class BfIRCodeGen : public BfIRCodeGenBase
public: public:
BfIRBuilder* mBfIRBuilder; BfIRBuilder* mBfIRBuilder;
BumpAllocator mAlloc;
BfTargetTriple mTargetTriple; BfTargetTriple mTargetTriple;
String mModuleName; String mModuleName;
llvm::LLVMContext* mLLVMContext; llvm::LLVMContext* mLLVMContext;

View file

@ -6096,7 +6096,7 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor
SizedArray<BfIRType, 2> paramTypes; SizedArray<BfIRType, 2> paramTypes;
for (auto& param : methodInstance->mParams) for (auto& param : methodInstance->mParams)
paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType)); paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
return mBfIRBuilder->GetIntrinsic(intrinId, paramTypes); return mBfIRBuilder->GetIntrinsic(intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
} }
else if (reportFailure) else if (reportFailure)
error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str()); error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str());

View file

@ -6281,6 +6281,11 @@ void BfModule::Visit(BfDeferStatement* deferStmt)
else else
scope = mCurMethodState->mCurScope; 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<BfBlock>(deferStmt->mTargetNode)) if (auto block = BfNodeDynCast<BfBlock>(deferStmt->mTargetNode))
{ {
if (deferStmt->mBind != NULL) if (deferStmt->mBind != NULL)