mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
203 lines
5 KiB
C++
203 lines
5 KiB
C++
#include "BeContext.h"
|
|
|
|
USING_NS_BF;
|
|
|
|
BeContext::BeContext()
|
|
{
|
|
mPointerSize = 8;
|
|
for (int primIdx = 0; primIdx < (int)BeTypeCode_COUNT; primIdx++)
|
|
mPrimitiveTypes[primIdx] = NULL;
|
|
}
|
|
|
|
void BeContext::NotImpl()
|
|
{
|
|
BF_FATAL("Not implemented");
|
|
}
|
|
|
|
BeType* BeContext::GetPrimitiveType(BeTypeCode typeCode)
|
|
{
|
|
if (typeCode == BeTypeCode_NullPtr)
|
|
{
|
|
return GetPointerTo(GetPrimitiveType(BeTypeCode_None));
|
|
}
|
|
|
|
if (mPrimitiveTypes[(int)typeCode] != NULL)
|
|
return mPrimitiveTypes[(int)typeCode];
|
|
|
|
BeType* primType = mTypes.Alloc<BeType>();
|
|
primType->mTypeCode = typeCode;
|
|
switch (typeCode)
|
|
{
|
|
case BeTypeCode_None:
|
|
primType->mSize = 0;
|
|
primType->mAlign = 0;
|
|
break;
|
|
case BeTypeCode_NullPtr:
|
|
primType->mSize = primType->mAlign = mPointerSize;
|
|
break;
|
|
case BeTypeCode_Boolean:
|
|
primType->mSize = primType->mAlign = 1;
|
|
break;
|
|
case BeTypeCode_Int8:
|
|
primType->mSize = primType->mAlign = 1;
|
|
break;
|
|
case BeTypeCode_Int16:
|
|
primType->mSize = primType->mAlign = 2;
|
|
break;
|
|
case BeTypeCode_Int32:
|
|
primType->mSize = primType->mAlign = 4;
|
|
break;
|
|
case BeTypeCode_Int64:
|
|
primType->mSize = primType->mAlign = 8;
|
|
break;
|
|
case BeTypeCode_Float:
|
|
primType->mSize = primType->mAlign = 4;
|
|
break;
|
|
case BeTypeCode_Double:
|
|
primType->mSize = primType->mAlign = 8;
|
|
break;
|
|
}
|
|
mPrimitiveTypes[(int)typeCode] = primType;
|
|
return primType;
|
|
}
|
|
|
|
BeStructType* BeContext::CreateStruct(const StringImpl& name)
|
|
{
|
|
BeStructType* structType = mTypes.Alloc<BeStructType>();
|
|
structType->mContext = this;
|
|
structType->mTypeCode = BeTypeCode_Struct;
|
|
structType->mName = name;
|
|
structType->mIsOpaque = true;
|
|
return structType;
|
|
}
|
|
|
|
BeStructType* BeContext::CreateStruct(const SizedArrayImpl<BeType*>& types)
|
|
{
|
|
BeStructType** valuePtr = NULL;
|
|
if (mAnonymousStructMap.TryGetValueWith(types, &valuePtr))
|
|
return *valuePtr;
|
|
|
|
Array<BeType*> key;
|
|
for (auto type : types)
|
|
key.Add(type);
|
|
|
|
BeStructType* structType = CreateStruct("");
|
|
SetStructBody(structType, types, false);
|
|
mAnonymousStructMap.TryAdd(key, structType);
|
|
return structType;
|
|
}
|
|
|
|
BePointerType* BeContext::GetPointerTo(BeType* beType)
|
|
{
|
|
if (beType->mPointerType == NULL)
|
|
{
|
|
BePointerType* pointerType = mTypes.Alloc<BePointerType>();
|
|
pointerType->mTypeCode = BeTypeCode_Pointer;
|
|
pointerType->mElementType = beType;
|
|
pointerType->mSize = mPointerSize;
|
|
pointerType->mAlign = mPointerSize;
|
|
beType->mPointerType = pointerType;
|
|
|
|
/*if (beType->IsSizedArray())
|
|
{
|
|
auto sizedArrayType = (BeSizedArrayType*)beType;
|
|
pointerType->mElementType = sizedArrayType->mElementType;
|
|
}*/
|
|
}
|
|
return beType->mPointerType;
|
|
}
|
|
|
|
void BeContext::SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed)
|
|
{
|
|
BF_ASSERT(structType->mMembers.IsEmpty());
|
|
|
|
int dataPos = 0;
|
|
for (auto& beType : types)
|
|
{
|
|
if (!packed)
|
|
{
|
|
int alignSize = beType->mAlign;
|
|
dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
|
|
}
|
|
BF_ASSERT(beType->mSize >= 0);
|
|
BeStructMember member;
|
|
member.mType = beType;
|
|
member.mByteOffset = dataPos;
|
|
dataPos += beType->mSize;
|
|
if (packed)
|
|
structType->mAlign = 1;
|
|
else
|
|
structType->mAlign = std::max(structType->mAlign, beType->mAlign);
|
|
structType->mMembers.push_back(member);
|
|
}
|
|
if (!packed)
|
|
{
|
|
int alignSize = structType->mAlign;
|
|
dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
|
|
}
|
|
structType->mSize = dataPos;
|
|
structType->mIsPacked = packed;
|
|
structType->mIsOpaque = false;
|
|
}
|
|
|
|
BeSizedArrayType* BeContext::CreateSizedArrayType(BeType* type, int length)
|
|
{
|
|
auto arrayType = mTypes.Alloc<BeSizedArrayType>();
|
|
arrayType->mContext = this;
|
|
arrayType->mTypeCode = BeTypeCode_SizedArray;
|
|
arrayType->mElementType = type;
|
|
arrayType->mLength = length;
|
|
arrayType->mSize = type->mSize * length;
|
|
arrayType->mAlign = type->mAlign;
|
|
return arrayType;
|
|
}
|
|
|
|
BeFunctionType* BeContext::CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg)
|
|
{
|
|
auto funcType = mTypes.Alloc<BeFunctionType>();
|
|
funcType->mTypeCode = BeTypeCode_Function;
|
|
funcType->mReturnType = returnType;
|
|
for (auto& paramType : paramTypes)
|
|
{
|
|
BeFunctionTypeParam funcParam;
|
|
funcParam.mType = paramType;
|
|
funcType->mParams.push_back(funcParam);
|
|
}
|
|
funcType->mIsVarArg = isVarArg;
|
|
return funcType;
|
|
}
|
|
|
|
bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
|
|
{
|
|
if (lhs == rhs)
|
|
return true;
|
|
|
|
if (lhs->mTypeCode != rhs->mTypeCode)
|
|
return false;
|
|
|
|
switch (lhs->mTypeCode)
|
|
{
|
|
case BeTypeCode_None:
|
|
case BeTypeCode_NullPtr:
|
|
case BeTypeCode_Boolean:
|
|
case BeTypeCode_Int8:
|
|
case BeTypeCode_Int16:
|
|
case BeTypeCode_Int32:
|
|
case BeTypeCode_Int64:
|
|
case BeTypeCode_Float:
|
|
case BeTypeCode_Double:
|
|
return true;
|
|
case BeTypeCode_Pointer:
|
|
return AreTypesEqual(((BePointerType*)lhs)->mElementType, ((BePointerType*)rhs)->mElementType);
|
|
case BeTypeCode_SizedArray:
|
|
{
|
|
auto lhsSizedArray = (BeSizedArrayType*)lhs;
|
|
auto rhsSizedArray = (BeSizedArrayType*)rhs;
|
|
if (lhsSizedArray->mLength != rhsSizedArray->mLength)
|
|
return false;
|
|
return AreTypesEqual(lhsSizedArray->mElementType, rhsSizedArray->mElementType);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|