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

Bug fixes, installer, [Export]

Fixed a bunch of bugs in aggregate const initializers
Fixed ZIP bugs
Fixed a compilation case where we change protection while reifying a type
Added another project kind - Dynamic Library
Added [Export] for DLL method exporting
Fixed some issues of things being  generated as __NOINLINE incorrectly
Fixed an issue with module extensions with not-yet-demanded on-demand methods
Started adding Installer
This commit is contained in:
Brian Fiete 2019-08-27 08:04:41 -07:00
parent efa22e51fb
commit 09016c8dc0
135 changed files with 3615 additions and 2337 deletions

View file

@ -477,7 +477,13 @@ bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject)
BfTypeInstance* typeInst = checkType->ToTypeInstance();
if (typeInst != NULL)
{
{
if ((typeInst->mTypeDef->mProject != NULL) && (typeInst->mTypeDef->mProject != curProject))
{
if (typeInst->mTypeDef->mProject->mTargetType == BfTargetType_BeefDynLib)
return false;
}
if (checkType->IsInterface())
return typeInst->mIsReified;
@ -757,6 +763,211 @@ BfIRFunction BfCompiler::CreateLoadSharedLibraries(BfVDataModule* bfModule, Arra
return loadSharedLibFunc;
}
void BfCompiler::GetTestMethods(BfVDataModule* bfModule, Array<TestMethod>& testMethods, HashContext& vdataHashCtx)
{
vdataHashCtx.Mixin(0xBEEF0001); // Marker
auto _CheckMethod = [&](BfTypeInstance* typeInstance, BfMethodInstance* methodInstance)
{
auto project = typeInstance->mTypeDef->mProject;
if (project->mTargetType != BfTargetType_BeefTest)
return;
if (project != bfModule->mProject)
return;
bool isTest = false;
if ((methodInstance->GetCustomAttributes() != NULL) &&
(methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
isTest = true;
if (!isTest)
return;
if (!methodInstance->mMethodDef->mIsStatic)
{
bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it is not static", bfModule->MethodToString(methodInstance).c_str()),
methodInstance->mMethodDef->GetRefNode());
bfModule->mHadBuildError = true;
return;
}
if (methodInstance->GetParamCount() > 0)
{
if ((methodInstance->GetParamInitializer(0) == NULL) &&
(methodInstance->GetParamKind(0) != BfParamKind_Params))
{
bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it contains parameters without defaults", bfModule->MethodToString(methodInstance).c_str()),
methodInstance->mMethodDef->GetRefNode());
bfModule->mHadBuildError = true;
return;
}
}
BF_ASSERT(typeInstance->IsReified());
TestMethod testMethod;
testMethod.mMethodInstance = methodInstance;
testMethods.Add(testMethod);
if (!bfModule->mProject->mUsedModules.Contains(typeInstance->mModule))
bfModule->mProject->mUsedModules.Add(typeInstance->mModule);
vdataHashCtx.Mixin(methodInstance->GetOwner()->mTypeId);
vdataHashCtx.Mixin(methodInstance->mMethodDef->mIdx);
};
for (auto type : mContext->mResolvedTypes)
{
auto typeInstance = type->ToTypeInstance();
if (typeInstance == NULL)
continue;
for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
{
if (methodInstanceGroup.mDefault != NULL)
{
_CheckMethod(typeInstance, methodInstanceGroup.mDefault);
}
}
}
}
void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& testMethods, BfIRValue& retValue)
{
for (auto& testMethod : testMethods)
{
auto methodInstance = testMethod.mMethodInstance;
auto typeInstance = methodInstance->GetOwner();
testMethod.mName += bfModule->TypeToString(typeInstance);
testMethod.mName += ".";
testMethod.mName += methodInstance->mMethodDef->mName;
testMethod.mName += "\t";
auto testAttribute = methodInstance->GetCustomAttributes()->Get(mTestAttributeTypeDef);
for (auto& field : testAttribute->mSetField)
{
auto constant = typeInstance->mConstHolder->GetConstant(field.mParam.mValue);
if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean) && (constant->mBool))
{
BfFieldDef* fieldDef = field.mFieldRef;
if (fieldDef->mName == "ShouldFail")
{
testMethod.mName += "Sf";
}
else if (fieldDef->mName == "Profile")
{
testMethod.mName += "Pr";
}
else if (fieldDef->mName == "Ignore")
{
testMethod.mName += "Ig";
}
}
}
bfModule->UpdateSrcPos(methodInstance->mMethodDef->GetRefNode(), (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
testMethod.mName += StrFormat("\t%s\t%d\t%d", bfModule->mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), bfModule->mCurFilePosition.mCurLine, bfModule->mCurFilePosition.mCurColumn);
}
std::stable_sort(testMethods.begin(), testMethods.end(),
[](const TestMethod& lhs, const TestMethod& rhs)
{
return lhs.mName < rhs.mName;
});
String methodData;
for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
{
String& methodName = testMethods[methodIdx].mName;
if (!methodData.IsEmpty())
methodData += "\n";
methodData += methodName;
}
//////////////////////////////////////////////////////////////////////////
auto testInitMethod = bfModule->GetInternalMethod("Test_Init");
auto testQueryMethod = bfModule->GetInternalMethod("Test_Query");
auto testFinishMethod = bfModule->GetInternalMethod("Test_Finish");
auto char8PtrType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Char8));
BfIRType strCharType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)methodData.length() + 1);
BfIRValue strConstant = bfModule->mBfIRBuilder->CreateConstString(methodData);
BfIRValue gv = bfModule->mBfIRBuilder->CreateGlobalVariable(strCharType,
true, BfIRLinkageType_External,
strConstant, "__bfTestData");
BfIRValue strPtrVal = bfModule->mBfIRBuilder->CreateBitCast(gv, bfModule->mBfIRBuilder->MapType(char8PtrType));
SizedArray<BfIRValue, 4> irArgs;
irArgs.Add(strPtrVal);
bfModule->mBfIRBuilder->CreateCall(testInitMethod.mFunc, irArgs);
BfIRBlock testHeadBlock = bfModule->mBfIRBuilder->CreateBlock("testHead");
BfIRBlock testEndBlock = bfModule->mBfIRBuilder->CreateBlock("testEnd");
bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
bfModule->mBfIRBuilder->AddBlock(testHeadBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testHeadBlock);
irArgs.clear();
auto testVal = bfModule->mBfIRBuilder->CreateCall(testQueryMethod.mFunc, irArgs);
auto switchVal = bfModule->mBfIRBuilder->CreateSwitch(testVal, testEndBlock, (int)testMethods.size());
for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
{
auto methodInstance = testMethods[methodIdx].mMethodInstance;
String& methodName = testMethods[methodIdx].mName;
auto testBlock = bfModule->mBfIRBuilder->CreateBlock(StrFormat("test%d", methodIdx));
bfModule->mBfIRBuilder->AddSwitchCase(switchVal, bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodIdx), testBlock);
bfModule->mBfIRBuilder->AddBlock(testBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testBlock);
auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
irArgs.clear();
if (methodInstance->GetParamCount() > 0)
{
if (methodInstance->GetParamKind(0) == BfParamKind_Params)
{
auto paramType = methodInstance->GetParamType(0);
auto paramTypeInst = paramType->ToTypeInstance();
BfTypedValue paramVal = BfTypedValue(bfModule->mBfIRBuilder->CreateAlloca(bfModule->mBfIRBuilder->MapTypeInst(paramTypeInst)), paramType);
bfModule->InitTypeInst(paramVal, NULL, false, BfIRValue());
//TODO: Assert 'length' var is at slot 1
auto arrayBits = bfModule->mBfIRBuilder->CreateBitCast(paramVal.mValue, bfModule->mBfIRBuilder->MapType(paramTypeInst->mBaseType));
auto addr = bfModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1);
auto storeInst = bfModule->mBfIRBuilder->CreateAlignedStore(bfModule->GetConstValue(0), addr, 4);
irArgs.Add(paramVal.mValue);
}
else
{
for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++)
{
irArgs.Add(methodInstance->mDefaultValues[defaultIdx]);
}
}
}
BfExprEvaluator exprEvaluator(bfModule);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
}
bfModule->mBfIRBuilder->AddBlock(testEndBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testEndBlock);
irArgs.clear();
bfModule->mBfIRBuilder->CreateCall(testFinishMethod.mFunc, irArgs);
retValue = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
}
void BfCompiler::CreateVData(BfVDataModule* bfModule)
{
bool isHotCompile = IsHotCompile();
@ -842,81 +1053,9 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
vdataHashCtx.Mixin(bfModule->mProject->mVDataConfigHash);
struct _TestMethod
{
String mName;
BfMethodInstance* mMethodInstance;
};
Array<_TestMethod> testMethods;
Array<TestMethod> testMethods;
if (project->mTargetType == BfTargetType_BeefTest)
{
vdataHashCtx.Mixin(0xBEEF0001); // Marker
auto _CheckMethod = [&](BfTypeInstance* typeInstance, BfMethodInstance* methodInstance)
{
auto project = typeInstance->mTypeDef->mProject;
if (project->mTargetType != BfTargetType_BeefTest)
return;
if (project != bfModule->mProject)
return;
bool isTest = false;
if ((methodInstance->GetCustomAttributes() != NULL) &&
(methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
isTest = true;
if (!isTest)
return;
if (!methodInstance->mMethodDef->mIsStatic)
{
bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it is not static", bfModule->MethodToString(methodInstance).c_str()),
methodInstance->mMethodDef->GetRefNode());
bfModule->mHadBuildError = true;
return;
}
if (methodInstance->GetParamCount() > 0)
{
if ((methodInstance->GetParamInitializer(0) == NULL) &&
(methodInstance->GetParamKind(0) != BfParamKind_Params))
{
bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it contains parameters without defaults", bfModule->MethodToString(methodInstance).c_str()),
methodInstance->mMethodDef->GetRefNode());
bfModule->mHadBuildError = true;
return;
}
}
BF_ASSERT(typeInstance->IsReified());
_TestMethod testMethod;
testMethod.mMethodInstance = methodInstance;
testMethods.Add(testMethod);
if (!bfModule->mProject->mUsedModules.Contains(typeInstance->mModule))
bfModule->mProject->mUsedModules.Add(typeInstance->mModule);
vdataHashCtx.Mixin(methodInstance->GetOwner()->mTypeId);
vdataHashCtx.Mixin(methodInstance->mMethodDef->mIdx);
};
for (auto type : mContext->mResolvedTypes)
{
auto typeInstance = type->ToTypeInstance();
if (typeInstance == NULL)
continue;
for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
{
if (methodInstanceGroup.mDefault != NULL)
{
_CheckMethod(typeInstance, methodInstanceGroup.mDefault);
}
}
}
}
GetTestMethods(bfModule, testMethods, vdataHashCtx);
Array<BfType*> vdataTypeList;
std::multimap<String, BfTypeInstance*> sortedStaticInitMap;
@ -956,7 +1095,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
auto module = typeInst->mModule;
if (module == NULL)
continue;
if (type->IsInterface())
vdataHashCtx.Mixin(typeInst->mSlotNum);
@ -997,7 +1136,14 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
{
vdataHashCtx.Mixin(baseType->mTypeDef->mSignatureHash);
baseType = baseType->mBaseType;
}
}
if (module->mProject != bfModule->mProject)
{
if ((module->mProject != NULL) && (module->mProject->mTargetType == BfTargetType_BeefDynLib))
continue;
}
if (typeInst->mHasStaticInitMethod)
sortedStaticInitMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
else if (typeInst->mHasStaticDtorMethod) // Only store types not already in the static init map
@ -1437,6 +1583,17 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "main");
}
else if (project->mTargetType == BfTargetType_BeefDynLib)
{
SmallVector<BfIRType, 4> paramTypes;
paramTypes.push_back(nullPtrType); // hinstDLL
paramTypes.push_back(int32Type); // fdwReason
paramTypes.push_back(nullPtrType); // lpvReserved
mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "DllMain");
if (mSystem->mPtrSize == 4)
bfModule->mBfIRBuilder->SetFuncCallingConv(mainFunc, BfIRCallingConv_StdCall);
}
else if (project->mTargetType == BfTargetType_BeefWindowsApplication)
{
SmallVector<BfIRType, 4> paramTypes;
@ -1478,6 +1635,17 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
}
#endif
BfIRBlock initSkipBlock;
if (project->mTargetType == BfTargetType_BeefDynLib)
{
auto initBlock = bfModule->mBfIRBuilder->CreateBlock("doInit", false);
initSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipInit", false);
auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1));
bfModule->mBfIRBuilder->CreateCondBr(cmpResult, initBlock, initSkipBlock);
bfModule->mBfIRBuilder->AddBlock(initBlock);
bfModule->mBfIRBuilder->SetInsertPoint(initBlock);
}
// Do the LoadLibrary calls below priority 100
bool didSharedLibLoad = false;
auto _CheckSharedLibLoad = [&]()
@ -1516,6 +1684,13 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
_CheckSharedLibLoad();
if (initSkipBlock)
{
bfModule->mBfIRBuilder->CreateBr(initSkipBlock);
bfModule->mBfIRBuilder->AddBlock(initSkipBlock);
bfModule->mBfIRBuilder->SetInsertPoint(initSkipBlock);
}
BfIRValue retValue;
if ((project->mTargetType == BfTargetType_BeefConsoleApplication) || (project->mTargetType == BfTargetType_BeefWindowsApplication))
{
@ -1655,142 +1830,24 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
if (!hadRet)
retValue = bfModule->GetConstValue32(0);
}
}
else if (project->mTargetType == BfTargetType_BeefDynLib)
{
retValue = bfModule->GetConstValue32(1);
}
if (project->mTargetType == BfTargetType_BeefTest)
EmitTestMethod(bfModule, testMethods, retValue);
BfIRBlock deinitSkipBlock;
if (project->mTargetType == BfTargetType_BeefDynLib)
{
for (auto& testMethod : testMethods)
{
auto methodInstance = testMethod.mMethodInstance;
auto typeInstance = methodInstance->GetOwner();
testMethod.mName += bfModule->TypeToString(typeInstance);
testMethod.mName += ".";
testMethod.mName += methodInstance->mMethodDef->mName;
testMethod.mName += "\t";
auto testAttribute = methodInstance->GetCustomAttributes()->Get(mTestAttributeTypeDef);
for (auto& field : testAttribute->mSetField)
{
auto constant = typeInstance->mConstHolder->GetConstant(field.mParam.mValue);
if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean) && (constant->mBool))
{
BfFieldDef* fieldDef = field.mFieldRef;
if (fieldDef->mName == "ShouldFail")
{
testMethod.mName += "Sf";
}
else if (fieldDef->mName == "Profile")
{
testMethod.mName += "Pr";
}
else if (fieldDef->mName == "Ignore")
{
testMethod.mName += "Ig";
}
}
}
bfModule->UpdateSrcPos(methodInstance->mMethodDef->GetRefNode(), (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
testMethod.mName += StrFormat("\t%s\t%d\t%d", bfModule->mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), bfModule->mCurFilePosition.mCurLine, bfModule->mCurFilePosition.mCurColumn);
}
std::stable_sort(testMethods.begin(), testMethods.end(),
[](const _TestMethod& lhs, const _TestMethod& rhs)
{
return lhs.mName < rhs.mName;
});
String methodData;
for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
{
String& methodName = testMethods[methodIdx].mName;
if (!methodData.IsEmpty())
methodData += "\n";
methodData += methodName;
}
//////////////////////////////////////////////////////////////////////////
auto testInitMethod = bfModule->GetInternalMethod("Test_Init");
auto testQueryMethod = bfModule->GetInternalMethod("Test_Query");
auto testFinishMethod = bfModule->GetInternalMethod("Test_Finish");
auto char8PtrType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Char8));
BfIRType strCharType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)methodData.length() + 1);
BfIRValue strConstant = bfModule->mBfIRBuilder->CreateConstString(methodData);
BfIRValue gv = bfModule->mBfIRBuilder->CreateGlobalVariable(strCharType,
true, BfIRLinkageType_External,
strConstant, "__bfTestData");
BfIRValue strPtrVal = bfModule->mBfIRBuilder->CreateBitCast(gv, bfModule->mBfIRBuilder->MapType(char8PtrType));
SizedArray<BfIRValue, 4> irArgs;
irArgs.Add(strPtrVal);
bfModule->mBfIRBuilder->CreateCall(testInitMethod.mFunc, irArgs);
BfIRBlock testHeadBlock = bfModule->mBfIRBuilder->CreateBlock("testHead");
BfIRBlock testEndBlock = bfModule->mBfIRBuilder->CreateBlock("testEnd");
bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
bfModule->mBfIRBuilder->AddBlock(testHeadBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testHeadBlock);
irArgs.clear();
auto testVal = bfModule->mBfIRBuilder->CreateCall(testQueryMethod.mFunc, irArgs);
auto switchVal = bfModule->mBfIRBuilder->CreateSwitch(testVal, testEndBlock, (int)testMethods.size());
for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
{
auto methodInstance = testMethods[methodIdx].mMethodInstance;
String& methodName = testMethods[methodIdx].mName;
auto testBlock = bfModule->mBfIRBuilder->CreateBlock(StrFormat("test%d", methodIdx));
bfModule->mBfIRBuilder->AddSwitchCase(switchVal, bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodIdx), testBlock);
bfModule->mBfIRBuilder->AddBlock(testBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testBlock);
auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
irArgs.clear();
if (methodInstance->GetParamCount() > 0)
{
if (methodInstance->GetParamKind(0) == BfParamKind_Params)
{
auto paramType = methodInstance->GetParamType(0);
auto paramTypeInst = paramType->ToTypeInstance();
BfTypedValue paramVal = BfTypedValue(bfModule->mBfIRBuilder->CreateAlloca(bfModule->mBfIRBuilder->MapTypeInst(paramTypeInst)), paramType);
bfModule->InitTypeInst(paramVal, NULL, false, BfIRValue());
//TODO: Assert 'length' var is at slot 1
auto arrayBits = bfModule->mBfIRBuilder->CreateBitCast(paramVal.mValue, bfModule->mBfIRBuilder->MapType(paramTypeInst->mBaseType));
auto addr = bfModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1);
auto storeInst = bfModule->mBfIRBuilder->CreateAlignedStore(bfModule->GetConstValue(0), addr, 4);
irArgs.Add(paramVal.mValue);
}
else
{
for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++)
{
irArgs.Add(methodInstance->mDefaultValues[defaultIdx]);
}
}
}
BfExprEvaluator exprEvaluator(bfModule);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
}
bfModule->mBfIRBuilder->AddBlock(testEndBlock);
bfModule->mBfIRBuilder->SetInsertPoint(testEndBlock);
irArgs.clear();
bfModule->mBfIRBuilder->CreateCall(testFinishMethod.mFunc, irArgs);
retValue = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
auto deinitBlock = bfModule->mBfIRBuilder->CreateBlock("doDeinit", false);
deinitSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipDeinit", false);
auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0));
bfModule->mBfIRBuilder->CreateCondBr(cmpResult, deinitBlock, deinitSkipBlock);
bfModule->mBfIRBuilder->AddBlock(deinitBlock);
bfModule->mBfIRBuilder->SetInsertPoint(deinitBlock);
}
bfModule->mBfIRBuilder->CreateCall(dtorFunc, SizedArray<BfIRValue, 0>());
@ -1801,6 +1858,13 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
bfModule->mBfIRBuilder->CreateCall(shutdownMethod.mFunc, SizedArray<BfIRValue, 0>());
}
if (deinitSkipBlock)
{
bfModule->mBfIRBuilder->CreateBr(deinitSkipBlock);
bfModule->mBfIRBuilder->AddBlock(deinitSkipBlock);
bfModule->mBfIRBuilder->SetInsertPoint(deinitSkipBlock);
}
if (retValue)
bfModule->mBfIRBuilder->CreateRet(retValue);
else
@ -5784,6 +5848,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
}
if ((bfProject->mTargetType != BfTargetType_BeefConsoleApplication) && (bfProject->mTargetType != BfTargetType_BeefWindowsApplication) &&
(bfProject->mTargetType != BfTargetType_BeefDynLib) &&
(bfProject->mTargetType != BfTargetType_C_ConsoleApplication) && (bfProject->mTargetType != BfTargetType_C_WindowsApplication) &&
(bfProject->mTargetType != BfTargetType_BeefTest))
continue;
@ -7866,6 +7931,11 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(BfCompiler*
{
if (!bfProject->ContainsReference(project))
canReference = false;
if (bfProject != project)
{
if (project->mTargetType == BfTargetType_BeefDynLib)
canReference = false;
}
}
if (!canReference)
continue;

View file

@ -291,6 +291,12 @@ public:
BfIRValue mStringVal;
};
struct TestMethod
{
String mName;
BfMethodInstance* mMethodInstance;
};
public:
BfPassInstance* mPassInstance;
FILE* mCompileLogFP;
@ -386,6 +392,8 @@ public:
void CheckModuleStringRefs(BfModule* module, BfVDataModule* vdataModule, int lastModuleRevision, HashSet<int>& foundStringIds, HashSet<int>& dllNameSet, Array<BfMethodInstance*>& dllMethods, Array<BfCompiler::StringValueEntry>& stringValueEntries);
void HashModuleVData(BfModule* module, HashContext& hash);
BfIRFunction CreateLoadSharedLibraries(BfVDataModule* bfModule, Array<BfMethodInstance*>& dllMethods);
void GetTestMethods(BfVDataModule* bfModule, Array<TestMethod>& testMethods, HashContext& vdataHashCtx);
void EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& testMethods, BfIRValue& retValue);
void CreateVData(BfVDataModule* bfModule);
void UpdateDependencyMap(bool deleteUnusued, bool& didWork);
void ProcessPurgatory(bool reifiedOnly);

View file

@ -652,6 +652,11 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
methodDef->mCheckedKind = BfCheckedKind_Checked;
else if (typeRefName == "Unchecked")
methodDef->mCheckedKind = BfCheckedKind_Unchecked;
else if (typeRefName == "Export")
{
mCurTypeDef->mIsAlwaysInclude = true;
methodDef->mImportKind = BfImportKind_Export;
}
else if (typeRefName == "Import")
{
methodDef->mImportKind = BfImportKind_Static;

View file

@ -4305,6 +4305,11 @@ BfIRFunction BfIRBuilder::CreateFunction(BfIRFunctionType funcType, BfIRLinkageT
NEW_CMD_INSERTED_IRVALUE;
mFunctionMap[name] = retVal;
if (name == "??B?$Result@PEAX@System@bf@@SAPEAXU012@@Z")
{
NOP;
}
//BfLogSys(mModule->mSystem, "BfIRBuilder::CreateFunction: %d %s Module:%p\n", retVal.mId, name.c_str(), mModule);
return retVal;
@ -4842,15 +4847,15 @@ BfIRMDNode BfIRBuilder::DbgCreateMethod(BfIRMDNode context, const StringImpl& na
BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateMethod, context, name, linkageName, file, lineNum, type, isLocalToUnit, isDefinition, vk, vIndex, vTableHolder, flags, isOptimized, fn, genericArgs, genericConstValueArgs);
NEW_CMD_INSERTED_IRMD;
if (vIndex == 8)
if (linkageName == "?Unwrap@?$Result@PEAX@System@bf@@AEAAPEAXXZ")
{
NOP;
}
if (mDbgVerifyCodeGen && gDebugDbgLoc)
{
OutputDebugStrF("DbgCreateFunction Context:%d name:%s = %d\n", context.mId, name.c_str(), retVal.mId);
}
// if (mDbgVerifyCodeGen && gDebugDbgLoc)
// {
// OutputDebugStrF("DbgCreateFunction Context:%d name:%s = %d\n", context.mId, name.c_str(), retVal.mId);
// }
return retVal;
}
@ -4860,10 +4865,10 @@ BfIRMDNode BfIRBuilder::DbgCreateFunction(BfIRMDNode context, const StringImpl&
BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateFunction, context, name, linkageName, file, lineNum, type, isLocalToUnit, isDefinition, scopeLine, flags, isOptimized, fn);
NEW_CMD_INSERTED_IRMD;
if (mDbgVerifyCodeGen && gDebugDbgLoc)
{
OutputDebugStrF("DbgCreateFunction Context:%d name:%s = %d\n", context.mId, name.c_str(), retVal.mId);
}
// if (mDbgVerifyCodeGen && gDebugDbgLoc)
// {
// OutputDebugStrF("DbgCreateFunction Context:%d name:%s = %d\n", context.mId, name.c_str(), retVal.mId);
// }
return retVal;
}

View file

@ -1118,8 +1118,8 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen)
// code as we walk the AST
//mBfIRBuilder->mDbgVerifyCodeGen = true;
if (
(mModuleName == "Color")
|| (mModuleName == "Tests_FuncRefs")
(mModuleName == "vdata")
|| (mModuleName == "System_Result_PTR_void")
//|| (mModuleName == "vdata")
|| (mModuleName == "Hey_Dude_Bro_TestClass")
)
@ -4474,7 +4474,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
BF_ASSERT(!methodInstance->GetOwner()->IsUnspecializedType());
// We need to create an empty thunk for this chained method
BfIRFunction func = CreateFunctionFrom(methodInstance);
BfIRFunction func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline);
mBfIRBuilder->SetActiveFunction(func);
auto block = mBfIRBuilder->CreateBlock("entry", true);
mBfIRBuilder->SetInsertPoint(block);
@ -8494,6 +8494,15 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
if (callingConv != BfIRCallingConv_CDecl)
mBfIRBuilder->SetFuncCallingConv(func, callingConv);
SetupLLVMMethod(methodInstance, func, isInlined);
// auto srcModule = methodInstance->GetOwner()->GetModule();
// if ((srcModule != NULL) && (srcModule->mProject != mProject))
// {
// if (srcModule->mProject->mTargetType == BfTargetType_BeefDynLib)
// {
// mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllImport);
// }
// }
return func;
}
@ -10485,12 +10494,7 @@ void BfModule::AddMethodReference(const BfMethodRef& methodRef, BfGetMethodInsta
}
BfModuleMethodInstance BfModule::ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags)
{
if (methodInstance->mMethodDef->mName == "OpenAudio")
{
NOP;
}
{
if ((flags & BfGetMethodInstanceFlag_ResultNotUsed) != 0)
return BfModuleMethodInstance(methodInstance, BfIRValue());
@ -11067,7 +11071,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
if (!mIsModuleMutable)
StartExtension();
if (!mBfIRBuilder->mIgnoreWrites)
if ((!mBfIRBuilder->mIgnoreWrites) && (methodInstance->mDeclModule != NULL))
{
StringT<128> mangledName;
BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
@ -11127,41 +11131,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
}
if ((methodInstance != NULL) && (!doingRedeclare))
{
if (mExtensionCount > 0)
{
if ((mIsModuleMutable) && (!methodInstance->mIRFunction) &&
((projectList.IsEmpty() || ((flags & BfGetMethodInstanceFlag_ExplicitSpecializedModule) != 0))))
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, false);
if (mAwaitingInitFinish)
FinishInit();
// We need to refer to a function that was defined in a prior module
methodInstance->mIRFunction = CreateFunctionFrom(methodInstance);
BF_ASSERT((methodInstance->mDeclModule == this) || (methodInstance->mDeclModule == mContext->mUnreifiedModule) || (methodInstance->mDeclModule == NULL));
methodInstance->mDeclModule = this;
// Add this inlined def to ourselves
if ((methodInstance->mAlwaysInline) && (HasCompiledOutput()) && (!methodInstance->mIsUnspecialized))
{
mIncompleteMethodCount++;
BfInlineMethodRequest* inlineMethodRequest = mContext->mInlineMethodWorkList.Alloc();
inlineMethodRequest->mType = typeInst;
inlineMethodRequest->mFromModule = this;
inlineMethodRequest->mFunc = methodInstance->mIRFunction;
inlineMethodRequest->mFromModuleRevision = mRevision;
inlineMethodRequest->mMethodInstance = methodInstance;
BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this);
BF_ASSERT(mIsModuleMutable);
}
}
}
{
if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
{
{
/*if ((!mCompiler->mIsResolveOnly) && (!isReified))
BF_ASSERT(!methodInstance->mIsReified);*/
@ -11191,6 +11163,44 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
}
}
if (mExtensionCount > 0)
{
if ((mIsModuleMutable) && (!methodInstance->mIRFunction) &&
((projectList.IsEmpty() || ((flags & BfGetMethodInstanceFlag_ExplicitSpecializedModule) != 0))))
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, false);
if ((methodInstance->mMethodDef->mName == "Unwrap") && (mModuleName == "System_Result_PTR_void"))
{
NOP;
}
if (mAwaitingInitFinish)
FinishInit();
// We need to refer to a function that was defined in a prior module
bool isInlined = (methodInstance->mAlwaysInline) || ((flags & BfGetMethodInstanceFlag_ForceInline) != 0);
methodInstance->mIRFunction = CreateFunctionFrom(methodInstance, false, isInlined);
BF_ASSERT((methodInstance->mDeclModule == this) || (methodInstance->mDeclModule == mContext->mUnreifiedModule) || (methodInstance->mDeclModule == NULL));
methodInstance->mDeclModule = this;
// Add this inlined def to ourselves
if ((methodInstance->mAlwaysInline) && (HasCompiledOutput()) && (!methodInstance->mIsUnspecialized))
{
mIncompleteMethodCount++;
BfInlineMethodRequest* inlineMethodRequest = mContext->mInlineMethodWorkList.Alloc();
inlineMethodRequest->mType = typeInst;
inlineMethodRequest->mFromModule = this;
inlineMethodRequest->mFunc = methodInstance->mIRFunction;
inlineMethodRequest->mFromModuleRevision = mRevision;
inlineMethodRequest->mMethodInstance = methodInstance;
BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this);
BF_ASSERT(mIsModuleMutable);
}
}
}
if (mCompiler->IsSkippingExtraResolveChecks())
return BfModuleMethodInstance(methodInstance, BfIRFunction());
else
@ -13545,6 +13555,8 @@ void BfModule::SetupLLVMMethod(BfMethodInstance* methodInstance, BfIRFunction fu
if (mCompiler->mOptions.mNoFramePointerElim)
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_NoFramePointerElim);
if (methodDef->mImportKind == BfImportKind_Export)
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport);
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_NoUnwind);
if (mSystem->mPtrSize == 8) // We need unwind info for debugging

View file

@ -1686,7 +1686,7 @@ public:
void CreateValueTypeEqualsMethod();
BfIRFunction GetIntrinsic(BfMethodInstance* methodInstance, bool reportFailure = false);
BfIRFunction GetBuiltInFunc(BfBuiltInFuncType funcType);
BfIRValue CreateFunctionFrom(BfMethodInstance* methodInstance, bool tryExisting = false, bool isInlined = false);
BfIRValue CreateFunctionFrom(BfMethodInstance* methodInstance, bool tryExisting, bool isInlined);
void EvaluateWithNewScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags);
BfTypedValue CreateValueFromExpression(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL);
BfTypedValue CreateValueFromExpression(BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL);

View file

@ -3434,6 +3434,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (typeRefName == "AlwaysInclude")
implRequired = true;
else if (typeRefName == "Export")
implRequired = true;
else if (typeRefName == "Test")
implRequired = true;
else
@ -4086,7 +4088,7 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
auto module = GetOrCreateMethodModule(methodInstance);
methodInstance->mDeclModule = module;
BfIRValue func = CreateFunctionFrom(methodInstance);
BfIRValue func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline);
methodInstance->mIRFunction = func;
module->mFuncReferences[methodInstance] = func;
@ -4892,8 +4894,10 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfTypeReference* typeRef,
while (checkOuterType != NULL)
{
for (auto checkType : checkOuterType->mTypeDef->mNestedTypes)
{
if ((!isFailurePass) && (!CheckProtection(checkType->mProtection, allowProtected, allowPrivate)))
{
auto latestCheckType = checkType->GetLatest();
if ((!isFailurePass) && (!CheckProtection(latestCheckType->mProtection, allowProtected, allowPrivate)))
continue;
if (checkType->mName->mString == findName)

View file

@ -577,6 +577,7 @@ enum BfImportKind : int8
BfImportKind_None,
BfImportKind_Static,
BfImportKind_Dynamic,
BfImportKind_Export
};
enum BfCheckedKind : int8
@ -911,8 +912,9 @@ struct BfTypeDefMapFuncs : public MultiHashSetFuncs
enum BfTargetType
{
BfTargetType_BeefConsoleApplication,
BfTargetType_BeefWindowsApplication,
BfTargetType_BeefWindowsApplication,
BfTargetType_BeefLib,
BfTargetType_BeefDynLib,
BfTargetType_CustomBuild,
BfTargetType_C_ConsoleApplication,
BfTargetType_C_WindowsApplication,