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

Linux fixes, CTFE progress

This commit is contained in:
Brian Fiete 2020-12-14 10:20:44 -08:00
parent 52a441f486
commit 7ddd9a205d
3 changed files with 253 additions and 151 deletions

View file

@ -4986,7 +4986,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{ {
if (mModule->mIsConstModule) if (mModule->mIsConstModule)
{ {
mModule->mCompiler->mCEMachine->QueueMethod(methodInstance); mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func);
} }
else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0) else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0)
{ {

View file

@ -2,7 +2,7 @@
#include "BfModule.h" #include "BfModule.h"
#include "BfCompiler.h" #include "BfCompiler.h"
#include "BfIRBuilder.h" #include "BfIRBuilder.h"
#include "..\Backend\BeIRCodeGen.h" #include "../Backend/BeIRCodeGen.h"
USING_NS_BF; USING_NS_BF;
@ -17,51 +17,51 @@ struct CeOpInfo
}; };
#define CEOPINFO_SIZED_1(OPNAME, OPINFOA) \ #define CEOPINFO_SIZED_1(OPNAME, OPINFOA) \
{OPNAME##"_8", OPINFOA}, \ {OPNAME "_8", OPINFOA}, \
{OPNAME##"_16", OPINFOA}, \ {OPNAME "_16", OPINFOA}, \
{OPNAME##"_32", OPINFOA}, \ {OPNAME "_32", OPINFOA}, \
{OPNAME##"_64", OPINFOA}, \ {OPNAME "_64", OPINFOA}, \
{OPNAME##"_X", OPINFOA, CEOI_IMM32} {OPNAME "_X", OPINFOA, CEOI_IMM32}
#define CEOPINFO_SIZED_2(OPNAME, OPINFOA, OPINFOB) \ #define CEOPINFO_SIZED_2(OPNAME, OPINFOA, OPINFOB) \
{OPNAME##"_8", OPINFOA, OPINFOB}, \ {OPNAME "_8", OPINFOA, OPINFOB}, \
{OPNAME##"_16", OPINFOA, OPINFOB}, \ {OPNAME "_16", OPINFOA, OPINFOB}, \
{OPNAME##"_32", OPINFOA, OPINFOB}, \ {OPNAME "_32", OPINFOA, OPINFOB}, \
{OPNAME##"_64", OPINFOA, OPINFOB}, \ {OPNAME "_64", OPINFOA, OPINFOB}, \
{OPNAME##"_X", OPINFOA, CEOI_IMM32, OPINFOB} {OPNAME "_X", OPINFOA, CEOI_IMM32, OPINFOB}
#define CEOPINFO_SIZED_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ #define CEOPINFO_SIZED_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_16", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_32", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_64", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_64", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_X", OPINFOA, CEOI_IMM32, OPINFOB, OPINFOC} {OPNAME "_X", OPINFOA, CEOI_IMM32, OPINFOB, OPINFOC}
#define CEOPINFO_SIZED_NUMERIC(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ #define CEOPINFO_SIZED_NUMERIC(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I32", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I64", OPINFOA, OPINFOB, OPINFOC} {OPNAME "_I64", OPINFOA, OPINFOB, OPINFOC}
#define CEOPINFO_SIZED_NUMERIC_PLUSF_2(OPNAME, OPINFOA, OPINFOB) \ #define CEOPINFO_SIZED_NUMERIC_PLUSF_2(OPNAME, OPINFOA, OPINFOB) \
{OPNAME##"_I8", OPINFOA, OPINFOB}, \ {OPNAME "_I8", OPINFOA, OPINFOB}, \
{OPNAME##"_I16", OPINFOA, OPINFOB}, \ {OPNAME "_I16", OPINFOA, OPINFOB}, \
{OPNAME##"_I32", OPINFOA, OPINFOB}, \ {OPNAME "_I32", OPINFOA, OPINFOB}, \
{OPNAME##"_I64", OPINFOA, OPINFOB}, \ {OPNAME "_I64", OPINFOA, OPINFOB}, \
{OPNAME##"_F32", OPINFOA, OPINFOB}, \ {OPNAME "_F32", OPINFOA, OPINFOB}, \
{OPNAME##"_F64", OPINFOA, OPINFOB} {OPNAME "_F64", OPINFOA, OPINFOB}
#define CEOPINFO_SIZED_NUMERIC_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ #define CEOPINFO_SIZED_NUMERIC_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I32", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I64", OPINFOA, OPINFOB, OPINFOC} {OPNAME "_I64", OPINFOA, OPINFOB, OPINFOC}
#define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \ #define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I32", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I64", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_I64", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_F32", OPINFOA, OPINFOB, OPINFOC}, \ {OPNAME "_F32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_F64", OPINFOA, OPINFOB, OPINFOC} {OPNAME "_F64", OPINFOA, OPINFOB, OPINFOC}
static CeOpInfo gOpInfo[] = static CeOpInfo gOpInfo[] =
{ {
@ -70,8 +70,8 @@ static CeOpInfo gOpInfo[] =
{"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},
{"FrameAddr32", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr_32", CEOI_FrameRef, CEOI_FrameRef},
{"FrameAddr64", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr_64", CEOI_FrameRef, CEOI_FrameRef},
{"Zero", CEOI_FrameRef, CEOI_IMM32}, {"Zero", CEOI_FrameRef, CEOI_IMM32},
{"Const_8", CEOI_FrameRef, CEOI_IMM8}, {"Const_8", CEOI_FrameRef, CEOI_IMM8},
@ -91,12 +91,12 @@ static CeOpInfo gOpInfo[] =
{"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef}, {"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef},
{"AddConst_I8", CEOI_FrameRef, CEOI_IMM8}, {"AddConst_I8", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM8},
{"AddConst_I16", CEOI_FrameRef, CEOI_IMM16}, {"AddConst_I16", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM16},
{"AddConst_I32", CEOI_FrameRef, CEOI_IMM32}, {"AddConst_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32},
{"AddConst_I64", CEOI_FrameRef, CEOI_IMM64}, {"AddConst_I64", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM64},
{"AddConst_F32", CEOI_FrameRef, CEOI_IMMF32}, {"AddConst_F32", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMMF32},
{"AddConst_F64", CEOI_FrameRef, CEOI_IMMF64}, {"AddConst_F64", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMMF64},
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Add", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), CEOPINFO_SIZED_NUMERIC_PLUSF_3("Add", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Sub", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef), CEOPINFO_SIZED_NUMERIC_PLUSF_3("Sub", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
@ -266,13 +266,8 @@ void CeBuilder::Fail(const StringImpl& str)
return; return;
String errStr = StrFormat("Failure during const code generation of %s: %s", mBeFunction->mName.c_str(), str.c_str()); String errStr = StrFormat("Failure during const code generation of %s: %s", mBeFunction->mName.c_str(), str.c_str());
if (mCurDbgLoc != NULL) if (mCurDbgLoc != NULL)
{ errStr += StrFormat(" at line %d:%d in %s", mCurDbgLoc->mLine + 1, mCurDbgLoc->mColumn + 1, mCurDbgLoc->GetDbgFile()->mFileName.c_str());
BeDumpContext dumpCtx;
errStr += "\n DbgLoc : ";
dumpCtx.ToString(errStr, mCurDbgLoc);
}
mCeFunction->mGenError = errStr; mCeFunction->mGenError = errStr;
} }
@ -292,6 +287,11 @@ void CeBuilder::Emit(int32 val)
*(int32*)mCeFunction->mCode.GrowUninitialized(4) = val; *(int32*)mCeFunction->mCode.GrowUninitialized(4) = val;
} }
void CeBuilder::Emit(int64 val)
{
*(int64*)mCeFunction->mCode.GrowUninitialized(8) = val;
}
void CeBuilder::Emit(bool val) void CeBuilder::Emit(bool val)
{ {
BF_FATAL("Invalid emit"); BF_FATAL("Invalid emit");
@ -530,23 +530,24 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
break; break;
case BeCastConstant::TypeId: case BeCastConstant::TypeId:
{ {
// auto constant = (BeCastConstant*)value; auto constant = (BeCastConstant*)value;
//
// CeOperand mcOperand; CeOperand mcOperand;
// auto relTo = GetOperand(constant->mTarget); auto relTo = GetOperand(constant->mTarget);
// if (relTo.mKind == CeOperandKind_Immediate_Null) if (relTo.mKind == CeOperandKind_Immediate)
// { {
// mcOperand.mKind = CeOperandKind_Immediate_Null; mcOperand.mKind = CeOperandKind_Immediate;
// mcOperand.mType = constant->mType; mcOperand.mType = constant->mType;
// return mcOperand; return mcOperand;
// } }
//
//Fail("Invalid operand");
// mcOperand = AllocVirtualReg(constant->mType); // mcOperand = AllocVirtualReg(constant->mType);
// auto vregInfo = GetVRegInfo(mcOperand); // auto vregInfo = GetVRegInfo(mcOperand);
// vregInfo->mDefOnFirstUse = true; // vregInfo->mDefOnFirstUse = true;
// vregInfo->mRelTo = relTo; // vregInfo->mRelTo = relTo;
// vregInfo->mIsExpr = true; // vregInfo->mIsExpr = true;
//
//return mcOperand; //return mcOperand;
} }
break; break;
@ -763,8 +764,10 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
if ((operand.mKind == CeOperandKind_AllocaAddr) && (!allowAlloca)) if ((operand.mKind == CeOperandKind_AllocaAddr) && (!allowAlloca))
{ {
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen; auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
auto result = FrameAlloc(mIntPtrType);
Emit((mPtrSize == 4) ? CeOp_FrameAddr32 : CeOp_FrameAddr64); auto ptrType = mCeMachine->GetBeContext()->GetPointerTo(operand.mType);
auto result = FrameAlloc(ptrType);
Emit((mPtrSize == 4) ? CeOp_FrameAddr_32 : CeOp_FrameAddr_64);
EmitFrameOffset(result); EmitFrameOffset(result);
Emit((int32)operand.mFrameOfs); Emit((int32)operand.mFrameOfs);
return result; return result;
@ -1386,28 +1389,53 @@ void CeBuilder::Build()
{ {
auto castedInst = (BeGEPInst*)inst; auto castedInst = (BeGEPInst*)inst;
auto mcVal = GetOperand(castedInst->mPtr); auto ceVal = GetOperand(castedInst->mPtr);
auto mcIdx0 = GetOperand(castedInst->mIdx0, false, true); auto ceIdx0 = GetOperand(castedInst->mIdx0, false, true);
BePointerType* ptrType = (BePointerType*)mcVal.mType; BePointerType* ptrType = (BePointerType*)ceVal.mType;
BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer); BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
result = mcVal; result = ceVal;
if (castedInst->mIdx1 != NULL) if (castedInst->mIdx1 != NULL)
{ {
// We assume we never do both an idx0 and idx1 at once. Fix if we change that. // We assume we never do both an idx0 and idx1 at once. Fix if we change that.
BF_ASSERT(castedInst->mIdx0); BF_ASSERT(castedInst->mIdx0);
auto mcIdx1 = GetOperand(castedInst->mIdx1); auto ceIdx1 = GetOperand(castedInst->mIdx1, false, true);
if (!mcIdx1.IsImmediate()) if (!ceIdx1.IsImmediate())
{ {
// This path is used when we have a const array that gets indexed by a non-const index value // This path is used when we have a const array that gets indexed by a non-const index value
// if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray) if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray)
// { {
// auto arrayType = (BeSizedArrayType*)ptrType->mElementType; auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
//
// auto elementPtrType = mModule->mContext->GetPointerTo(arrayType->mElementType); auto elementPtrType = beModule->mContext->GetPointerTo(arrayType->mElementType);
//
if (ceIdx1.IsImmediate())
{
if (ceIdx1.mImmediate == 0)
{
result = ceVal;
result.mType = elementPtrType;
}
else
{
auto ptrValue = FrameAlloc(elementPtrType);
result = ptrValue;
result = FrameAlloc(elementPtrType);
Emit((CeOp)(CeOp_AddConst_I32));
EmitFrameOffset(result);
EmitFrameOffset(ceVal);
Emit((int32)(ceIdx1.mImmediate * arrayType->mElementType->mSize));
}
}
else
{
auto ptrValue = FrameAlloc(elementPtrType);
result = ptrValue;
}
// auto ptrValue = AllocVirtualReg(elementPtrType); // auto ptrValue = AllocVirtualReg(elementPtrType);
// auto ptrInfo = GetVRegInfo(ptrValue); // auto ptrInfo = GetVRegInfo(ptrValue);
// ptrInfo->mIsExpr = true; // ptrInfo->mIsExpr = true;
@ -1432,21 +1460,19 @@ void CeBuilder::Build()
// CreateDefineVReg(result); // CreateDefineVReg(result);
// //TODO: Always correct? // //TODO: Always correct?
// result.mKind = BeMCOperandKind_VReg; // result.mKind = BeMCOperandKind_VReg;
// }
// } else
// else
// SoftFail("Invalid GEP", inst->mDbgLoc);
Fail("Invalid GEP"); Fail("Invalid GEP");
} }
else else
{ {
BF_ASSERT(mcIdx1.IsImmediate()); BF_ASSERT(ceIdx1.IsImmediate());
int byteOffset = 0; int byteOffset = 0;
BeType* elementType = NULL; BeType* elementType = NULL;
if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct) if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct)
{ {
BeStructType* structType = (BeStructType*)ptrType->mElementType; BeStructType* structType = (BeStructType*)ptrType->mElementType;
auto& structMember = structType->mMembers[mcIdx1.mImmediate]; auto& structMember = structType->mMembers[ceIdx1.mImmediate];
elementType = structMember.mType; elementType = structMember.mType;
byteOffset = structMember.mByteOffset; byteOffset = structMember.mByteOffset;
} }
@ -1454,13 +1480,13 @@ void CeBuilder::Build()
{ {
auto arrayType = (BeSizedArrayType*)ptrType->mElementType; auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
elementType = arrayType->mElementType; elementType = arrayType->mElementType;
byteOffset = mcIdx1.mImmediate * elementType->mSize; byteOffset = ceIdx1.mImmediate * elementType->mSize;
} }
else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector) else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector)
{ {
auto arrayType = (BeVectorType*)ptrType->mElementType; auto arrayType = (BeVectorType*)ptrType->mElementType;
elementType = arrayType->mElementType; elementType = arrayType->mElementType;
byteOffset = mcIdx1.mImmediate * elementType->mSize; byteOffset = ceIdx1.mImmediate * elementType->mSize;
} }
else else
{ {
@ -1469,12 +1495,18 @@ void CeBuilder::Build()
auto elementPtrType = beModule->mContext->GetPointerTo(elementType); auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
if (byteOffset != 0)
{
//result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1); result = FrameAlloc(elementPtrType);
// The def is primary to create a single 'master location' for the GEP vreg to become legalized before use Emit((CeOp)(CeOp_AddConst_I32));
//CreateDefineVReg(result); EmitFrameOffset(result);
//result.mKind = BeMCOperandKind_VReg; EmitFrameOffset(ceVal);
Emit((int32)byteOffset);
}
else
{
result.mType = elementPtrType;
}
} }
} }
else else
@ -1701,10 +1733,15 @@ void CeBuilder::Build()
*((int32*)(&mCeFunction->mCode[0] + jumpEntry.mEmitPos)) = ceBlock.mEmitOfs - jumpEntry.mEmitPos - 4; *((int32*)(&mCeFunction->mCode[0] + jumpEntry.mEmitPos)) = ceBlock.mEmitOfs - jumpEntry.mEmitPos - 4;
} }
if (mCeFunction->mCode.size() == 0)
{
Fail("No method definition available");
return;
}
if (mCeFunction->mGenError.IsEmpty())
mCeFunction->mFailed = false; mCeFunction->mFailed = false;
mCeFunction->mFrameSize = mFrameSize; mCeFunction->mFrameSize = mFrameSize;
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -1724,9 +1761,9 @@ CeMachine::~CeMachine()
delete mCeModule; delete mCeModule;
} }
void CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{ {
mCurModule->Fail(str, mCurTargetSrc); return mCurModule->Fail(str, mCurTargetSrc);
} }
void CeMachine::Init() void CeMachine::Init()
@ -1746,6 +1783,20 @@ void CeMachine::Init()
mCeModule->mWantsIRIgnoreWrites = false; mCeModule->mWantsIRIgnoreWrites = false;
} }
BeContext* CeMachine::GetBeContext()
{
if (mCeModule == NULL)
return NULL;
return mCeModule->mBfIRBuilder->mBeIRCodeGen->mBeContext;
}
BeModule* CeMachine::GetBeModule()
{
if (mCeModule == NULL)
return NULL;
return mCeModule->mBfIRBuilder->mBeIRCodeGen->mBeModule;
}
void CeMachine::CompileStarted() void CeMachine::CompileStarted()
{ {
mRevision++; mRevision++;
@ -1843,6 +1894,14 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
return false; \ return false; \
} }
// This check will fail for addresses < 64K (null pointer), or out-of-bounds
#define CE_CHECKADDR(ADDR, SIZE) \
if (((ADDR) - 0x10000) + sizeof(uint32) > (BF_CE_STACK_SIZE - 0x10000)) \
{ \
_Fail("Access violation"); \
return false; \
}
#define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1) #define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1)
#define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1)) #define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1))
#define CEOP_BIN(OP, T) \ #define CEOP_BIN(OP, T) \
@ -1852,6 +1911,13 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
auto rhs = CE_GETFRAME(T); \ auto rhs = CE_GETFRAME(T); \
result = lhs OP rhs; \ result = lhs OP rhs; \
} }
#define CEOP_BIN_CONST(OP, T) \
{ \
auto& result = CE_GETFRAME(T); \
auto lhs = CE_GETFRAME(T); \
auto rhs = CE_GETINST(T); \
result = lhs OP rhs; \
}
#define CEOP_UNARY(OP, T) \ #define CEOP_UNARY(OP, T) \
{ \ { \
auto& result = CE_GETFRAME(T); \ auto& result = CE_GETFRAME(T); \
@ -1871,6 +1937,20 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
auto val = CE_GETFRAME(TFROM); \ auto val = CE_GETFRAME(TFROM); \
result = (TTO)val; \ result = (TTO)val; \
} }
#define CE_LOAD(T) \
{ \
auto& result = CE_GETFRAME(T); \
auto ceAddr = CE_GETFRAME(uint32); \
CE_CHECKADDR(ceAddr, sizeof(T)); \
result = *(T*)(memStart + ceAddr); \
}
#define CE_STORE(T) \
{ \
auto val = CE_GETFRAME(T); \
auto ceAddr = CE_GETFRAME(uint32); \
CE_CHECKADDR(ceAddr, sizeof(T)); \
*(T*)(memStart + ceAddr) = val; \
}
#define CEOP_MOVE(T) \ #define CEOP_MOVE(T) \
{ \ { \
auto val = CE_GETFRAME(T); \ auto val = CE_GETFRAME(T); \
@ -1895,7 +1975,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
{ {
CeFunction* ceFunction = startFunction; CeFunction* ceFunction = startFunction;
uint8* memStart = &mMemory[0]; uint8* memStart = &mMemory[0];
uint8* instPtr = &ceFunction->mCode[0]; uint8* instPtr = (ceFunction->mCode.IsEmpty()) ? NULL : &ceFunction->mCode[0];
uint8* stackPtr = startStackPtr; uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr; uint8* framePtr = startFramePtr;
@ -1914,6 +1994,19 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
Fail(_GetCurFrame(), error); Fail(_GetCurFrame(), error);
}; };
auto _CheckFunction = [&](CeFunction* checkFunction)
{
if (!checkFunction->mFailed)
return true;
auto error = Fail(_GetCurFrame(), "Method call failed");
if ((error != NULL) && (!checkFunction->mGenError.IsEmpty()))
mCeModule->mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError);
return false;
};
if (!_CheckFunction(ceFunction))
return false;
int callCount = 0; int callCount = 0;
while (true) while (true)
@ -1957,7 +2050,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
instPtr += relOfs - 4; instPtr += relOfs - 4;
} }
break; break;
case CeOp_FrameAddr64: case CeOp_FrameAddr_64:
{ {
auto& result = CE_GETFRAME(int64); auto& result = CE_GETFRAME(int64);
auto addr = &CE_GETFRAME(uint8); auto addr = &CE_GETFRAME(uint8);
@ -2004,17 +2097,16 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
} }
break; break;
case CeOp_Load_32: case CeOp_Load_32:
{ CE_LOAD(uint32);
auto& result = CE_GETFRAME(uint32); break;
auto ceAddr = CE_GETFRAME(uint32); case CeOp_Load_64:
// This check will fail for addresses < 256 (null pointer), or out-of-bounds the other direction CE_LOAD(uint64);
if ((ceAddr - 256) + sizeof(uint32) > (BF_CE_STACK_SIZE - 256)) break;
{ case CeOp_Store_32:
//TODO: Throw error CE_STORE(uint32);
return false; break;
} case CeOp_Store_64:
result = *(uint32*)(memStart + ceAddr); CE_STORE(uint64);
}
break; break;
case CeOp_Move_8: case CeOp_Move_8:
CEOP_MOVE(int8); CEOP_MOVE(int8);
@ -2076,6 +2168,15 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
{ {
callEntry.mFunction = NULL; callEntry.mFunction = NULL;
mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction); mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction);
if ((callEntry.mFunction != NULL) && (!callEntry.mFunction->mInitialized))
{
PrepareFunction(callEntry.mFunction);
}
if (!_CheckFunction(callEntry.mFunction))
return false;
callEntry.mBindRevision = mRevision; callEntry.mBindRevision = mRevision;
} }
@ -2106,6 +2207,12 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
case CeOp_Conv_I32_I64: case CeOp_Conv_I32_I64:
CE_CAST(int32, int64); CE_CAST(int32, int64);
break; break;
case CeOp_AddConst_I32:
CEOP_BIN_CONST(+, int32);
break;
case CeOp_AddConst_I64:
CEOP_BIN_CONST(+, int64);
break;
case CeOp_Add_I32: case CeOp_Add_I32:
CEOP_BIN(+, int32); CEOP_BIN(+, int32);
break; break;
@ -2184,17 +2291,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction)
} }
} }
void CeMachine::ProcessWorkQueue() CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added)
{
while (!mWorkQueue.IsEmpty())
{
auto ceFunction = mWorkQueue.back();
mWorkQueue.pop_back();
PrepareFunction(ceFunction);
}
}
CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, bool& added)
{ {
CeFunction** functionValuePtr = NULL; CeFunction** functionValuePtr = NULL;
CeFunction* ceFunction = NULL; CeFunction* ceFunction = NULL;
@ -2209,6 +2306,14 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, bool& added
ceFunction = new CeFunction(); ceFunction = new CeFunction();
ceFunction->mMethodInstance = methodInstance; ceFunction->mMethodInstance = methodInstance;
if ((func) && (!func.IsConst()) && (!func.IsFake()))
{
if (auto function = BeValueDynCast<BeFunction>(mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(func.mId)))
{
mNamedFunctionMap[function->mName] = ceFunction;
}
}
*functionValuePtr = ceFunction; *functionValuePtr = ceFunction;
} }
else else
@ -2216,12 +2321,10 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, bool& added
return ceFunction; return ceFunction;
} }
void CeMachine::QueueMethod(BfMethodInstance* methodInstance) void CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func)
{ {
bool added = false; bool added = false;
auto ceFunction = GetFunction(methodInstance, added); auto ceFunction = GetFunction(methodInstance, func, added);
if (added)
mWorkQueue.Add(ceFunction);
} }
BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags) BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags)
@ -2249,13 +2352,9 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
} }
bool added = false; bool added = false;
CeFunction* ceFunction = GetFunction(methodInstance, added); CeFunction* ceFunction = GetFunction(methodInstance, BfIRValue(), added);
if (!ceFunction->mInitialized) if (!ceFunction->mInitialized)
{
PrepareFunction(ceFunction); PrepareFunction(ceFunction);
ProcessWorkQueue();
}
BF_ASSERT(mWorkQueue.IsEmpty());
mMemory.Resize(BF_CE_STACK_SIZE); mMemory.Resize(BF_CE_STACK_SIZE);
auto stackPtr = &mMemory[0] + mMemory.mSize; auto stackPtr = &mMemory[0] + mMemory.mSize;

View file

@ -6,6 +6,8 @@
NS_BF_BEGIN NS_BF_BEGIN
class BfMethodInstance; class BfMethodInstance;
class BeModule;
class BeContext;
class BeDbgLoc; class BeDbgLoc;
class BeType; class BeType;
class BeValue; class BeValue;
@ -46,8 +48,8 @@ enum CeOp : int16
CeOp_JmpIf, CeOp_JmpIf,
CeOp_JmpIfNot, CeOp_JmpIfNot,
CeOp_FrameAddr32, CeOp_FrameAddr_32,
CeOp_FrameAddr64, CeOp_FrameAddr_64,
CeOp_Zero, CeOp_Zero,
CEOP_SIZED(Const), CEOP_SIZED(Const),
@ -284,6 +286,7 @@ public:
void Emit(uint8 val); void Emit(uint8 val);
void Emit(CeOp val); void Emit(CeOp val);
void Emit(int32 val); void Emit(int32 val);
void Emit(int64 val);
void Emit(bool val); void Emit(bool val);
void Emit(void* ptr, int size); void Emit(void* ptr, int size);
void EmitJump(CeOp op, const CeOperand& block); void EmitJump(CeOp op, const CeOperand& block);
@ -328,7 +331,6 @@ public:
Array<CeFrame> mCallStack; Array<CeFrame> mCallStack;
Array<uint8> mMemory; Array<uint8> mMemory;
uint8* mStackMin; uint8* mStackMin;
Array<CeFunction*> mWorkQueue;
BfAstNode* mCurTargetSrc; BfAstNode* mCurTargetSrc;
BfModule* mCurModule; BfModule* mCurModule;
@ -337,9 +339,11 @@ public:
CeMachine(BfCompiler* compiler); CeMachine(BfCompiler* compiler);
~CeMachine(); ~CeMachine();
void Fail(const CeFrame& curFrame, const StringImpl& error); BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
void Init(); void Init();
BeContext* GetBeContext();
BeModule* GetBeModule();
void RemoveMethod(BfMethodInstance* methodInstance); void RemoveMethod(BfMethodInstance* methodInstance);
int GetConstantSize(BfConstant* constant); int GetConstantSize(BfConstant* constant);
void WriteConstant(uint8* ptr, BfConstant* constant); void WriteConstant(uint8* ptr, BfConstant* constant);
@ -347,12 +351,11 @@ public:
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr); bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
void PrepareFunction(CeFunction* methodInstance); void PrepareFunction(CeFunction* methodInstance);
void ProcessWorkQueue(); CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
CeFunction* GetFunction(BfMethodInstance* methodInstance, bool& added);
public: public:
void CompileStarted(); void CompileStarted();
void QueueMethod(BfMethodInstance* methodInstance); void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags); BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
}; };