1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Code generator support

This commit is contained in:
Brian Fiete 2021-12-11 09:08:42 -08:00
parent 195c705a46
commit 73099e4a04
15 changed files with 1472 additions and 83 deletions

View file

@ -420,6 +420,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mInternalTypeDef = NULL;
mPlatformTypeDef = NULL;
mCompilerTypeDef = NULL;
mCompilerGeneratorTypeDef = NULL;
mDiagnosticsDebugTypeDef = NULL;
mIDisposableTypeDef = NULL;
mIIntegerTypeDef = NULL;
@ -6765,6 +6766,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mInternalTypeDef = _GetRequiredType("System.Internal");
mPlatformTypeDef = _GetRequiredType("System.Platform");
mCompilerTypeDef = _GetRequiredType("System.Compiler");
mCompilerGeneratorTypeDef = _GetRequiredType("System.Compiler.Generator");
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
mIIntegerTypeDef = _GetRequiredType("System.IInteger");
@ -8087,6 +8089,149 @@ String BfCompiler::GetTypeDefList()
return result;
}
String BfCompiler::GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args)
{
if (typeInst == NULL)
{
auto type = mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_BaseType);
if (type != NULL)
typeInst = type->ToTypeInstance();
if (typeInst == NULL)
return "";
}
BfTypeVector typeVector;
typeVector.Add(typeInst);
auto generatorTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompilerGeneratorTypeDef)->ToTypeInstance();
auto methodDef = generatorTypeInst->mTypeDef->GetMethodByName(generatorMethodName);
auto moduleMethodInstance = mContext->mUnreifiedModule->GetMethodInstance(generatorTypeInst, methodDef, typeVector);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mContext->mUnreifiedModule->mCurMethodInstance, moduleMethodInstance.mMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mContext->mUnreifiedModule->mCurTypeInstance, typeInst);
BfExprEvaluator exprEvaluator(mContext->mUnreifiedModule);
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_Comptime;
SizedArray<BfIRValue, 1> irArgs;
if (args != NULL)
irArgs.Add(mContext->mUnreifiedModule->GetStringObjectValue(*args));
auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs, NULL, BfCreateCallFlags_None);
if (callResult.mValue.IsConst())
{
auto stringPtr = mContext->mUnreifiedModule->GetStringPoolString(callResult.mValue, mContext->mUnreifiedModule->mBfIRBuilder);
if (stringPtr != NULL)
return *stringPtr;
}
return "";
}
void BfCompiler::HandleGeneratorErrors(StringImpl& result)
{
if ((mPassInstance->mErrors.IsEmpty()) && (mPassInstance->mOutStream.IsEmpty()))
return;
result.Clear();
for (auto& msg : mPassInstance->mOutStream)
{
String error = msg;
error.Replace('\n', '\r');
result += "!error\t";
result += error;
result += "\n";
}
}
String BfCompiler::GetGeneratorTypeDefList()
{
String result;
BfProject* curProject = NULL;
Dictionary<BfProject*, int> projectIds;
BfResolvePassData resolvePassData;
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
BfPassInstance passInstance(mSystem);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
for (auto typeDef : mSystem->mTypeDefs)
{
if (typeDef->mProject->mDisabled)
continue;
if (typeDef->mIsPartial)
continue;
auto type = mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_BaseType);
if ((type != NULL) && (type->IsTypeInstance()))
{
auto typeInst = type->ToTypeInstance();
if ((typeInst->mBaseType != NULL) && (typeInst->mBaseType->IsInstanceOf(mCompilerGeneratorTypeDef)))
{
result += typeDef->mProject->mName;
result += ":";
result += BfTypeUtils::TypeToString(typeDef, BfTypeNameFlag_InternalName);
String nameString = GetGeneratorString(typeDef, typeInst, "GetName", NULL);
if (!nameString.IsEmpty())
result += "\t" + nameString;
result += "\n";
}
}
}
HandleGeneratorErrors(result);
return result;
}
String BfCompiler::GetGeneratorInitData(const StringImpl& typeName, const StringImpl& args)
{
BfResolvePassData resolvePassData;
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
BfPassInstance passInstance(mSystem);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
Array<BfTypeDef*> typeDefs;
GetTypeDefs(typeName, typeDefs);
String result;
for (auto typeDef : typeDefs)
{
result += GetGeneratorString(typeDef, NULL, "InitUI", &args);
if (!result.IsEmpty())
break;
}
HandleGeneratorErrors(result);
return result;
}
String BfCompiler::GetGeneratorGenData(const StringImpl& typeName, const StringImpl& args)
{
BfResolvePassData resolvePassData;
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
BfPassInstance passInstance(mSystem);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
Array<BfTypeDef*> typeDefs;
GetTypeDefs(typeName, typeDefs);
String result;
for (auto typeDef : typeDefs)
{
result += GetGeneratorString(typeDef, NULL, "Generate", &args);
if (!result.IsEmpty())
break;
}
HandleGeneratorErrors(result);
return result;
}
struct TypeDefMatchHelper
{
public:
@ -8580,9 +8725,9 @@ String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr)
return result;
}
String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
void BfCompiler::GetTypeDefs(const StringImpl& inTypeName, Array<BfTypeDef*>& typeDefs)
{
BfProject* project = NULL;
BfProject* project = NULL;
int idx = 0;
int sep = (int)inTypeName.IndexOf(':');
@ -8595,7 +8740,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
String typeName;
int genericCount = 0;
int pendingGenericCount = 0;
for ( ; idx < (int)inTypeName.length(); idx++)
for (; idx < (int)inTypeName.length(); idx++)
{
char c = inTypeName[idx];
if (c == '<')
@ -8606,7 +8751,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
genericCount++;
else if (c == '>')
{
pendingGenericCount = genericCount;
pendingGenericCount = genericCount;
genericCount = 0;
}
}
@ -8620,10 +8765,10 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
typeName += c;
}
}
bool isGlobals = false;
if (typeName == ":static")
{
{
typeName.clear();
isGlobals = true;
}
@ -8637,63 +8782,73 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
if (typeName[i] == '+')
typeName[i] = '.';
String result;
TypeDefMatchHelper matchHelper(result);
BfAtomComposite nameComposite;
BfAtomComposite nameComposite;
if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
{
{
auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
while (itr)
{
{
auto typeDef = *itr;
if ((!typeDef->mIsPartial) &&
(typeDef->mProject == project) &&
(typeDef->mFullName == nameComposite) &&
(typeDef->IsGlobalsContainer() == isGlobals) &&
(typeDef->GetSelfGenericParamCount() == pendingGenericCount))
{
auto refNode = typeDef->GetRefNode();
result += "S";
matchHelper.AddLocation(refNode);
result += "\n";
for (auto fieldDef : typeDef->mFields)
{
result += "F";
result += fieldDef->mName;
matchHelper.AddFieldDef(fieldDef);
}
for (auto propDef : typeDef->mProperties)
{
if (propDef->GetRefNode() == NULL)
continue;
result += "P";
matchHelper.AddPropertyDef(typeDef, propDef);
}
for (auto methodDef : typeDef->mMethods)
{
if ((methodDef->mMethodType != BfMethodType_Normal) &&
(methodDef->mMethodType != BfMethodType_Mixin) &&
(methodDef->mMethodType != BfMethodType_Ctor) &&
(methodDef->mMethodType != BfMethodType_Dtor))
continue;
if (methodDef->mMethodDeclaration == NULL)
continue;
result += "M";
matchHelper.AddMethodDef(methodDef);
}
{
typeDefs.Add(typeDef);
}
itr.MoveToNextHashMatch();
}
}
}
String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
{
Array<BfTypeDef*> typeDefs;
GetTypeDefs(inTypeName, typeDefs);
String result;
TypeDefMatchHelper matchHelper(result);
for (auto typeDef : typeDefs)
{
auto refNode = typeDef->GetRefNode();
result += "S";
matchHelper.AddLocation(refNode);
result += "\n";
for (auto fieldDef : typeDef->mFields)
{
result += "F";
result += fieldDef->mName;
matchHelper.AddFieldDef(fieldDef);
}
for (auto propDef : typeDef->mProperties)
{
if (propDef->GetRefNode() == NULL)
continue;
result += "P";
matchHelper.AddPropertyDef(typeDef, propDef);
}
for (auto methodDef : typeDef->mMethods)
{
if ((methodDef->mMethodType != BfMethodType_Normal) &&
(methodDef->mMethodType != BfMethodType_Mixin) &&
(methodDef->mMethodType != BfMethodType_Ctor) &&
(methodDef->mMethodType != BfMethodType_Dtor))
continue;
if (methodDef->mMethodDeclaration == NULL)
continue;
result += "M";
matchHelper.AddMethodDef(methodDef);
}
}
return result;
}
@ -8970,6 +9125,30 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone()
#endif
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorTypeDefList(BfCompiler* bfCompiler)
{
String& outString = *gTLStrReturn.Get();
outString.clear();
outString = bfCompiler->GetGeneratorTypeDefList();
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorInitData(BfCompiler* bfCompiler, char* typeDefName, char* args)
{
String& outString = *gTLStrReturn.Get();
outString.clear();
outString = bfCompiler->GetGeneratorInitData(typeDefName, args);
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorGenData(BfCompiler* bfCompiler, char* typeDefName, char* args)
{
String& outString = *gTLStrReturn.Get();
outString.clear();
outString = bfCompiler->GetGeneratorGenData(typeDefName, args);
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler)
{
String& outString = *gTLStrReturn.Get();

View file

@ -374,6 +374,7 @@ public:
BfTypeDef* mInternalTypeDef;
BfTypeDef* mPlatformTypeDef;
BfTypeDef* mCompilerTypeDef;
BfTypeDef* mCompilerGeneratorTypeDef;
BfTypeDef* mDiagnosticsDebugTypeDef;
BfTypeDef* mIDisposableTypeDef;
BfTypeDef* mIIntegerTypeDef;
@ -511,9 +512,15 @@ public:
void ProcessAutocompleteTempType();
void GetSymbolReferences();
void Cancel();
void RequestFastFinish();
void RequestFastFinish();
String GetTypeDefList();
String GetTypeDefMatches(const StringImpl& searchSrc);
String GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args);
void HandleGeneratorErrors(StringImpl& result);
String GetGeneratorTypeDefList();
String GetGeneratorInitData(const StringImpl& typeName, const StringImpl& args);
String GetGeneratorGenData(const StringImpl& typeName, const StringImpl& args);
String GetTypeDefMatches(const StringImpl& searchSrc);
void GetTypeDefs(const StringImpl& typeName, Array<BfTypeDef*>& typeDefs);
String GetTypeDefInfo(const StringImpl& typeName);
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);

View file

@ -11789,7 +11789,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (mExpectingType->IsFunction())
{
BfIRValue result;
if ((hasIncompatibleCallingConventions) && (mModule->HasCompiledOutput()))
if ((hasIncompatibleCallingConventions) && (mModule->HasExecutedOutput()))
{
//
{
@ -11949,7 +11949,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
// Do we need a special delegate type for this?
if (((captureThisByValue) || (needsSplat) || (implicitParamCount > 0) /*|| (hasIncompatibleCallingConventions)*/) &&
(mModule->HasCompiledOutput()))
(mModule->HasExecutedOutput()))
{
hasCaptures = true;
auto curProject = mModule->mCurTypeInstance->mTypeDef->mProject;
@ -12030,7 +12030,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
// Do we need specialized calling code for this?
BfIRValue funcValue;
if (((needsSplat) || (implicitParamCount > 0) || (hasIncompatibleCallingConventions)) &&
(mModule->HasCompiledOutput()))
(mModule->HasExecutedOutput()))
{
int fieldIdx = 0;
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
@ -12208,7 +12208,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
// >> delegate.mTarget = bindResult.mTarget
BfIRValue valPtr;
if (mModule->HasCompiledOutput())
if (mModule->HasExecutedOutput())
{
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
@ -12226,7 +12226,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (!funcValue)
{
if ((mModule->HasCompiledOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
if ((mModule->HasExecutedOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
mModule->AssertErrorState();
return;
}
@ -13188,7 +13188,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
mModule->mIncompleteMethodCount++;
SetAndRestoreValue<BfClosureState*> prevClosureState(mModule->mCurMethodState->mClosureState, &closureState);
if (mModule->HasCompiledOutput())
if (mModule->HasExecutedOutput())
mModule->SetupIRMethod(methodInstance, methodInstance->mIRFunction, methodInstance->mAlwaysInline);
// This keeps us from giving errors twice. ProcessMethod can give errors when we capture by value but needed to
@ -14415,7 +14415,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
if (!bindResult.mFunc)
{
BF_ASSERT((!mModule->HasCompiledOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
BF_ASSERT((!mModule->HasExecutedOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
appendSizeValue = mModule->GetConstValue(0);
}
else
@ -19717,7 +19717,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
}
}
}
else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) &&
else if (((mModule->HasExecutedOutput()) || (mModule->mIsComptimeModule)) &&
(wantsChecks))
{
if (checkedKind == BfCheckedKind_NotSet)

View file

@ -9617,6 +9617,11 @@ bool BfModule::HasCompiledOutput()
return (!mSystem->mIsResolveOnly) && (mGeneratesCode) && (!mIsComptimeModule);
}
bool BfModule::HasExecutedOutput()
{
return ((!mSystem->mIsResolveOnly) && (mGeneratesCode)) || (mIsComptimeModule);
}
// We will skip the object access check for any occurrences of this value
void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
{
@ -15818,7 +15823,7 @@ void BfModule::CreateStaticCtor()
auto methodDef = mCurMethodInstance->mMethodDef;
BfIRBlock exitBB;
if ((HasCompiledOutput()) && (!mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
if ((HasExecutedOutput()) && (!mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
{
auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
auto didStaticInitVarAddr = mBfIRBuilder->CreateGlobalVariable(
@ -17041,7 +17046,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
break;
}
if ((HasCompiledOutput()) && (matchedMethod != NULL))
if ((HasExecutedOutput()) && (matchedMethod != NULL))
{
SizedArray<BfIRValue, 1> args;
auto ctorBodyMethodInstance = GetMethodInstance(mCurTypeInstance->mBaseType, matchedMethod, BfTypeVector());
@ -18486,7 +18491,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
return;
}
if (HasCompiledOutput())
if (HasExecutedOutput())
{
BF_ASSERT(mIsModuleMutable);
}
@ -19713,7 +19718,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
skipBody = true;
skipEndChecks = true;
if ((HasCompiledOutput()) || (mIsComptimeModule))
if (HasExecutedOutput())
{
// Clear out DebugLoc - to mark the ".addr" code as part of prologue
mBfIRBuilder->ClearDebugLocation();
@ -19977,7 +19982,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
{
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
if ((HasCompiledOutput()) || (mIsComptimeModule))
if (HasExecutedOutput())
{
EmitEnumToStringBody();
}
@ -19990,7 +19995,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
{
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
if ((HasCompiledOutput()) || (mIsComptimeModule))
if (HasExecutedOutput())
{
EmitTupleToStringBody();
}
@ -20032,7 +20037,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
mBfIRBuilder->CreateRetVoid();
}
else if ((HasCompiledOutput()) || (mIsComptimeModule))
else if (HasExecutedOutput())
{
String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);

View file

@ -1633,6 +1633,7 @@ public:
bool IsTargetingBeefBackend();
bool WantsLifetimes();
bool HasCompiledOutput();
bool HasExecutedOutput();
void SkipObjectAccessCheck(BfTypedValue typedVal);
void EmitObjectAccessCheck(BfTypedValue typedVal);
void EmitEnsureInstructionAt();

View file

@ -1288,7 +1288,7 @@ void CeBuilder::Build()
auto methodInstance = mCeFunction->mMethodInstance;
if (methodInstance != NULL)
{
{
BfMethodInstance dupMethodInstance;
dupMethodInstance.CopyFrom(methodInstance);
auto methodDef = methodInstance->mMethodDef;
@ -1638,10 +1638,10 @@ void CeBuilder::Build()
EmitBinaryOp(CeOp_Shl_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_RightShift:
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_ARightShift:
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
default:
Fail("Invalid binary op");
@ -2476,7 +2476,18 @@ void CeBuilder::Build()
EmitFrameOffset(ceSize);
}
break;
case BfIRIntrinsic_MemSet:
{
CeOperand ceDestPtr = GetOperand(castedInst->mArgs[0].mValue);
CeOperand ceValue = GetOperand(castedInst->mArgs[1].mValue);
CeOperand ceSize = GetOperand(castedInst->mArgs[2].mValue);
Emit(CeOp_MemSet);
EmitFrameOffset(ceDestPtr);
EmitFrameOffset(ceValue);
EmitFrameOffset(ceSize);
}
break;
case BfIRIntrinsic_AtomicFence:
// Nothing to do