mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Linux fixes, CTFE progress
This commit is contained in:
parent
52a441f486
commit
7ddd9a205d
3 changed files with 253 additions and 151 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,24 +530,25 @@ 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;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// mcOperand = AllocVirtualReg(constant->mType);
|
//Fail("Invalid operand");
|
||||||
// auto vregInfo = GetVRegInfo(mcOperand);
|
// mcOperand = AllocVirtualReg(constant->mType);
|
||||||
// vregInfo->mDefOnFirstUse = true;
|
// auto vregInfo = GetVRegInfo(mcOperand);
|
||||||
// vregInfo->mRelTo = relTo;
|
// vregInfo->mDefOnFirstUse = true;
|
||||||
// vregInfo->mIsExpr = true;
|
// vregInfo->mRelTo = relTo;
|
||||||
//
|
// vregInfo->mIsExpr = true;
|
||||||
// return mcOperand;
|
|
||||||
|
//return mcOperand;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BeConstant::TypeId:
|
case BeConstant::TypeId:
|
||||||
|
@ -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;
|
||||||
|
@ -985,7 +988,7 @@ void CeBuilder::HandleParams()
|
||||||
}
|
}
|
||||||
|
|
||||||
void CeBuilder::Build()
|
void CeBuilder::Build()
|
||||||
{
|
{
|
||||||
mCeFunction->mFailed = true;
|
mCeFunction->mFailed = true;
|
||||||
|
|
||||||
auto methodInstance = mCeFunction->mMethodInstance;
|
auto methodInstance = mCeFunction->mMethodInstance;
|
||||||
|
@ -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
|
Fail("Invalid GEP");
|
||||||
// SoftFail("Invalid GEP", inst->mDbgLoc);
|
|
||||||
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,27 +1480,33 @@ 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
|
||||||
{
|
{
|
||||||
Fail("Invalid gep target");
|
Fail("Invalid gep target");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
|
auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1);
|
if (byteOffset != 0)
|
||||||
// The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
|
{
|
||||||
//CreateDefineVReg(result);
|
result = FrameAlloc(elementPtrType);
|
||||||
//result.mKind = BeMCOperandKind_VReg;
|
Emit((CeOp)(CeOp_AddConst_I32));
|
||||||
|
EmitFrameOffset(result);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCeFunction->mFailed = false;
|
if (mCeFunction->mCode.size() == 0)
|
||||||
mCeFunction->mFrameSize = mFrameSize;
|
{
|
||||||
|
Fail("No method definition available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCeFunction->mGenError.IsEmpty())
|
||||||
|
mCeFunction->mFailed = false;
|
||||||
|
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,10 +1975,10 @@ 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;
|
||||||
|
|
||||||
auto _GetCurFrame = [&]()
|
auto _GetCurFrame = [&]()
|
||||||
{
|
{
|
||||||
CeFrame ceFrame;
|
CeFrame ceFrame;
|
||||||
|
@ -1913,7 +1993,20 @@ 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;
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -327,8 +330,7 @@ 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;
|
||||||
|
@ -336,23 +338,24 @@ public:
|
||||||
public:
|
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);
|
||||||
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);
|
||||||
|
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue