From 6e5b6694a1bb5a20f34e6ea01550f94875d8ee1c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 30 Jun 2020 12:13:20 -0700 Subject: [PATCH] Fixed dynamic Beef libs on Linux/macOS --- BeefRT/CMakeLists.txt | 2 ++ BeefySysLib/platform/posix/PosixCommon.cpp | 40 +++++++++++++++------- IDE/src/BuildContext.bf | 15 +++++--- IDE/src/IDEApp.bf | 16 +++++++-- IDEHelper/Backend/BeIRCodeGen.cpp | 6 ++++ IDEHelper/Compiler/BfCompiler.cpp | 39 +++++++++++++++++++-- IDEHelper/Compiler/BfIRBuilder.h | 4 ++- IDEHelper/Compiler/BfIRCodeGen.cpp | 29 ++++++++++++++++ IDEHelper/Compiler/BfMangler.cpp | 7 +++- bin/build.sh | 15 ++++---- 10 files changed, 139 insertions(+), 34 deletions(-) diff --git a/BeefRT/CMakeLists.txt b/BeefRT/CMakeLists.txt index 65ea462a..ed65705b 100644 --- a/BeefRT/CMakeLists.txt +++ b/BeefRT/CMakeLists.txt @@ -16,6 +16,8 @@ set(OUTPUT_RELEASE Release/bin) project(${PROJECT_NAME} CXX C) +add_compile_options(-fPIC) + # Define Release by default. if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug") diff --git a/BeefySysLib/platform/posix/PosixCommon.cpp b/BeefySysLib/platform/posix/PosixCommon.cpp index 62796dfc..a62fc81e 100644 --- a/BeefySysLib/platform/posix/PosixCommon.cpp +++ b/BeefySysLib/platform/posix/PosixCommon.cpp @@ -304,9 +304,21 @@ void mkdir(const char* path) typedef void(*CrashInfoFunc)(); -static CritSect gSysCritSect; -static String gCrashInfo; -static Array gCrashInfoFuncs; +struct BfpGlobalData +{ + CritSect mSysCritSect; + String mCrashInfo; + Array mCrashInfoFuncs; +}; + +static BfpGlobalData* gBfpGlobal; + +static BfpGlobalData* BfpGetGlobalData() +{ + if (gBfpGlobal == NULL) + gBfpGlobal = new BfpGlobalData(); + return gBfpGlobal; +} #ifdef BFP_HAS_BACKTRACE @@ -437,18 +449,18 @@ static void Crashed() { // { - AutoCrit autoCrit(gSysCritSect); + AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect); String debugDump; debugDump += "**** FATAL APPLICATION ERROR ****\n"; - for (auto func : gCrashInfoFuncs) + for (auto func : BfpGetGlobalData()->mCrashInfoFuncs) func(); - if (!gCrashInfo.IsEmpty()) + if (!BfpGetGlobalData()->mCrashInfo.IsEmpty()) { - debugDump += gCrashInfo; + debugDump += BfpGetGlobalData()->mCrashInfo; debugDump += "\n"; } @@ -498,14 +510,16 @@ static void SigHandler(int sig) } if (sigName != NULL) - gCrashInfo += StrFormat("Signal: %s\n", sigName); + BfpGetGlobalData()->mCrashInfo += StrFormat("Signal: %s\n", sigName); else - gCrashInfo += StrFormat("Signal: %d\n", sig); + BfpGetGlobalData()->mCrashInfo += StrFormat("Signal: %d\n", sig); Crashed(); } BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags) { + BfpGetGlobalData(); + if (version != BFP_VERSION) { BfpSystem_FatalError(StrFormat("Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version).c_str(), "BFP FATAL ERROR"); @@ -561,14 +575,14 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind cra BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc) { - AutoCrit autoCrit(gSysCritSect); - gCrashInfoFuncs.Add(crashInfoFunc); + AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect); + BfpGetGlobalData()->mCrashInfoFuncs.Add(crashInfoFunc); } BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str) // Can do at any time, or during CrashInfoFunc callbacks { - AutoCrit autoCrit(gSysCritSect); - gCrashInfo.Append(str); + AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect); + BfpGetGlobalData()->mCrashInfo.Append(str); } void BfpSystem_Shutdown() diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index 879850ed..d5f9924c 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -313,7 +313,9 @@ namespace IDE testProjectInfo = gApp.mTestManager.GetProjectInfo(project); bool isExe = (project.mGeneralOptions.mTargetType != Project.TargetType.BeefLib) || (testProjectInfo != null); - if (isExe) + bool isDynLib = project.mGeneralOptions.mTargetType == Project.TargetType.BeefDynLib; + + if (isExe || isDynLib) { CopyLibFiles(targetPath, workspaceOptions, options); @@ -335,6 +337,11 @@ namespace IDE linkLine.Append(" "); }*/ + if (isDynLib) + { + linkLine.Append("-shared "); + } + if ((mPlatformType == .Windows) && ((project.mGeneralOptions.mTargetType == Project.TargetType.BeefGUIApplication) || (project.mGeneralOptions.mTargetType == Project.TargetType.C_GUIApplication))) @@ -1092,10 +1099,8 @@ namespace IDE absOutputDir.Append(projectBuildDir); outputDir = absOutputDir; targetPath.Append(outputDir, "/", project.mProjectName); -#if BF_PLATFORM_WINDOWS - targetPath.Append(".exe"); -#endif - + if (mPlatformType == .Windows) + targetPath.Append(".exe"); Debug.Assert(testProjectInfo.mTestExePath == null); testProjectInfo.mTestExePath = new String(targetPath); } diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index ac1d2e37..7fe23703 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -8337,6 +8337,8 @@ namespace IDE bfProject.SetDisabled(false); + let platform = Workspace.PlatformType.GetFromName(mPlatformName); + var preprocessorMacros = scope DefinesSet(); void AddMacros(List macros) { @@ -8406,10 +8408,18 @@ namespace IDE } } + var relocType = options.mBeefOptions.mRelocType; + + if (relocType == .NotSet) + { + if (platform != .Windows) + relocType = .PIC; + } + bfProject.SetOptions(targetType, project.mBeefGlobalOptions.mStartupObject, preprocessorMacros.mDefines, - optimizationLevel, ltoType, options.mBeefOptions.mRelocType, options.mBeefOptions.mPICLevel, + optimizationLevel, ltoType, relocType, options.mBeefOptions.mPICLevel, options.mBeefOptions.mMergeFunctions, options.mBeefOptions.mCombineLoads, options.mBeefOptions.mVectorizeLoops, options.mBeefOptions.mVectorizeSLP); @@ -8930,10 +8940,10 @@ namespace IDE else if (project.mGeneralOptions.mTargetType != .CustomBuild) newString.Append(".exe"); case .macOS: - if (project.mGeneralOptions.mTargetType == Project.TargetType.BeefLib) + if (project.mGeneralOptions.mTargetType == .BeefLib) newString.Append(".dylib"); default: - if (project.mGeneralOptions.mTargetType == Project.TargetType.BeefLib) + if (project.mGeneralOptions.mTargetType == .BeefDynLib) newString.Append(".so"); } } diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index f9300de9..bc087013 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -2318,6 +2318,12 @@ void BeIRCodeGen::HandleNextCmd() else if (attribute == BFIRAttribute_NoRecurse) { } + else if (attribute == BFIRAttribute_Constructor) + { + } + else if (attribute == BFIRAttribute_Destructor) + { + } else BF_FATAL("Unhandled"); } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 920742f4..6f28681c 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -735,7 +735,7 @@ BfIRFunction BfCompiler::CreateLoadSharedLibraries(BfVDataModule* bfModule, Arra bfModule->GetDefaultValue(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)), dllHandleName); BfIRValue namePtr = bfModule->GetStringCharPtr(strNum); - SmallVector args; + SmallVector args; args.push_back(namePtr); args.push_back(dllHandleVar); BfIRValue dllHandleValue = bfModule->mBfIRBuilder->CreateCall(loadSharedLibraryProc.mFunc, args); @@ -1624,6 +1624,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) if ((targetType == BfTargetType_BeefWindowsApplication) && (mOptions.mPlatformType != BfPlatformType_Windows)) targetType = BfTargetType_BeefConsoleApplication; + bool isPosixDynLib = (targetType == BfTargetType_BeefDynLib) && (mOptions.mPlatformType != BfPlatformType_Windows); + // Generate "main" if (!IsHotCompile()) { @@ -1677,7 +1679,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true); bfModule->mBfIRBuilder->SetInsertPoint(entryBlock); -#ifndef BF_PLATFORM_WINDOWS + if ((mOptions.mPlatformType != BfPlatformType_Windows) && + ((targetType == BfTargetType_BeefConsoleApplication) || (targetType == BfTargetType_BeefTest))) { SmallVector paramTypes; paramTypes.push_back(int32Type); @@ -1692,7 +1695,6 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) args.push_back(bfModule->mBfIRBuilder->GetArgument(1)); bfModule->mBfIRBuilder->CreateCall(setCmdLineFunc, args); } -#endif BfIRBlock initSkipBlock; if (targetType == BfTargetType_BeefDynLib) @@ -1949,6 +1951,37 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize); bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, NULL, 0, dbgArrayType, false, irVal); } + + if (isPosixDynLib) + { + auto voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None)); + SizedArray paramTypes; + BfIRFunctionType funcType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes); + BfIRFunction func = bfModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_Internal, "BfDynLib__Startup"); + bfModule->mBfIRBuilder->SetActiveFunction(func); + bfModule->mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_Constructor); + auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("main", true); + bfModule->mBfIRBuilder->SetInsertPoint(entryBlock); + + SmallVector startArgs; + startArgs.push_back(bfModule->mBfIRBuilder->CreateConstNull()); + startArgs.push_back(bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1)); + startArgs.push_back(bfModule->mBfIRBuilder->CreateConstNull()); + bfModule->mBfIRBuilder->CreateCall(mainFunc, startArgs); + bfModule->mBfIRBuilder->CreateRetVoid(); + + ////////////////////////////////////////////////////////////////////////// + + func = bfModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_Internal, "BfDynLib__Shutdown"); + bfModule->mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_Destructor); + bfModule->mBfIRBuilder->SetActiveFunction(func); + entryBlock = bfModule->mBfIRBuilder->CreateBlock("main", true); + bfModule->mBfIRBuilder->SetInsertPoint(entryBlock); + SmallVector stopArgs; + startArgs[1] = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0); + bfModule->mBfIRBuilder->CreateCall(mainFunc, startArgs); + bfModule->mBfIRBuilder->CreateRetVoid(); + } } // Generate "System.GC.MarkAllStaticMembers" diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index e76ddf60..7e1b7039 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -611,7 +611,9 @@ enum BfIRAttribute BFIRAttribute_NoFramePointerElim, BFIRAttribute_DllImport, BFIRAttribute_DllExport, - BFIRAttribute_NoRecurse + BFIRAttribute_NoRecurse, + BFIRAttribute_Constructor, + BFIRAttribute_Destructor, }; struct BfIRFunctionType diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 47b2aa4b..28ea6c5a 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -2737,6 +2737,35 @@ void BfIRCodeGen::HandleNextCmd() { func->addFnAttr("no-frame-pointer-elim", "true"); } + else if ((attribute == BFIRAttribute_Constructor) || (attribute == BFIRAttribute_Destructor)) + { + CmdParamVec members; + members.push_back(llvm::Type::getInt32Ty(*mLLVMContext)); + members.push_back(func->getType()); + members.push_back(llvm::Type::getInt8PtrTy(*mLLVMContext)); + llvm::StructType* structType = llvm::StructType::get(*mLLVMContext, members); + + CmdParamVec structVals; + structVals.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mLLVMContext), 0x7FFFFF00)); + structVals.push_back(func); + structVals.push_back(llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(*mLLVMContext))); + auto constStruct = llvm::ConstantStruct::get(structType, structVals); + + CmdParamVec structArrVals; + structArrVals.push_back(constStruct); + + auto arrTy = llvm::ArrayType::get(structType, 1); + auto constArr = llvm::ConstantArray::get(arrTy, structArrVals); + + auto globalVariable = new llvm::GlobalVariable( + *mLLVMModule, + arrTy, + false, + llvm::GlobalValue::AppendingLinkage, + constArr, + (attribute == BFIRAttribute_Constructor) ? "llvm.global_ctors" : "llvm.global_dtors", + NULL, llvm::GlobalValue::NotThreadLocal); + } else func->addAttribute(argIdx, LLVMMapAttribute(attribute)); } diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index 90ca75c2..a1073c7b 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -719,7 +719,12 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst) } mangleContext.mPrefixObjectPointer = true; - String methodName = methodInst->mMethodDef->mName; + StringT<128> methodName = methodInst->mMethodDef->mName; + for (int i = 0; i < (int)methodName.length(); i++) + { + if (methodName[i] == '@') + methodName[i] = '$'; + } if (methodInst->mMethodDef->mIsOperator) { diff --git a/bin/build.sh b/bin/build.sh index 521f13d3..774752b7 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -3,6 +3,7 @@ echo Starting build.sh PATH=/usr/local/bin:$PATH:$HOME/bin SCRIPTPATH=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P) +ROOTPATH="$(dirname "$SCRIPTPATH")" echo Building from from $SCRIPTPATH cd $SCRIPTPATH @@ -50,15 +51,13 @@ else LINKOPTS="-ldl -lpthread -Wl,-rpath -Wl,\$ORIGIN" fi -if [ ! -L libBeefRT_d.a ]; then - ln -s ../../jbuild_d/Debug/bin/libBeefRT_d.a libBeefRT_d.a - ln -s ../../jbuild_d/Debug/bin/libBeefySysLib_d.$LIBEXT libBeefySysLib_d.$LIBEXT - ln -s ../../jbuild_d/Debug/bin/libIDEHelper_d.$LIBEXT libIDEHelper_d.$LIBEXT +ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libBeefRT_d.a libBeefRT_d.a +ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libBeefySysLib_d.$LIBEXT libBeefySysLib_d.$LIBEXT +ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libIDEHelper_d.$LIBEXT libIDEHelper_d.$LIBEXT - ln -s ../../jbuild/Release/bin/libBeefRT.a libBeefRT.a - ln -s ../../jbuild/Release/bin/libBeefySysLib.$LIBEXT libBeefySysLib.$LIBEXT - ln -s ../../jbuild/Release/bin/libIDEHelper.$LIBEXT libIDEHelper.$LIBEXT -fi +ln -s -f $ROOTPATH/jbuild/Release/bin/libBeefRT.a libBeefRT.a +ln -s -f $ROOTPATH/jbuild/Release/bin/libBeefySysLib.$LIBEXT libBeefySysLib.$LIBEXT +ln -s -f $ROOTPATH/jbuild/Release/bin/libIDEHelper.$LIBEXT libIDEHelper.$LIBEXT ### DEBUG ###