From 8aef7275d063f3ebbd26d3d78e5b5085c667bfa0 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sun, 28 Aug 2022 07:41:35 -0700 Subject: [PATCH] Added `Compiler.Align` --- BeefLibs/corlib/src/Compiler.bf | 7 +++++ BeefLibs/corlib/src/Interop.bf | 1 + IDEHelper/Compiler/BfModuleTypeUtils.cpp | 38 ++++++++++++++++-------- IDEHelper/Compiler/CeMachine.cpp | 15 ++++++++++ IDEHelper/Compiler/CeMachine.h | 7 ++++- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index f98559b5..9a97cd26 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -300,6 +300,7 @@ namespace System } static extern void Comptime_SetReturnType(int32 typeId); + static extern void Comptime_Align(int32 typeId, int32 align); static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str); static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags); static extern void Comptime_EmitTypeBody(int32 typeId, StringView text); @@ -328,6 +329,12 @@ namespace System Comptime_SetReturnType((.)type.TypeId); } + [Comptime(OnlyFromComptime=true)] + public static void Align(Type type, int align) + { + Comptime_Align((.)type.TypeId, (.)align); + } + [Comptime(OnlyFromComptime=true)] public static void EmitAddInterface(Type owner, Type iface) { diff --git a/BeefLibs/corlib/src/Interop.bf b/BeefLibs/corlib/src/Interop.bf index dbfe793b..1dc4728d 100644 --- a/BeefLibs/corlib/src/Interop.bf +++ b/BeefLibs/corlib/src/Interop.bf @@ -108,6 +108,7 @@ namespace System if ((field.FieldType == null) || (!field.FieldType.IsSizedArray) || (field.FieldType.Size != 0)) Runtime.FatalError("Type must end in a zero-sized array"); var elementType = (field.FieldType as SizedArrayType).UnderlyingType; + Compiler.Align(type, elementType.Align); Compiler.EmitTypeBody(type, scope $""" public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + Math.Align(typeof(Self).Size, typeof({elementType}).Align))); public static int GetAllocSize(int arrayCount) => Math.Align(typeof(Self).Size, typeof({elementType}).Align) + typeof({elementType}).Size*arrayCount; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 87811127..34684377 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2544,19 +2544,24 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* } } } - else if (ceEmitContext->HasEmissions()) + else { - if (typeInstance->mCeTypeInfo == NULL) - typeInstance->mCeTypeInfo = new BfCeTypeInfo(); - if (typeInstance->mCeTypeInfo->mNext == NULL) - typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + if (ceEmitContext->HasEmissions()) + { + if (typeInstance->mCeTypeInfo == NULL) + typeInstance->mCeTypeInfo = new BfCeTypeInfo(); + if (typeInstance->mCeTypeInfo->mNext == NULL) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); - BfCeTypeEmitEntry entry; - entry.mEmitData = ceEmitContext->mEmitData; - typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; + BfCeTypeEmitEntry entry; + entry.mEmitData = ceEmitContext->mEmitData; + typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; + typeInstance->mCeTypeInfo->mNext->mAlign = BF_MAX(typeInstance->mCeTypeInfo->mNext->mAlign, ceEmitContext->mAlign); + } + + if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL)) + typeInstance->mCeTypeInfo->mFailed = true; } - else if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL)) - typeInstance->mCeTypeInfo->mFailed = true; if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish)) { @@ -5088,6 +5093,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap; typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash; + typeInstance->mCeTypeInfo->mAlign = typeInstance->mCeTypeInfo->mNext->mAlign; } delete typeInstance->mCeTypeInfo->mNext; @@ -5113,8 +5119,11 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy typeInstance->mCeTypeInfo->mFailed = false; } - if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty())) - hadNewMembers = true; + if (typeInstance->mCeTypeInfo != NULL) + { + if (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()) + hadNewMembers = true; + } if ((typeInstance->mTypeDef->IsEmitted()) && (typeInstance->mCeTypeInfo == NULL)) { @@ -5596,6 +5605,11 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy bool needsExplicitAlignment = true; + if (typeInstance->mCeTypeInfo != NULL) + { + typeInstance->mInstAlign = BF_MAX(typeInstance->mInstAlign, typeInstance->mCeTypeInfo->mAlign); + } + for (int fieldIdx = 0; fieldIdx < (int)dataFieldVec.size(); fieldIdx++) { auto fieldInstance = dataFieldVec[fieldIdx]; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 96e094e3..07599669 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -6086,6 +6086,17 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* else _Fail("Comptime return types can only be set on methods declared with a 'var' return type"); } + else if (checkFunction->mFunctionKind == CeFunctionKind_Align) + { + int32 typeId = *(int32*)((uint8*)stackPtr); + int32 align = *(int32*)((uint8*)stackPtr + sizeof(int32)); + if ((mCurEmitContext == NULL) || (mCurEmitContext->mType == NULL) || (mCurEmitContext->mType->mTypeId != typeId)) + { + _Fail("This type cannot be modified in this context"); + return false; + } + mCurEmitContext->mAlign = BF_MAX(mCurEmitContext->mAlign, align); + } else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody) { int32 typeId = *(int32*)((uint8*)stackPtr); @@ -9297,6 +9308,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_SetReturnType; } + else if (methodDef->mName == "Comptime_Align") + { + ceFunction->mFunctionKind = CeFunctionKind_Align; + } else if (methodDef->mName == "Comptime_EmitTypeBody") { ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody; diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 1277b8ff..dee18e8d 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -449,6 +449,7 @@ enum CeFunctionKind CeFunctionKind_Method_GetGenericArg, CeFunctionKind_SetReturnType, + CeFunctionKind_Align, CeFunctionKind_EmitTypeBody, CeFunctionKind_EmitAddInterface, CeFunctionKind_EmitMethodEntry, @@ -975,6 +976,7 @@ public: Array mInterfaces; String mEmitData; String mExitEmitData; + int32 mAlign; bool mFailed; CeEmitContext() @@ -982,11 +984,12 @@ public: mType = NULL; mMethodInstance = NULL; mFailed = false; + mAlign = -1; } bool HasEmissions() { - return !mEmitData.IsEmpty() || !mInterfaces.IsEmpty(); + return !mEmitData.IsEmpty() || !mInterfaces.IsEmpty() || (mAlign != -1); } }; @@ -1031,6 +1034,7 @@ public: bool mFastFinished; bool mFailed; bool mMayHaveUniqueEmitLocations; + int32 mAlign; BfCeTypeInfo* mNext; public: @@ -1039,6 +1043,7 @@ public: mFastFinished = false; mFailed = false; mMayHaveUniqueEmitLocations = false; + mAlign = -1; mNext = NULL; } };