mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Comptime method reflection, method entry/exit emission
This commit is contained in:
parent
bc8758bbac
commit
8f3060fd3c
18 changed files with 944 additions and 117 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Reflection;
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
public struct Attribute
|
public struct Attribute
|
||||||
|
@ -542,6 +543,6 @@ namespace System
|
||||||
|
|
||||||
interface IComptimeMethodApply
|
interface IComptimeMethodApply
|
||||||
{
|
{
|
||||||
void ApplyToMethod(Type type);
|
void ApplyToMethod(ComptimeMethodInfo methodInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,10 @@ namespace System
|
||||||
|
|
||||||
static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
|
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_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
||||||
static extern void Comptime_EmitDefinition(int32 typeId, StringView text);
|
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
||||||
|
static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text);
|
||||||
|
static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text);
|
||||||
|
static extern void Comptime_EmitMixin(StringView text);
|
||||||
|
|
||||||
[Comptime(OnlyFromComptime=true)]
|
[Comptime(OnlyFromComptime=true)]
|
||||||
public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags)
|
public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags)
|
||||||
|
@ -80,9 +83,28 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
[Comptime(OnlyFromComptime=true)]
|
[Comptime(OnlyFromComptime=true)]
|
||||||
public static void EmitDefinition(Type owner, StringView text)
|
public static void EmitTypeBody(Type owner, StringView text)
|
||||||
{
|
{
|
||||||
Comptime_EmitDefinition((.)owner.TypeId, text);
|
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Comptime(OnlyFromComptime=true)]
|
||||||
|
public static void EmitMethodEntry(ComptimeMethodInfo methodHandle, StringView text)
|
||||||
|
{
|
||||||
|
Comptime_EmitMethodEntry(methodHandle.mNativeMethodInstance, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Comptime(OnlyFromComptime=true)]
|
||||||
|
public static void EmitMethodExit(ComptimeMethodInfo methodHandle, StringView text)
|
||||||
|
{
|
||||||
|
Comptime_EmitMethodExit(methodHandle.mNativeMethodInstance, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public static void Mixin(StringView text)
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
Comptime_EmitMixin(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
153
BeefLibs/corlib/src/Reflection/CEMethodInfo.bf
Normal file
153
BeefLibs/corlib/src/Reflection/CEMethodInfo.bf
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace System.Reflection
|
||||||
|
{
|
||||||
|
struct ComptimeMethodInfo
|
||||||
|
{
|
||||||
|
[CRepr, Packed]
|
||||||
|
public struct Info
|
||||||
|
{
|
||||||
|
public int32 mReturnTypeId;
|
||||||
|
public int32 mParamCount;
|
||||||
|
public MethodFlags mMethodFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CRepr, Packed]
|
||||||
|
public struct ParamInfo
|
||||||
|
{
|
||||||
|
public int32 mParamTypeId;
|
||||||
|
public TypeInstance.ParamFlags mParamFlags;
|
||||||
|
public String mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int64 mNativeMethodInstance;
|
||||||
|
|
||||||
|
public bool IsInitialized => true;
|
||||||
|
public StringView Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int ParamCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
return Type.[Friend]Comptime_Method_GetInfo(mNativeMethodInstance).mParamCount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool IsConstructor => Name == "__BfCtor" || Name == "__BfStaticCtor";
|
||||||
|
public bool IsDestructor => Name == "__BfStaticDtor" || Name == "__BfStaticDtor";
|
||||||
|
public Type ReturnType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
Type.[Friend]GetType((.)Type.[Friend]Comptime_Method_GetInfo(mNativeMethodInstance).mReturnTypeId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(int64 nativeMethodInstance)
|
||||||
|
{
|
||||||
|
mNativeMethodInstance = nativeMethodInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type GetParamType(int paramIdx)
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
return Type.[Friend]GetType((.)Type.[Friend]Comptime_Method_GetParamInfo(mNativeMethodInstance, (.)paramIdx).mParamTypeId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView GetParamName(int paramIdx)
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
return Type.[Friend]Comptime_Method_GetParamInfo(mNativeMethodInstance, (.)paramIdx).mName;
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
if (Compiler.IsComptime)
|
||||||
|
{
|
||||||
|
String str = Type.[Friend]Comptime_Method_ToString(mNativeMethodInstance);
|
||||||
|
strBuffer.Append(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Enumerator : IEnumerator<ComptimeMethodInfo>
|
||||||
|
{
|
||||||
|
BindingFlags mBindingFlags;
|
||||||
|
TypeInstance mTypeInstance;
|
||||||
|
int32 mIdx;
|
||||||
|
int32 mCount;
|
||||||
|
|
||||||
|
public this(TypeInstance typeInst, BindingFlags bindingFlags)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine($"this {typeInst}");
|
||||||
|
|
||||||
|
mTypeInstance = typeInst;
|
||||||
|
mBindingFlags = bindingFlags;
|
||||||
|
mIdx = -1;
|
||||||
|
if ((mTypeInstance == null) || (!Compiler.IsComptime))
|
||||||
|
mCount = 0;
|
||||||
|
else
|
||||||
|
mCount = Type.[Friend]Comptime_GetMethodCount((.)mTypeInstance.TypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset() mut
|
||||||
|
{
|
||||||
|
mIdx = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext() mut
|
||||||
|
{
|
||||||
|
if (mTypeInstance == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
mIdx++;
|
||||||
|
if (mIdx == mCount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int64 nativeMethodHandle = Type.[Friend]Comptime_GetMethod((int32)mTypeInstance.TypeId, mIdx);
|
||||||
|
let info = Type.[Friend]Comptime_Method_GetInfo(nativeMethodHandle);
|
||||||
|
|
||||||
|
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (info.mMethodFlags.HasFlag(.Static)));
|
||||||
|
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!info.mMethodFlags.HasFlag(.Static)));
|
||||||
|
if (matches)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComptimeMethodInfo Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int64 nativeMethodHandle = Type.[Friend]Comptime_GetMethod((int32)mTypeInstance.TypeId, mIdx);
|
||||||
|
return ComptimeMethodInfo(nativeMethodHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<ComptimeMethodInfo> GetNext() mut
|
||||||
|
{
|
||||||
|
if (!MoveNext())
|
||||||
|
return .Err;
|
||||||
|
return Current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,12 @@ namespace System
|
||||||
return MethodInfo.Enumerator(null, bindingFlags);
|
return MethodInfo.Enumerator(null, bindingFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public virtual ComptimeMethodInfo.Enumerator GetMethods(BindingFlags bindingFlags = cDefaultLookup)
|
||||||
|
{
|
||||||
|
return ComptimeMethodInfo.Enumerator(null, bindingFlags);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual Result<MethodInfo, MethodError> GetMethod(StringView methodName, BindingFlags bindingFlags = cDefaultLookup)
|
public virtual Result<MethodInfo, MethodError> GetMethod(StringView methodName, BindingFlags bindingFlags = cDefaultLookup)
|
||||||
{
|
{
|
||||||
MethodInfo matched = default;
|
MethodInfo matched = default;
|
||||||
|
@ -40,6 +46,16 @@ namespace System
|
||||||
return .Err(.NoResults);
|
return .Err(.NoResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public virtual Result<ComptimeMethodInfo, MethodError> GetMethod(int methodIdx)
|
||||||
|
{
|
||||||
|
int64 nativeMethod = Comptime_GetMethod((.)TypeId, (.)methodIdx);
|
||||||
|
if (nativeMethod == 0)
|
||||||
|
return .Err(.NoResults);
|
||||||
|
|
||||||
|
return ComptimeMethodInfo(nativeMethod);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual Result<Object> CreateObject()
|
public virtual Result<Object> CreateObject()
|
||||||
{
|
{
|
||||||
return .Err;
|
return .Err;
|
||||||
|
@ -66,6 +82,12 @@ namespace System.Reflection
|
||||||
return MethodInfo.Enumerator(this, bindingFlags);
|
return MethodInfo.Enumerator(this, bindingFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public override ComptimeMethodInfo.Enumerator GetMethods(BindingFlags bindingFlags = cDefaultLookup)
|
||||||
|
{
|
||||||
|
return ComptimeMethodInfo.Enumerator(this, bindingFlags);
|
||||||
|
}
|
||||||
|
|
||||||
public override Result<MethodInfo, MethodError> GetMethod(int methodIdx)
|
public override Result<MethodInfo, MethodError> GetMethod(int methodIdx)
|
||||||
{
|
{
|
||||||
if ((methodIdx < 0) || (methodIdx >= mMethodDataCount))
|
if ((methodIdx < 0) || (methodIdx >= mMethodDataCount))
|
||||||
|
|
|
@ -475,6 +475,12 @@ namespace System
|
||||||
static extern Type Comptime_GetTypeByName(StringView name);
|
static extern Type Comptime_GetTypeByName(StringView name);
|
||||||
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
|
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
|
||||||
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr);
|
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr);
|
||||||
|
static extern int32 Comptime_GetMethodCount(int32 typeId);
|
||||||
|
static extern int64 Comptime_GetMethod(int32 typeId, int32 methodIdx);
|
||||||
|
static extern String Comptime_Method_ToString(int64 methodHandle);
|
||||||
|
static extern String Comptime_Method_GetName(int64 methodHandle);
|
||||||
|
static extern ComptimeMethodInfo.Info Comptime_Method_GetInfo(int64 methodHandle);
|
||||||
|
static extern ComptimeMethodInfo.ParamInfo Comptime_Method_GetParamInfo(int64 methodHandle, int32 paramIdx);
|
||||||
|
|
||||||
protected static Type GetType(TypeId typeId)
|
protected static Type GetType(TypeId typeId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -777,11 +777,14 @@ namespace IDE.ui
|
||||||
if (itr.GetNext() case .Ok(let fileName))
|
if (itr.GetNext() case .Ok(let fileName))
|
||||||
{
|
{
|
||||||
entry.mFile = new String(fileName);
|
entry.mFile = new String(fileName);
|
||||||
|
if (!entry.mFile.IsEmpty)
|
||||||
|
{
|
||||||
entry.mLine = int.Parse(itr.GetNext()).Get();
|
entry.mLine = int.Parse(itr.GetNext()).Get();
|
||||||
entry.mColumn = int.Parse(itr.GetNext()).Get();
|
entry.mColumn = int.Parse(itr.GetNext()).Get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Debug.Assert(addIdx == -1);
|
Debug.Assert(addIdx == -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1111,6 +1111,11 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
|
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
|
||||||
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
|
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
|
||||||
RETURN_BETTER_OR_WORSE(newMethodDef->mIsMutating, prevMethodDef->mIsMutating);
|
RETURN_BETTER_OR_WORSE(newMethodDef->mIsMutating, prevMethodDef->mIsMutating);
|
||||||
|
if (newMethodDef->mHasComptime != prevMethodDef->mHasComptime)
|
||||||
|
{
|
||||||
|
bool isComptime = (mModule->mIsComptimeModule) || ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0);
|
||||||
|
RETURN_BETTER_OR_WORSE(newMethodDef->mHasComptime == isComptime, prevMethodDef->mHasComptime == isComptime);
|
||||||
|
}
|
||||||
|
|
||||||
RETURN_RESULTS;
|
RETURN_RESULTS;
|
||||||
}
|
}
|
||||||
|
@ -5190,9 +5195,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
// We didn't properly resolve this so queue for a rebuild later
|
// We didn't properly resolve this so queue for a rebuild later
|
||||||
mModule->DeferRebuildType(mModule->mCurTypeInstance);
|
mModule->DeferRebuildType(mModule->mCurTypeInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
doConstReturn = true;
|
|
||||||
}
|
}
|
||||||
|
doConstReturn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mModule->mIsComptimeModule)
|
else if (mModule->mIsComptimeModule)
|
||||||
|
|
|
@ -1989,6 +1989,12 @@ void BfIRBuilder::Write(const BfIRValue& irValue)
|
||||||
Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
|
Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case (int)BfConstType_Undef:
|
||||||
|
{
|
||||||
|
auto undefConst = (BfConstantUndef*)constant;
|
||||||
|
Write(undefConst->mType);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case (int)BfConstType_TypeOf_WithData:
|
case (int)BfConstType_TypeOf_WithData:
|
||||||
{
|
{
|
||||||
auto typeofConst = (BfTypeOf_WithData_Const*)constant;
|
auto typeofConst = (BfTypeOf_WithData_Const*)constant;
|
||||||
|
|
|
@ -2798,6 +2798,14 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
|
|
||||||
if (mIsComptimeModule)
|
if (mIsComptimeModule)
|
||||||
{
|
{
|
||||||
|
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
|
||||||
|
{
|
||||||
|
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
|
||||||
|
if (bfError != NULL)
|
||||||
|
mCompiler->mPassInstance->MoreInfo(error, refNode);
|
||||||
|
return bfError;
|
||||||
|
}
|
||||||
|
|
||||||
mHadBuildError = true;
|
mHadBuildError = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2925,6 +2933,14 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
if (!mHadBuildError)
|
if (!mHadBuildError)
|
||||||
mHadBuildError = true;
|
mHadBuildError = true;
|
||||||
|
|
||||||
|
if ((mCurMethodState != NULL) && (mCurMethodState->mEmitRefNode != NULL))
|
||||||
|
{
|
||||||
|
BfError* bfError = mCompiler->mPassInstance->Fail("Emitted code had errors", mCurMethodState->mEmitRefNode);
|
||||||
|
if (bfError != NULL)
|
||||||
|
mCompiler->mPassInstance->MoreInfo(errorString, refNode);
|
||||||
|
return bfError;
|
||||||
|
}
|
||||||
|
|
||||||
// Check mixins
|
// Check mixins
|
||||||
{
|
{
|
||||||
auto checkMethodInstance = mCurMethodState;
|
auto checkMethodInstance = mCurMethodState;
|
||||||
|
@ -2934,6 +2950,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
if (rootMixinState != NULL)
|
if (rootMixinState != NULL)
|
||||||
{
|
{
|
||||||
BfError* bfError = mCompiler->mPassInstance->Fail(StrFormat("Failed to inject mixin '%s'", MethodToString(rootMixinState->mMixinMethodInstance).c_str()), rootMixinState->mSource);
|
BfError* bfError = mCompiler->mPassInstance->Fail(StrFormat("Failed to inject mixin '%s'", MethodToString(rootMixinState->mMixinMethodInstance).c_str()), rootMixinState->mSource);
|
||||||
|
if (bfError != NULL)
|
||||||
mCompiler->mPassInstance->MoreInfo(errorString, refNode);
|
mCompiler->mPassInstance->MoreInfo(errorString, refNode);
|
||||||
|
|
||||||
auto mixinState = checkMethodInstance->mMixinState;
|
auto mixinState = checkMethodInstance->mMixinState;
|
||||||
|
@ -3043,6 +3060,14 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mCurMethodState != NULL) && (mCurMethodState->mEmitRefNode != NULL))
|
||||||
|
{
|
||||||
|
BfError* bfError = mCompiler->mPassInstance->Warn(warningNum, "Emitted code had errors", mCurMethodState->mEmitRefNode);
|
||||||
|
if (bfError != NULL)
|
||||||
|
mCompiler->mPassInstance->MoreInfo(warning, refNode);
|
||||||
|
return bfError;
|
||||||
|
}
|
||||||
|
|
||||||
BfError* bfError;
|
BfError* bfError;
|
||||||
if (refNode != NULL)
|
if (refNode != NULL)
|
||||||
bfError = mCompiler->mPassInstance->WarnAt(warningNum, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
|
bfError = mCompiler->mPassInstance->WarnAt(warningNum, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
|
||||||
|
@ -4973,6 +4998,8 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type)
|
||||||
return mBfIRBuilder->Comptime_GetReflectType(type->mTypeId, mBfIRBuilder->MapType(typeTypeInst));
|
return mBfIRBuilder->Comptime_GetReflectType(type->mTypeId, mBfIRBuilder->MapType(typeTypeInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PopulateType(type);
|
||||||
|
|
||||||
BfIRValue globalVariable;
|
BfIRValue globalVariable;
|
||||||
|
|
||||||
BfIRValue* globalVariablePtr = NULL;
|
BfIRValue* globalVariablePtr = NULL;
|
||||||
|
@ -4997,6 +5024,11 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type)
|
||||||
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, this);
|
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeDataName == "?sBfTypeData@Zoing@BeefTest@bf@@2HA")
|
||||||
|
{
|
||||||
|
NOP;
|
||||||
|
}
|
||||||
|
|
||||||
BfLogSysM("Creating TypeData %s\n", typeDataName.c_str());
|
BfLogSysM("Creating TypeData %s\n", typeDataName.c_str());
|
||||||
|
|
||||||
globalVariable = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeTypeInst, BfIRPopulateType_Full), true, BfIRLinkageType_External, BfIRValue(), typeDataName);
|
globalVariable = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeTypeInst, BfIRPopulateType_Full), true, BfIRLinkageType_External, BfIRValue(), typeDataName);
|
||||||
|
@ -5110,6 +5142,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
|
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeDataName == "?sBfTypeData@@bf@@2HA")
|
||||||
|
{
|
||||||
|
NOP;
|
||||||
|
}
|
||||||
|
|
||||||
int typeCode = BfTypeCode_None;
|
int typeCode = BfTypeCode_None;
|
||||||
|
|
||||||
if (typeInstance != NULL)
|
if (typeInstance != NULL)
|
||||||
|
@ -6401,6 +6438,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
auto methodDef = typeDef->mMethods[methodIdx];
|
auto methodDef = typeDef->mMethods[methodIdx];
|
||||||
if (methodDef->mIsNoReflect)
|
if (methodDef->mIsNoReflect)
|
||||||
continue;
|
continue;
|
||||||
|
if (methodDef->mHasComptime)
|
||||||
|
continue;
|
||||||
|
|
||||||
auto defaultMethod = methodInstanceGroup->mDefault;
|
auto defaultMethod = methodInstanceGroup->mDefault;
|
||||||
if (defaultMethod == NULL)
|
if (defaultMethod == NULL)
|
||||||
|
@ -6481,43 +6520,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
|
|
||||||
BfIRValue methodNameConst = GetStringObjectValue(methodDef->mName, true);
|
BfIRValue methodNameConst = GetStringObjectValue(methodDef->mName, true);
|
||||||
|
|
||||||
enum MethodFlags
|
BfMethodFlags methodFlags = moduleMethodInstance.mMethodInstance->GetMethodFlags();
|
||||||
{
|
|
||||||
MethodFlags_Protected = 3,
|
|
||||||
MethodFlags_Public = 6,
|
|
||||||
MethodFlags_Static = 0x10,
|
|
||||||
MethodFlags_Virtual = 0x40,
|
|
||||||
MethodFlags_StdCall = 0x1000,
|
|
||||||
MethodFlags_FastCall = 0x2000,
|
|
||||||
MethodFlags_ThisCall = 0x3000,
|
|
||||||
MethodFlags_Mutating = 0x4000,
|
|
||||||
MethodFlags_Constructor = 0x8000,
|
|
||||||
};
|
|
||||||
|
|
||||||
MethodFlags methodFlags = (MethodFlags)0;
|
|
||||||
|
|
||||||
if (methodDef->mProtection == BfProtection_Protected)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Protected);
|
|
||||||
if (methodDef->mProtection == BfProtection_Public)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Public);
|
|
||||||
if (methodDef->mIsStatic)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Static);
|
|
||||||
if ((methodDef->mIsVirtual) || (moduleMethodInstance.mMethodInstance->mVirtualTableIdx != -1))
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Virtual);
|
|
||||||
if (methodDef->mCallingConvention == BfCallingConvention_Fastcall)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_FastCall);
|
|
||||||
if (methodDef->mIsMutating)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Mutating);
|
|
||||||
if (methodDef->mMethodType == BfMethodType_Ctor)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_Constructor);
|
|
||||||
|
|
||||||
auto callingConvention = GetIRCallingConvention(defaultMethod);
|
|
||||||
if (callingConvention == BfIRCallingConv_ThisCall)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_ThisCall);
|
|
||||||
else if (callingConvention == BfIRCallingConv_StdCall)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_StdCall);
|
|
||||||
else if (callingConvention == BfIRCallingConv_FastCall)
|
|
||||||
methodFlags = (MethodFlags)(methodFlags | MethodFlags_FastCall);
|
|
||||||
|
|
||||||
int customAttrIdx = _HandleCustomAttrs(methodCustomAttributes);
|
int customAttrIdx = _HandleCustomAttrs(methodCustomAttributes);
|
||||||
|
|
||||||
|
@ -9830,8 +9833,11 @@ BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* met
|
||||||
return methodInstance;
|
return methodInstance;
|
||||||
|
|
||||||
if ((owner->IsDelegateFromTypeRef()) ||
|
if ((owner->IsDelegateFromTypeRef()) ||
|
||||||
|
(owner->IsFunctionFromTypeRef()) ||
|
||||||
(owner->IsTuple()))
|
(owner->IsTuple()))
|
||||||
|
{
|
||||||
return methodInstance;
|
return methodInstance;
|
||||||
|
}
|
||||||
|
|
||||||
auto genericType = (BfTypeInstance*)owner;
|
auto genericType = (BfTypeInstance*)owner;
|
||||||
if ((genericType->IsUnspecializedType()) && (!genericType->IsUnspecializedTypeVariation()))
|
if ((genericType->IsUnspecializedType()) && (!genericType->IsUnspecializedTypeVariation()))
|
||||||
|
@ -10451,11 +10457,16 @@ StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodName
|
||||||
return methodName;
|
return methodName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::pv(BfType* type)
|
void BfModule::pt(BfType* type)
|
||||||
{
|
{
|
||||||
OutputDebugStrF("%s\n", TypeToString(type).c_str());
|
OutputDebugStrF("%s\n", TypeToString(type).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::pm(BfMethodInstance* type)
|
||||||
|
{
|
||||||
|
OutputDebugStrF("%s\n", MethodToString(type).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
static void AddAttributeTargetName(BfAttributeTargets& flagsLeft, BfAttributeTargets checkFlag, String& str, String addString)
|
static void AddAttributeTargetName(BfAttributeTargets& flagsLeft, BfAttributeTargets checkFlag, String& str, String addString)
|
||||||
{
|
{
|
||||||
if ((flagsLeft & checkFlag) == 0)
|
if ((flagsLeft & checkFlag) == 0)
|
||||||
|
@ -12080,6 +12091,8 @@ bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstan
|
||||||
return false;
|
return false;
|
||||||
if (methodA->mMethodDef->mCheckedKind != methodB->mMethodDef->mCheckedKind)
|
if (methodA->mMethodDef->mCheckedKind != methodB->mMethodDef->mCheckedKind)
|
||||||
return false;
|
return false;
|
||||||
|
if (methodA->mMethodDef->mHasComptime != methodB->mMethodDef->mHasComptime)
|
||||||
|
return false;
|
||||||
if ((methodA->mMethodDef->mMethodType == BfMethodType_Mixin) != (methodB->mMethodDef->mMethodType == BfMethodType_Mixin))
|
if ((methodA->mMethodDef->mMethodType == BfMethodType_Mixin) != (methodB->mMethodDef->mMethodType == BfMethodType_Mixin))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -14271,6 +14284,7 @@ void BfModule::EmitDeferredScopeCalls(bool useSrcPositions, BfScopeData* scopeDa
|
||||||
{
|
{
|
||||||
if (deferredCallEntry->mDeferredBlock != NULL)
|
if (deferredCallEntry->mDeferredBlock != NULL)
|
||||||
{
|
{
|
||||||
|
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, deferredCallEntry->mEmitRefNode);
|
||||||
VisitEmbeddedStatement(deferredCallEntry->mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
VisitEmbeddedStatement(deferredCallEntry->mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
||||||
}
|
}
|
||||||
deferredCallEntry = deferredCallEntry->mNext;
|
deferredCallEntry = deferredCallEntry->mNext;
|
||||||
|
@ -19583,6 +19597,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
isExpressionBody = true;
|
isExpressionBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DoCEEmit(methodInstance);
|
||||||
|
|
||||||
if (auto fieldDtorBody = BfNodeDynCast<BfFieldDtorDeclaration>(methodDef->mBody))
|
if (auto fieldDtorBody = BfNodeDynCast<BfFieldDtorDeclaration>(methodDef->mBody))
|
||||||
{
|
{
|
||||||
while (fieldDtorBody != NULL)
|
while (fieldDtorBody != NULL)
|
||||||
|
@ -19790,7 +19806,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid linking any internal funcs that were just supposed to be comptime-accessible
|
// Avoid linking any internal funcs that were just supposed to be comptime-accessible
|
||||||
if (((methodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) && (!mIsComptimeModule))
|
if ((methodDef->mHasComptime) && (!mIsComptimeModule))
|
||||||
wantsRemoveBody = true;
|
wantsRemoveBody = true;
|
||||||
|
|
||||||
if ((hasExternSpecifier) && (!skipBody))
|
if ((hasExternSpecifier) && (!skipBody))
|
||||||
|
|
|
@ -273,6 +273,7 @@ public:
|
||||||
SizedArray<BfIRValue, 1> mScopeArgs;
|
SizedArray<BfIRValue, 1> mScopeArgs;
|
||||||
Array<BfDeferredCapture> mCaptures;
|
Array<BfDeferredCapture> mCaptures;
|
||||||
BfBlock* mDeferredBlock;
|
BfBlock* mDeferredBlock;
|
||||||
|
BfAstNode* mEmitRefNode;
|
||||||
int64 mBlockId;
|
int64 mBlockId;
|
||||||
int mHandlerCount;
|
int mHandlerCount;
|
||||||
bool mBypassVirtual;
|
bool mBypassVirtual;
|
||||||
|
@ -292,6 +293,7 @@ public:
|
||||||
mNext = NULL;
|
mNext = NULL;
|
||||||
mSrcNode = NULL;
|
mSrcNode = NULL;
|
||||||
mDeferredBlock = NULL;
|
mDeferredBlock = NULL;
|
||||||
|
mEmitRefNode = NULL;
|
||||||
mBlockId = -1;
|
mBlockId = -1;
|
||||||
mHandlerCount = 0;
|
mHandlerCount = 0;
|
||||||
mArgsNeedLoad = false;
|
mArgsNeedLoad = false;
|
||||||
|
@ -991,6 +993,7 @@ public:
|
||||||
BfScopeData* mCurScope;
|
BfScopeData* mCurScope;
|
||||||
BfScopeData* mTailScope; // Usually equals mCurScope
|
BfScopeData* mTailScope; // Usually equals mCurScope
|
||||||
BfScopeData* mOverrideScope;
|
BfScopeData* mOverrideScope;
|
||||||
|
BfAstNode* mEmitRefNode;
|
||||||
TempKind mTempKind; // Used for var inference, etc
|
TempKind mTempKind; // Used for var inference, etc
|
||||||
bool mInDeferredBlock;
|
bool mInDeferredBlock;
|
||||||
bool mHadReturn;
|
bool mHadReturn;
|
||||||
|
@ -1024,6 +1027,7 @@ public:
|
||||||
mHeadScope.mIsScopeHead = true;
|
mHeadScope.mIsScopeHead = true;
|
||||||
mCurScope = &mHeadScope;
|
mCurScope = &mHeadScope;
|
||||||
mTailScope = &mHeadScope;
|
mTailScope = &mHeadScope;
|
||||||
|
mEmitRefNode = NULL;
|
||||||
mOverrideScope = NULL;
|
mOverrideScope = NULL;
|
||||||
mHadReturn = false;
|
mHadReturn = false;
|
||||||
mLeftBlockUncond = false;
|
mLeftBlockUncond = false;
|
||||||
|
@ -1370,6 +1374,12 @@ public:
|
||||||
|
|
||||||
#define BFMODULE_FATAL(module, msg) (module)->FatalError((msg), __FILE__, __LINE__)
|
#define BFMODULE_FATAL(module, msg) (module)->FatalError((msg), __FILE__, __LINE__)
|
||||||
|
|
||||||
|
struct BfCEParseContext
|
||||||
|
{
|
||||||
|
int mFailIdx;
|
||||||
|
int mWarnIdx;
|
||||||
|
};
|
||||||
|
|
||||||
class BfModule : public BfStructuralVisitor
|
class BfModule : public BfStructuralVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1523,7 +1533,8 @@ public:
|
||||||
StringT<128> TypeToString(BfType* resolvedType, BfTypeNameFlags typeNameFlags, Array<String>* genericMethodParamNameOverrides = NULL);
|
StringT<128> TypeToString(BfType* resolvedType, BfTypeNameFlags typeNameFlags, Array<String>* genericMethodParamNameOverrides = NULL);
|
||||||
void DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None, Array<String>* genericMethodParamNameOverrides = NULL);
|
void DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None, Array<String>* genericMethodParamNameOverrides = NULL);
|
||||||
StringT<128> MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags methodNameFlags = BfMethodNameFlag_ResolveGenericParamNames, BfTypeVector* typeGenericArgs = NULL, BfTypeVector* methodGenericArgs = NULL);
|
StringT<128> MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags methodNameFlags = BfMethodNameFlag_ResolveGenericParamNames, BfTypeVector* typeGenericArgs = NULL, BfTypeVector* methodGenericArgs = NULL);
|
||||||
void pv(BfType* type);
|
void pt(BfType* type);
|
||||||
|
void pm(BfMethodInstance* type);
|
||||||
void CurrentAddToConstHolder(BfIRValue& irVal);
|
void CurrentAddToConstHolder(BfIRValue& irVal);
|
||||||
void ClearConstData();
|
void ClearConstData();
|
||||||
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
|
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
|
||||||
|
@ -1562,7 +1573,7 @@ public:
|
||||||
void EmitDefaultReturn();
|
void EmitDefaultReturn();
|
||||||
void EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags = BfDeferredBlockFlag_None);
|
void EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags = BfDeferredBlockFlag_None);
|
||||||
bool AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scope);
|
bool AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scope);
|
||||||
void AddDeferredBlock(BfBlock* block, BfScopeData* scope, Array<BfDeferredCapture>* captures = NULL);
|
BfDeferredCallEntry* AddDeferredBlock(BfBlock* block, BfScopeData* scope, Array<BfDeferredCapture>* captures = NULL);
|
||||||
BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);
|
BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);
|
||||||
void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks);
|
void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks);
|
||||||
void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
|
void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
|
||||||
|
@ -1698,10 +1709,14 @@ public:
|
||||||
void SetTypeOptions(BfTypeInstance* typeInstance);
|
void SetTypeOptions(BfTypeInstance* typeInstance);
|
||||||
BfModuleOptions GetModuleOptions();
|
BfModuleOptions GetModuleOptions();
|
||||||
BfCheckedKind GetDefaultCheckedKind();
|
BfCheckedKind GetDefaultCheckedKind();
|
||||||
|
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
|
||||||
|
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& src);
|
||||||
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode);
|
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode);
|
||||||
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes);
|
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes);
|
||||||
|
void CEMixin(BfAstNode* refNode, const StringImpl& src);
|
||||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind);
|
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind);
|
||||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
|
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
|
||||||
|
void DoCEEmit(BfMethodInstance* methodInstance);
|
||||||
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
||||||
static BfModule* GetModuleFor(BfType* type);
|
static BfModule* GetModuleFor(BfType* type);
|
||||||
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);
|
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);
|
||||||
|
|
|
@ -1933,24 +1933,11 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance)
|
||||||
typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
|
typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode)
|
BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& src)
|
||||||
{
|
{
|
||||||
if (ceEmitContext->mEmitData.IsEmpty())
|
BfCEParseContext ceParseContext;
|
||||||
return;
|
ceParseContext.mFailIdx = mCompiler->mPassInstance->mFailedIdx;
|
||||||
|
ceParseContext.mWarnIdx = mCompiler->mPassInstance->mWarnIdx;
|
||||||
int prevFailIdx = mCompiler->mPassInstance->mFailedIdx;
|
|
||||||
int prevWarnIdx = mCompiler->mPassInstance->mWarnIdx;
|
|
||||||
|
|
||||||
String src;
|
|
||||||
|
|
||||||
if (activeTypeDef->mEmitParser != NULL)
|
|
||||||
src += "\n\n";
|
|
||||||
|
|
||||||
src += "// Code emission in ";
|
|
||||||
src += ctxString;
|
|
||||||
src += "\n\n";
|
|
||||||
src += ceEmitContext->mEmitData;
|
|
||||||
ceEmitContext->mEmitData.Clear();
|
|
||||||
|
|
||||||
bool createdParser = false;
|
bool createdParser = false;
|
||||||
int startSrcIdx = 0;
|
int startSrcIdx = 0;
|
||||||
|
@ -1989,6 +1976,46 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
||||||
activeTypeDef->mEmitParser->Parse(mCompiler->mPassInstance);
|
activeTypeDef->mEmitParser->Parse(mCompiler->mPassInstance);
|
||||||
activeTypeDef->mEmitParser->FinishSideNodes();
|
activeTypeDef->mEmitParser->FinishSideNodes();
|
||||||
|
|
||||||
|
if (createdParser)
|
||||||
|
{
|
||||||
|
AutoCrit crit(mSystem->mDataLock);
|
||||||
|
mSystem->mParsers.Add(activeTypeDef->mEmitParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ceParseContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfModule::FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext)
|
||||||
|
{
|
||||||
|
if ((ceParseContext->mFailIdx != mCompiler->mPassInstance->mFailedIdx) && (refNode != NULL))
|
||||||
|
Fail("Emitted code had errors", refNode);
|
||||||
|
else if ((ceParseContext->mWarnIdx != mCompiler->mPassInstance->mWarnIdx) && (refNode != NULL))
|
||||||
|
Warn(0, "Emitted code had warnings", refNode);
|
||||||
|
else if ((ceParseContext->mFailIdx != mCompiler->mPassInstance->mFailedIdx) ||
|
||||||
|
(ceParseContext->mWarnIdx != mCompiler->mPassInstance->mWarnIdx))
|
||||||
|
{
|
||||||
|
AddFailType(typeInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode)
|
||||||
|
{
|
||||||
|
if (ceEmitContext->mEmitData.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String src;
|
||||||
|
|
||||||
|
if (activeTypeDef->mEmitParser != NULL)
|
||||||
|
src += "\n\n";
|
||||||
|
|
||||||
|
src += "// Code emission in ";
|
||||||
|
src += ctxString;
|
||||||
|
src += "\n\n";
|
||||||
|
src += ceEmitContext->mEmitData;
|
||||||
|
ceEmitContext->mEmitData.Clear();
|
||||||
|
|
||||||
|
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, activeTypeDef, src);
|
||||||
|
|
||||||
auto typeDeclaration = activeTypeDef->mEmitParser->mAlloc->Alloc<BfTypeDeclaration>();
|
auto typeDeclaration = activeTypeDef->mEmitParser->mAlloc->Alloc<BfTypeDeclaration>();
|
||||||
|
|
||||||
BfReducer bfReducer;
|
BfReducer bfReducer;
|
||||||
|
@ -2008,21 +2035,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
||||||
defBuilder.DoVisitChild(typeDeclaration->mDefineNode);
|
defBuilder.DoVisitChild(typeDeclaration->mDefineNode);
|
||||||
defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum);
|
defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum);
|
||||||
|
|
||||||
if (createdParser)
|
FinishCEParseContext(refNode, typeInstance, &ceParseContext);
|
||||||
{
|
|
||||||
AutoCrit crit(mSystem->mDataLock);
|
|
||||||
mSystem->mParsers.Add(activeTypeDef->mEmitParser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) && (refNode != NULL))
|
|
||||||
Fail("Emitted code had errors", refNode);
|
|
||||||
else if ((prevWarnIdx != mCompiler->mPassInstance->mWarnIdx) && (refNode != NULL))
|
|
||||||
Warn(0, "Emitted code had warnings", refNode);
|
|
||||||
else if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) ||
|
|
||||||
(prevWarnIdx != mCompiler->mPassInstance->mWarnIdx))
|
|
||||||
{
|
|
||||||
AddFailType(typeInstance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
|
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
|
||||||
|
@ -2066,7 +2079,12 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
|
|
||||||
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
||||||
|
|
||||||
if (!ceEmitContext->mEmitData.IsEmpty())
|
if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit)
|
||||||
|
{
|
||||||
|
// We populated before we could finish
|
||||||
|
AssertErrorState();
|
||||||
|
}
|
||||||
|
else if (!ceEmitContext->mEmitData.IsEmpty())
|
||||||
{
|
{
|
||||||
String ctxStr = "comptime ApplyToType of ";
|
String ctxStr = "comptime ApplyToType of ";
|
||||||
ctxStr += TypeToString(attrType);
|
ctxStr += TypeToString(attrType);
|
||||||
|
@ -2082,6 +2100,76 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
|
||||||
|
{
|
||||||
|
auto activeTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;
|
||||||
|
|
||||||
|
String src;
|
||||||
|
if (activeTypeDef->mEmitParser != NULL)
|
||||||
|
src += "\n\n";
|
||||||
|
src += "// Code emission in ";
|
||||||
|
src += MethodToString(mCurMethodInstance);
|
||||||
|
src += "\n";
|
||||||
|
src += code;
|
||||||
|
|
||||||
|
BfReducer bfReducer;
|
||||||
|
bfReducer.mSource = activeTypeDef->mEmitParser;
|
||||||
|
bfReducer.mPassInstance = mCompiler->mPassInstance;
|
||||||
|
bfReducer.mSystem = mSystem;
|
||||||
|
bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration;
|
||||||
|
bfReducer.mCurMethodDecl = BfNodeDynCast<BfMethodDeclaration>(mCurMethodInstance->mMethodDef->mMethodDeclaration);
|
||||||
|
|
||||||
|
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, refNode);
|
||||||
|
|
||||||
|
EmitEnsureInstructionAt();
|
||||||
|
bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo);
|
||||||
|
mBfIRBuilder->SaveDebugLocation();
|
||||||
|
|
||||||
|
BfCEParseContext ceParseContext = CEEmitParse(mCurTypeInstance, activeTypeDef, src);
|
||||||
|
bfReducer.mAlloc = activeTypeDef->mEmitParser->mAlloc;
|
||||||
|
bfReducer.HandleBlock(activeTypeDef->mEmitParser->mRootNode, false);
|
||||||
|
|
||||||
|
SetAndRestoreValue<BfIRMDNode> prevInlinedAt(mCurMethodState->mCurScope->mDIInlinedAt);
|
||||||
|
SetAndRestoreValue<BfIRMDNode> prevDIScope(mCurMethodState->mCurScope->mDIScope);
|
||||||
|
SetAndRestoreValue<BfIRMDNode> prevAltDIFile(mCurMethodState->mCurScope->mAltDIFile);
|
||||||
|
|
||||||
|
if (wantsDIData)
|
||||||
|
{
|
||||||
|
llvm::SmallVector<BfIRMDNode, 8> diParams;
|
||||||
|
diParams.push_back(mBfIRBuilder->DbgGetType(GetPrimitiveType(BfTypeCode_None)));
|
||||||
|
BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParams);
|
||||||
|
|
||||||
|
//int defLine = mModule->mCurFilePosition.mCurLine;
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation();
|
||||||
|
|
||||||
|
// We used to have the "def" line be the inlining position, but the linker we de-duplicate instances of these functions without regard to their unique line
|
||||||
|
// definitions, so we need to be consistent and use the actual line
|
||||||
|
UpdateSrcPos(activeTypeDef->mEmitParser->mRootNode, BfSrcPosFlag_NoSetDebugLoc);
|
||||||
|
int defLine = mCurFilePosition.mCurLine;
|
||||||
|
auto diParentType = mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance);
|
||||||
|
if (!mBfIRBuilder->mIgnoreWrites)
|
||||||
|
{
|
||||||
|
String methodName = "Comptime_Mixin";
|
||||||
|
mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(diParentType, methodName, "", mCurFilePosition.mFileInstance->mDIFile,
|
||||||
|
defLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
|
||||||
|
mCurMethodState->mCurScope->mAltDIFile = mCurFilePosition.mFileInstance->mDIFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSrcPos(activeTypeDef->mEmitParser->mRootNode);
|
||||||
|
|
||||||
|
SetIllegalSrcPos();
|
||||||
|
|
||||||
|
Visit(activeTypeDef->mEmitParser->mRootNode);
|
||||||
|
|
||||||
|
mBfIRBuilder->RestoreDebugLocation();
|
||||||
|
mBfIRBuilder->DupDebugLocation();
|
||||||
|
|
||||||
|
FinishCEParseContext(refNode, mCurTypeInstance, &ceParseContext);
|
||||||
|
}
|
||||||
|
|
||||||
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind)
|
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind)
|
||||||
{
|
{
|
||||||
HashSet<BfTypeInstance*> foundAttributes;
|
HashSet<BfTypeInstance*> foundAttributes;
|
||||||
|
@ -2166,7 +2254,12 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
|
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
|
||||||
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
|
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
|
||||||
|
|
||||||
if (!ceEmitContext->mEmitData.IsEmpty())
|
if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit)
|
||||||
|
{
|
||||||
|
// We populated before we could finish
|
||||||
|
AssertErrorState();
|
||||||
|
}
|
||||||
|
else if (!ceEmitContext->mEmitData.IsEmpty())
|
||||||
{
|
{
|
||||||
String ctxStr = "OnCompile execution of ";
|
String ctxStr = "OnCompile execution of ";
|
||||||
ctxStr += MethodToString(methodInstance);
|
ctxStr += MethodToString(methodInstance);
|
||||||
|
@ -2203,6 +2296,113 @@ void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
|
||||||
|
{
|
||||||
|
auto customAttributes = methodInstance->GetCustomAttributes();
|
||||||
|
if (customAttributes == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto typeInstance = methodInstance->GetOwner();
|
||||||
|
|
||||||
|
CeEmitContext ceEmitContext;
|
||||||
|
ceEmitContext.mMethodInstance = methodInstance;
|
||||||
|
|
||||||
|
BfTypeInstance* iComptimeMethodApply = NULL;
|
||||||
|
for (auto& customAttribute : customAttributes->mAttributes)
|
||||||
|
{
|
||||||
|
auto attrType = customAttribute.mType;
|
||||||
|
PopulateType(attrType, BfPopulateType_DataAndMethods);
|
||||||
|
if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto& ifaceEntry : attrType->mInterfaces)
|
||||||
|
{
|
||||||
|
if (iComptimeMethodApply == NULL)
|
||||||
|
iComptimeMethodApply = ResolveTypeDef(mCompiler->mIComptimeMethodApply)->ToTypeInstance();
|
||||||
|
if (ifaceEntry.mInterfaceType != iComptimeMethodApply)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if (!foundAttributes.Add(attrType))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
BfMethodInstance* applyMethodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
|
||||||
|
if (applyMethodInstance == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, &ceEmitContext);
|
||||||
|
auto ceContext = mCompiler->mCEMachine->AllocContext();
|
||||||
|
|
||||||
|
BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
|
||||||
|
|
||||||
|
SizedArray<BfIRValue, 1> args;
|
||||||
|
if (!attrType->IsValuelessType())
|
||||||
|
args.Add(attrVal);
|
||||||
|
args.Add(mBfIRBuilder->CreateConst(BfTypeCode_UInt64, (uint64)(intptr)methodInstance));
|
||||||
|
mCompiler->mCEMachine->mMethodInstanceSet.Add(methodInstance);
|
||||||
|
|
||||||
|
//TESTING
|
||||||
|
// mCompiler->mCEMachine->ReleaseContext(ceContext);
|
||||||
|
// ceContext = mCompiler->mCEMachine->AllocContext();
|
||||||
|
// ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize;
|
||||||
|
|
||||||
|
auto activeTypeDef = typeInstance->mTypeDef;
|
||||||
|
auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL);
|
||||||
|
|
||||||
|
if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty()))
|
||||||
|
{
|
||||||
|
String src;
|
||||||
|
src += "// Code emission in comptime ApplyToMethod of ";
|
||||||
|
src += TypeToString(attrType);
|
||||||
|
src += " to ";
|
||||||
|
src += MethodToString(methodInstance);
|
||||||
|
src += " ";
|
||||||
|
src += customAttribute.mRef->LocationToString();
|
||||||
|
src += "\n";
|
||||||
|
|
||||||
|
BfReducer bfReducer;
|
||||||
|
bfReducer.mSource = activeTypeDef->mEmitParser;
|
||||||
|
bfReducer.mPassInstance = mCompiler->mPassInstance;
|
||||||
|
bfReducer.mSystem = mSystem;
|
||||||
|
bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration;
|
||||||
|
bfReducer.mCurMethodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration);
|
||||||
|
|
||||||
|
if (!ceEmitContext.mEmitData.IsEmpty())
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef);
|
||||||
|
|
||||||
|
String entrySrc = src;
|
||||||
|
if (activeTypeDef->mEmitParser != NULL)
|
||||||
|
entrySrc += "\n\n";
|
||||||
|
entrySrc += src;
|
||||||
|
entrySrc += ceEmitContext.mEmitData;
|
||||||
|
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, activeTypeDef, entrySrc);
|
||||||
|
bfReducer.mAlloc = activeTypeDef->mEmitParser->mAlloc;
|
||||||
|
bfReducer.HandleBlock(activeTypeDef->mEmitParser->mRootNode, false);
|
||||||
|
Visit(activeTypeDef->mEmitParser->mRootNode);
|
||||||
|
FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ceEmitContext.mExitEmitData.IsEmpty())
|
||||||
|
{
|
||||||
|
String exitSrc;
|
||||||
|
if (activeTypeDef->mEmitParser != NULL)
|
||||||
|
exitSrc += "\n\n";
|
||||||
|
exitSrc += src;
|
||||||
|
exitSrc += ceEmitContext.mExitEmitData;
|
||||||
|
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, activeTypeDef, exitSrc);
|
||||||
|
bfReducer.mAlloc = activeTypeDef->mEmitParser->mAlloc;
|
||||||
|
bfReducer.HandleBlock(activeTypeDef->mEmitParser->mRootNode, false);
|
||||||
|
auto deferredBlock = AddDeferredBlock(activeTypeDef->mEmitParser->mRootNode, &mCurMethodState->mHeadScope);
|
||||||
|
deferredBlock->mEmitRefNode = customAttribute.mRef;
|
||||||
|
FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mCompiler->mCEMachine->ReleaseContext(ceContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
||||||
{
|
{
|
||||||
auto typeInstance = resolvedTypeRef->ToTypeInstance();
|
auto typeInstance = resolvedTypeRef->ToTypeInstance();
|
||||||
|
@ -6316,6 +6516,11 @@ BfPointerType* BfModule::CreatePointerType(BfTypeReference* typeRef)
|
||||||
|
|
||||||
BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
||||||
{
|
{
|
||||||
|
if (typeDef->mTypeDeclaration == NULL)
|
||||||
|
{
|
||||||
|
BF_ASSERT(!typeDef->mIsDelegate && !typeDef->mIsFunction);
|
||||||
|
}
|
||||||
|
|
||||||
//BF_ASSERT(typeDef->mTypeCode != BfTypeCode_Extension);
|
//BF_ASSERT(typeDef->mTypeCode != BfTypeCode_Extension);
|
||||||
BF_ASSERT(!typeDef->mIsPartial || typeDef->mIsCombinedPartial);
|
BF_ASSERT(!typeDef->mIsPartial || typeDef->mIsCombinedPartial);
|
||||||
|
|
||||||
|
|
|
@ -630,6 +630,35 @@ BfImportKind BfMethodInstance::GetImportKind()
|
||||||
return BfMethodDef::GetImportKindFromPath(*filePath);
|
return BfMethodDef::GetImportKindFromPath(*filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfMethodFlags BfMethodInstance::GetMethodFlags()
|
||||||
|
{
|
||||||
|
BfMethodFlags methodFlags = (BfMethodFlags)0;
|
||||||
|
|
||||||
|
if (mMethodDef->mProtection == BfProtection_Protected)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Protected);
|
||||||
|
if (mMethodDef->mProtection == BfProtection_Public)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Public);
|
||||||
|
if (mMethodDef->mIsStatic)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Static);
|
||||||
|
if ((mMethodDef->mIsVirtual) || (mVirtualTableIdx != -1))
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Virtual);
|
||||||
|
if (mMethodDef->mCallingConvention == BfCallingConvention_Fastcall)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_FastCall);
|
||||||
|
if (mMethodDef->mIsMutating)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Mutating);
|
||||||
|
if (mMethodDef->mMethodType == BfMethodType_Ctor)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_Constructor);
|
||||||
|
|
||||||
|
auto callingConvention = GetOwner()->mModule->GetIRCallingConvention(this);
|
||||||
|
if (callingConvention == BfIRCallingConv_ThisCall)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_ThisCall);
|
||||||
|
else if (callingConvention == BfIRCallingConv_StdCall)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_StdCall);
|
||||||
|
else if (callingConvention == BfIRCallingConv_FastCall)
|
||||||
|
methodFlags = (BfMethodFlags)(methodFlags | BfMethodFlags_FastCall);
|
||||||
|
return methodFlags;
|
||||||
|
}
|
||||||
|
|
||||||
void BfMethodInstance::UndoDeclaration(bool keepIRFunction)
|
void BfMethodInstance::UndoDeclaration(bool keepIRFunction)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -899,6 +899,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
BfImportKind GetImportKind();
|
BfImportKind GetImportKind();
|
||||||
|
BfMethodFlags GetMethodFlags();
|
||||||
void UndoDeclaration(bool keepIRFunction = false);
|
void UndoDeclaration(bool keepIRFunction = false);
|
||||||
BfTypeInstance* GetOwner();
|
BfTypeInstance* GetOwner();
|
||||||
BfModule* GetModule();
|
BfModule* GetModule();
|
||||||
|
|
|
@ -512,13 +512,14 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::AddDeferredBlock(BfBlock* block, BfScopeData* scopeData, Array<BfDeferredCapture>* captures)
|
BfDeferredCallEntry* BfModule::AddDeferredBlock(BfBlock* block, BfScopeData* scopeData, Array<BfDeferredCapture>* captures)
|
||||||
{
|
{
|
||||||
BfDeferredCallEntry* deferredCallEntry = new BfDeferredCallEntry();
|
BfDeferredCallEntry* deferredCallEntry = new BfDeferredCallEntry();
|
||||||
deferredCallEntry->mDeferredBlock = block;
|
deferredCallEntry->mDeferredBlock = block;
|
||||||
if (captures != NULL)
|
if (captures != NULL)
|
||||||
deferredCallEntry->mCaptures = *captures;
|
deferredCallEntry->mCaptures = *captures;
|
||||||
AddDeferredCallEntry(deferredCallEntry, scopeData);
|
AddDeferredCallEntry(deferredCallEntry, scopeData);
|
||||||
|
return deferredCallEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfDeferredCallEntry* BfModule::AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scopeData, BfAstNode* srcNode, bool bypassVirtual, bool doNullCheck)
|
BfDeferredCallEntry* BfModule::AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scopeData, BfAstNode* srcNode, bool bypassVirtual, bool doNullCheck)
|
||||||
|
@ -826,6 +827,7 @@ void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool mov
|
||||||
AddLocalVariableDef(localVar, true);
|
AddLocalVariableDef(localVar, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, deferredCallEntry.mEmitRefNode);
|
||||||
VisitEmbeddedStatement(deferredCallEntry.mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
VisitEmbeddedStatement(deferredCallEntry.mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
||||||
RestoreScopeState();
|
RestoreScopeState();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -187,6 +187,19 @@ enum BfTypeFlags
|
||||||
BfTypeFlags_HasDestructor = 0x40000,
|
BfTypeFlags_HasDestructor = 0x40000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BfMethodFlags
|
||||||
|
{
|
||||||
|
BfMethodFlags_Protected = 3,
|
||||||
|
BfMethodFlags_Public = 6,
|
||||||
|
BfMethodFlags_Static = 0x10,
|
||||||
|
BfMethodFlags_Virtual = 0x40,
|
||||||
|
BfMethodFlags_StdCall = 0x1000,
|
||||||
|
BfMethodFlags_FastCall = 0x2000,
|
||||||
|
BfMethodFlags_ThisCall = 0x3000,
|
||||||
|
BfMethodFlags_Mutating = 0x4000,
|
||||||
|
BfMethodFlags_Constructor = 0x8000,
|
||||||
|
};
|
||||||
|
|
||||||
enum BfObjectFlags : uint8
|
enum BfObjectFlags : uint8
|
||||||
{
|
{
|
||||||
BfObjectFlag_None = 0,
|
BfObjectFlag_None = 0,
|
||||||
|
|
|
@ -1172,6 +1172,8 @@ void CeBuilder::HandleParams()
|
||||||
|
|
||||||
void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance)
|
void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance)
|
||||||
{
|
{
|
||||||
|
SetAndRestoreValue<BfMethodState*> prevMethodStateInConstEval(mCeMachine->mCeModule->mCurMethodState, NULL);
|
||||||
|
|
||||||
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
|
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
|
||||||
auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
|
auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
|
||||||
auto beModule = irCodeGen->mBeModule;
|
auto beModule = irCodeGen->mBeModule;
|
||||||
|
@ -2680,7 +2682,7 @@ BfError* CeContext::Fail(const StringImpl& error)
|
||||||
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
|
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
|
||||||
if (bfError == NULL)
|
if (bfError == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
mCeMachine->mCompiler->mPassInstance->MoreInfo(error, mCeMachine->mCeModule->mCompiler->GetAutoComplete() != NULL);
|
mCeMachine->mCompiler->mPassInstance->MoreInfo(error, mCeMachine->mCompiler->GetAutoComplete() != NULL);
|
||||||
return bfError;
|
return bfError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3020,6 +3022,12 @@ addr_ce CeContext::GetString(int stringId)
|
||||||
return *ceAddrPtr;
|
return *ceAddrPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr_ce CeContext::GetString(const StringImpl& str)
|
||||||
|
{
|
||||||
|
int stringId = mCeMachine->mCeModule->mContext->GetStringLiteralId(str);
|
||||||
|
return GetString(stringId);
|
||||||
|
}
|
||||||
|
|
||||||
BfType* CeContext::GetBfType(int typeId)
|
BfType* CeContext::GetBfType(int typeId)
|
||||||
{
|
{
|
||||||
if ((uintptr)typeId < (uintptr)mCeMachine->mCeModule->mContext->mTypes.size())
|
if ((uintptr)typeId < (uintptr)mCeMachine->mCeModule->mContext->mTypes.size())
|
||||||
|
@ -3616,6 +3624,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
||||||
|
|
||||||
AutoTimer autoTimer(mCeMachine->mRevisionExecuteTime);
|
AutoTimer autoTimer(mCeMachine->mRevisionExecuteTime);
|
||||||
|
|
||||||
|
SetAndRestoreValue<CeContext*> prevContext(mCeMachine->mCurContext, this);
|
||||||
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
|
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
|
||||||
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
|
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
|
||||||
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
|
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
|
||||||
|
@ -3623,7 +3632,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
||||||
SetAndRestoreValue<BfType*> prevExpectingType(mCurExpectingType, expectingType);
|
SetAndRestoreValue<BfType*> prevExpectingType(mCurExpectingType, expectingType);
|
||||||
|
|
||||||
// Reentrancy may occur as methods need defining
|
// Reentrancy may occur as methods need defining
|
||||||
SetAndRestoreValue<BfMethodState*> prevMethodStateInConstEval(module->mCurMethodState, NULL);
|
//SetAndRestoreValue<BfMethodState*> prevMethodStateInConstEval(module->mCurMethodState, NULL);
|
||||||
|
|
||||||
if (mCeMachine->mAppendAllocInfo != NULL)
|
if (mCeMachine->mAppendAllocInfo != NULL)
|
||||||
{
|
{
|
||||||
|
@ -3887,7 +3896,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CE_CHECKALLOC(SIZE) \
|
#define CE_CHECKALLOC(SIZE) \
|
||||||
if ((uintptr)memSize + (uintptr)SIZE > BF_CE_MAX_MEMORY) \
|
if ((SIZE < 0) || (uintptr)memSize + (uintptr)SIZE > BF_CE_MAX_MEMORY) \
|
||||||
{ \
|
{ \
|
||||||
_Fail("Maximum memory size exceeded"); \
|
_Fail("Maximum memory size exceeded"); \
|
||||||
}
|
}
|
||||||
|
@ -4006,6 +4015,14 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
||||||
instPtr = &ceFunction->mCode[0]; \
|
instPtr = &ceFunction->mCode[0]; \
|
||||||
CE_CHECKSTACK();
|
CE_CHECKSTACK();
|
||||||
|
|
||||||
|
static void CeSetAddrVal(void* ptr, addr_ce val, int32 ptrSize)
|
||||||
|
{
|
||||||
|
if (ptrSize == 4)
|
||||||
|
*(int32*)(ptr) = (int32)val;
|
||||||
|
else
|
||||||
|
*(int64*)(ptr) = (int64)val;
|
||||||
|
}
|
||||||
|
|
||||||
bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType)
|
bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType)
|
||||||
{
|
{
|
||||||
auto ceModule = mCeMachine->mCeModule;
|
auto ceModule = mCeMachine->mCeModule;
|
||||||
|
@ -4208,7 +4225,119 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
handled = true;
|
handled = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitDefinition)
|
else if (checkFunction->mFunctionKind == CeFunctionKind_GetMethodCount)
|
||||||
|
{
|
||||||
|
int32 typeId = *(int32*)((uint8*)stackPtr + 4);
|
||||||
|
|
||||||
|
CeTypeInfo* typeInfo = mCeMachine->GetTypeInfo(GetBfType(typeId));
|
||||||
|
if (typeInfo == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int32*)(stackPtr + 0) = (int)typeInfo->mMethodInstances.size();
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_GetMethod)
|
||||||
|
{
|
||||||
|
int32 typeId = *(int32*)((uint8*)stackPtr + 8);
|
||||||
|
int32 methodIdx = *(int32*)((uint8*)stackPtr + 8+4);
|
||||||
|
|
||||||
|
CeTypeInfo* typeInfo = mCeMachine->GetTypeInfo(GetBfType(typeId));
|
||||||
|
if (typeInfo == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((methodIdx < 0) || (methodIdx >= typeInfo->mMethodInstances.mSize))
|
||||||
|
{
|
||||||
|
_Fail("Method out of bounds");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int64*)(stackPtr + 0) = (int64)(intptr)typeInfo->mMethodInstances[methodIdx];
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_Method_ToString)
|
||||||
|
{
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr + ptrSize);
|
||||||
|
|
||||||
|
auto methodInstance = mCeMachine->GetMethodInstance(methodHandle);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid method instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CeSetAddrVal(stackPtr + 0, GetString(mCeMachine->mCeModule->MethodToString(methodInstance)), ptrSize);
|
||||||
|
_FixVariables();
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_Method_GetName)
|
||||||
|
{
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr + ptrSize);
|
||||||
|
|
||||||
|
auto methodInstance = mCeMachine->GetMethodInstance(methodHandle);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid method instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CeSetAddrVal(stackPtr + 0, GetString(methodInstance->mMethodDef->mName), ptrSize);
|
||||||
|
_FixVariables();
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_Method_GetInfo)
|
||||||
|
{
|
||||||
|
// int32 mReturnType
|
||||||
|
// int32 mParamCount
|
||||||
|
// int16 mFlags
|
||||||
|
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr + 4+4+2);
|
||||||
|
|
||||||
|
auto methodInstance = mCeMachine->GetMethodInstance(methodHandle);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid method instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int32*)(stackPtr + 0) = methodInstance->mReturnType->mTypeId;
|
||||||
|
*(int32*)(stackPtr + 4) = methodInstance->GetParamCount();
|
||||||
|
*(int16*)(stackPtr + 4+4) = methodInstance->GetMethodFlags();
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_Method_GetParamInfo)
|
||||||
|
{
|
||||||
|
// int32 mParamType
|
||||||
|
// int16 mFlags
|
||||||
|
// str mName
|
||||||
|
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr + 4+2+ptrSize);
|
||||||
|
int32 paramIdx = *(int32*)((uint8*)stackPtr + 4+2+ptrSize+8);
|
||||||
|
|
||||||
|
auto methodInstance = mCeMachine->GetMethodInstance(methodHandle);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
{
|
||||||
|
_Fail("Invalid method instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int32*)(stackPtr + 0) = methodInstance->GetParamType(paramIdx)->mTypeId;
|
||||||
|
*(int16*)(stackPtr + 4) = 0; // Flags
|
||||||
|
CeSetAddrVal(stackPtr + 4+2, GetString(methodInstance->GetParamName(paramIdx)), ptrSize);
|
||||||
|
_FixVariables();
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
|
||||||
{
|
{
|
||||||
int32 typeId = *(int32*)((uint8*)stackPtr);
|
int32 typeId = *(int32*)((uint8*)stackPtr);
|
||||||
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int32));
|
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int32));
|
||||||
|
@ -4226,6 +4355,60 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
handled = true;
|
handled = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMethodEntry)
|
||||||
|
{
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr);
|
||||||
|
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int64));
|
||||||
|
|
||||||
|
if ((mCurEmitContext == NULL) || (mCurEmitContext->mMethodInstance == NULL) ||
|
||||||
|
(methodHandle != (int64)mCurEmitContext->mMethodInstance))
|
||||||
|
{
|
||||||
|
_Fail("Code cannot be emitted for this method in this context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!GetStringFromStringView(strViewPtr, mCurEmitContext->mEmitData))
|
||||||
|
{
|
||||||
|
_Fail("Invalid StringView");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMethodExit)
|
||||||
|
{
|
||||||
|
int64 methodHandle = *(int64*)((uint8*)stackPtr);
|
||||||
|
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int64));
|
||||||
|
if ((mCurEmitContext == NULL) || (mCurEmitContext->mMethodInstance == NULL) ||
|
||||||
|
(methodHandle != (int64)mCurEmitContext->mMethodInstance))
|
||||||
|
{
|
||||||
|
_Fail("Code cannot be emitted for this method in this context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!GetStringFromStringView(strViewPtr, mCurEmitContext->mExitEmitData))
|
||||||
|
{
|
||||||
|
_Fail("Invalid StringView");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMixin)
|
||||||
|
{
|
||||||
|
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr);
|
||||||
|
String emitStr;
|
||||||
|
if (!GetStringFromStringView(strViewPtr, emitStr))
|
||||||
|
{
|
||||||
|
_Fail("Invalid StringView");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurModule->CEMixin(mCurTargetSrc, emitStr);
|
||||||
|
|
||||||
|
handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep)
|
else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep)
|
||||||
{
|
{
|
||||||
int32 sleepMS = *(int32*)((uint8*)stackPtr);
|
int32 sleepMS = *(int32*)((uint8*)stackPtr);
|
||||||
|
@ -4461,7 +4644,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
|
|
||||||
if (valueAddr == 0)
|
if (valueAddr == 0)
|
||||||
{
|
{
|
||||||
result = 0;
|
CeSetAddrVal(&result, 0, ptrSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4477,9 +4660,10 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ceModule->TypeIsSubTypeOf(valueType->ToTypeInstance(), ifaceType->ToTypeInstance(), false))
|
if (ceModule->TypeIsSubTypeOf(valueType->ToTypeInstance(), ifaceType->ToTypeInstance(), false))
|
||||||
result = valueAddr;
|
CeSetAddrVal(&result, valueAddr, ptrSize);
|
||||||
else
|
else
|
||||||
result = 0;
|
CeSetAddrVal(&result, 0, ptrSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4973,7 +5157,15 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
|
|
||||||
CE_CHECKADDR(valueAddr, sizeof(int32));
|
CE_CHECKADDR(valueAddr, sizeof(int32));
|
||||||
int32 objTypeId = *(int32*)(memStart + valueAddr);
|
int32 objTypeId = *(int32*)(memStart + valueAddr);
|
||||||
auto valueType = ceModule->mContext->mTypes[objTypeId]->ToTypeInstance();
|
|
||||||
|
auto bfObjectType = GetBfType(objTypeId);
|
||||||
|
if ((bfObjectType == NULL) || (!bfObjectType->IsTypeInstance()))
|
||||||
|
{
|
||||||
|
_Fail("Invalid object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto valueType = bfObjectType->ToTypeInstance();
|
||||||
BfMethodInstance* methodInstance = NULL;
|
BfMethodInstance* methodInstance = NULL;
|
||||||
|
|
||||||
if (valueType != NULL)
|
if (valueType != NULL)
|
||||||
|
@ -5671,8 +5863,10 @@ void CeMachine::CompileStarted()
|
||||||
|
|
||||||
void CeMachine::CompileDone()
|
void CeMachine::CompileDone()
|
||||||
{
|
{
|
||||||
// So things like delted local methods get recheckeds
|
// So things like deleted local methods get recheckeds
|
||||||
mRevision++;
|
mRevision++;
|
||||||
|
mTypeInfoMap.Clear();
|
||||||
|
mMethodInstanceSet.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
|
void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
|
||||||
|
@ -6008,12 +6202,48 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
|
||||||
{
|
{
|
||||||
ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;
|
ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;
|
||||||
}
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_GetMethod")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_GetMethod;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_GetMethodCount")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_GetMethodCount;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_Method_ToString")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_Method_ToString;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_Method_GetName")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_Method_GetName;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_Method_GetInfo")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_Method_GetInfo;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_Method_GetParamInfo")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_Method_GetParamInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
|
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
|
||||||
{
|
{
|
||||||
if (methodDef->mName == "Comptime_EmitDefinition")
|
if (methodDef->mName == "Comptime_EmitTypeBody")
|
||||||
{
|
{
|
||||||
ceFunction->mFunctionKind = CeFunctionKind_EmitDefinition;
|
ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_EmitMethodEntry")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_EmitMethodEntry;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_EmitMethodExit")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_EmitMethodExit;
|
||||||
|
}
|
||||||
|
else if (methodDef->mName == "Comptime_EmitMixin")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_EmitMixin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
|
else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
|
||||||
|
@ -6188,6 +6418,52 @@ CeFunction* CeMachine::GetPreparedFunction(BfMethodInstance* methodInstance)
|
||||||
return ceFunction;
|
return ceFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CeTypeInfo* CeMachine::GetTypeInfo(BfType* type)
|
||||||
|
{
|
||||||
|
if (type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
auto typeInstance = type->ToTypeInstance();
|
||||||
|
if (typeInstance == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CeTypeInfo* ceTypeInfo = NULL;
|
||||||
|
if (!mTypeInfoMap.TryAdd(type, NULL, &ceTypeInfo))
|
||||||
|
{
|
||||||
|
if (ceTypeInfo->mRevision == typeInstance->mRevision)
|
||||||
|
return ceTypeInfo;
|
||||||
|
ceTypeInfo->mMethodInstances.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
mCeModule->PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
||||||
|
ceTypeInfo->mRevision = typeInstance->mRevision;
|
||||||
|
for (auto& methodGroup : typeInstance->mMethodInstanceGroups)
|
||||||
|
{
|
||||||
|
if (methodGroup.mDefault != NULL)
|
||||||
|
{
|
||||||
|
mMethodInstanceSet.Add(methodGroup.mDefault);
|
||||||
|
ceTypeInfo->mMethodInstances.Add(methodGroup.mDefault);
|
||||||
|
}
|
||||||
|
if (methodGroup.mMethodSpecializationMap != NULL)
|
||||||
|
{
|
||||||
|
for (auto& kv : *methodGroup.mMethodSpecializationMap)
|
||||||
|
{
|
||||||
|
mMethodInstanceSet.Add(kv.mValue);
|
||||||
|
ceTypeInfo->mMethodInstances.Add(kv.mValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ceTypeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfMethodInstance* CeMachine::GetMethodInstance(int64 methodHandle)
|
||||||
|
{
|
||||||
|
BfMethodInstance* methodInstance = (BfMethodInstance*)(intptr)methodHandle;
|
||||||
|
if (!mMethodInstanceSet.Contains(methodInstance))
|
||||||
|
return false;
|
||||||
|
return methodInstance;
|
||||||
|
}
|
||||||
|
|
||||||
void CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func)
|
void CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func)
|
||||||
{
|
{
|
||||||
if (mPreparingFunction != NULL)
|
if (mPreparingFunction != NULL)
|
||||||
|
|
|
@ -254,7 +254,17 @@ enum CeFunctionKind
|
||||||
CeFunctionKind_GetReflectTypeByName,
|
CeFunctionKind_GetReflectTypeByName,
|
||||||
CeFunctionKind_GetReflectSpecializedType,
|
CeFunctionKind_GetReflectSpecializedType,
|
||||||
CeFunctionKind_Type_GetCustomAttribute,
|
CeFunctionKind_Type_GetCustomAttribute,
|
||||||
CeFunctionKind_EmitDefinition,
|
CeFunctionKind_GetMethodCount,
|
||||||
|
CeFunctionKind_GetMethod,
|
||||||
|
CeFunctionKind_Method_ToString,
|
||||||
|
CeFunctionKind_Method_GetName,
|
||||||
|
CeFunctionKind_Method_GetInfo,
|
||||||
|
CeFunctionKind_Method_GetParamInfo,
|
||||||
|
|
||||||
|
CeFunctionKind_EmitTypeBody,
|
||||||
|
CeFunctionKind_EmitMethodEntry,
|
||||||
|
CeFunctionKind_EmitMethodExit,
|
||||||
|
CeFunctionKind_EmitMixin,
|
||||||
CeFunctionKind_Sleep,
|
CeFunctionKind_Sleep,
|
||||||
CeFunctionKind_Char32_ToLower,
|
CeFunctionKind_Char32_ToLower,
|
||||||
CeFunctionKind_Char32_ToUpper,
|
CeFunctionKind_Char32_ToUpper,
|
||||||
|
@ -613,11 +623,14 @@ class CeEmitContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BfType* mType;
|
BfType* mType;
|
||||||
|
BfMethodInstance* mMethodInstance;
|
||||||
String mEmitData;
|
String mEmitData;
|
||||||
|
String mExitEmitData;
|
||||||
|
|
||||||
CeEmitContext()
|
CeEmitContext()
|
||||||
{
|
{
|
||||||
mType = NULL;
|
mType = NULL;
|
||||||
|
mMethodInstance = NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -662,6 +675,7 @@ public:
|
||||||
int GetTypeIdFromType(addr_ce typeAddr);
|
int GetTypeIdFromType(addr_ce typeAddr);
|
||||||
addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
|
addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
|
||||||
addr_ce GetString(int stringId);
|
addr_ce GetString(int stringId);
|
||||||
|
addr_ce GetString(const StringImpl& str);
|
||||||
addr_ce GetConstantData(BeConstant* constant);
|
addr_ce GetConstantData(BeConstant* constant);
|
||||||
BfType* GetBfType(int typeId);
|
BfType* GetBfType(int typeId);
|
||||||
void PrepareConstStructEntry(CeConstStructData& constStructData);
|
void PrepareConstStructEntry(CeConstStructData& constStructData);
|
||||||
|
@ -677,12 +691,20 @@ public:
|
||||||
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
|
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CeTypeInfo
|
||||||
|
{
|
||||||
|
Array<BfMethodInstance*> mMethodInstances;
|
||||||
|
int mRevision;
|
||||||
|
};
|
||||||
|
|
||||||
class CeMachine
|
class CeMachine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
|
Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
|
||||||
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
|
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
|
||||||
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
|
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
|
||||||
|
Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
|
||||||
|
HashSet<BfMethodInstance*> mMethodInstanceSet;
|
||||||
|
|
||||||
Array<CeContext*> mContextList;
|
Array<CeContext*> mContextList;
|
||||||
|
|
||||||
|
@ -722,6 +744,8 @@ public:
|
||||||
void CheckFunctions();
|
void CheckFunctions();
|
||||||
CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
|
CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
|
||||||
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
|
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
|
||||||
|
CeTypeInfo* GetTypeInfo(BfType* type);
|
||||||
|
BfMethodInstance* GetMethodInstance(int64 methodHandle);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void CompileStarted();
|
void CompileStarted();
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Tests
|
namespace Tests
|
||||||
{
|
{
|
||||||
|
@ -27,11 +29,26 @@ namespace Tests
|
||||||
[Comptime]
|
[Comptime]
|
||||||
public void ApplyToType(Type type)
|
public void ApplyToType(Type type)
|
||||||
{
|
{
|
||||||
Compiler.EmitDefinition(type, scope $"""
|
Compiler.EmitTypeBody(type, scope $"""
|
||||||
public int32 m{mMemberName} = {mInitVal};
|
public int32 m{mMemberName} = {mInitVal};
|
||||||
public int32 GetVal{mMemberName}() => mC;
|
public int32 GetVal{mMemberName}() => mC;
|
||||||
""");
|
""");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(.Method)]
|
||||||
|
struct LogAttribute : Attribute, IComptimeMethodApply
|
||||||
|
{
|
||||||
|
public static String gLog = new .() ~ delete _;
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public void ApplyToMethod(ComptimeMethodInfo method)
|
||||||
|
{
|
||||||
|
String emit = scope $"LogAttribute.gLog.AppendF($\"Called {method}";
|
||||||
|
for (var fieldIdx < method.ParamCount)
|
||||||
|
emit.AppendF($" {{ {method.GetParamName(fieldIdx)} }}");
|
||||||
|
emit.Append("\");");
|
||||||
|
Compiler.EmitMethodEntry(method, emit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,13 +60,19 @@ namespace Tests
|
||||||
[OnCompile(.TypeInit), Comptime]
|
[OnCompile(.TypeInit), Comptime]
|
||||||
public static void Generate()
|
public static void Generate()
|
||||||
{
|
{
|
||||||
Compiler.EmitDefinition(typeof(Self), """
|
Compiler.EmitTypeBody(typeof(Self), """
|
||||||
public int32 mB = 234;
|
public int32 mB = 234;
|
||||||
public int32 GetValB() => mB;
|
public int32 GetValB() => mB;
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Log]
|
||||||
|
public static void MethodA(int a, int b)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -59,6 +82,12 @@ namespace Tests
|
||||||
Test.Assert(ca.GetValB() == 234);
|
Test.Assert(ca.GetValB() == 234);
|
||||||
Test.Assert(ca.mC == 345);
|
Test.Assert(ca.mC == 345);
|
||||||
Test.Assert(ca.GetValC() == 345);
|
Test.Assert(ca.GetValC() == 345);
|
||||||
|
|
||||||
|
Compiler.Mixin("int val = 99;");
|
||||||
|
Test.Assert(val == 99);
|
||||||
|
|
||||||
|
MethodA(34, 45);
|
||||||
|
Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue