diff --git a/src/c/CMakeLists.txt b/src/c/CMakeLists.txt index 0d75407d..03207123 100644 --- a/src/c/CMakeLists.txt +++ b/src/c/CMakeLists.txt @@ -12,11 +12,15 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least Clang 9.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) message(FATAL_ERROR "Clang++ version must be at least 9.0!") - elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 11) + elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14) + set(PERFFLOWASPECT_CLANG_14_NEWER TRUE CACHE BOOL "using >=clang14") + add_definitions(-DPERFFLOWASPECT_CLANG_14_NEWER) + elseif ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 11) AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)) set(PERFFLOWASPECT_CLANG_11_NEWER TRUE CACHE BOOL "using >=clang11") + set(PERFFLOWASPECT_CLANG_14_NEWER FALSE CACHE BOOL "using < clang14") add_definitions(-DPERFFLOWASPECT_CLANG_11_NEWER) elseif (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11) - set(PERFFLOWASPECT_CLANG_11_NEWER FALSE CACHE BOOL "using >=clang11") + set(PERFFLOWASPECT_CLANG_11_NEWER FALSE CACHE BOOL "using < clang11") endif() else() message(WARNING "Unsupported CXX compiler: please use Clang >= 9.0") diff --git a/src/c/host-configs/lassen-4.14.0-ppc64le-clang@14.0.5-gcc@8.3.1.cmake b/src/c/host-configs/lassen-4.14.0-ppc64le-clang@14.0.5-gcc@8.3.1.cmake index 43651809..34f1ff71 100644 --- a/src/c/host-configs/lassen-4.14.0-ppc64le-clang@14.0.5-gcc@8.3.1.cmake +++ b/src/c/host-configs/lassen-4.14.0-ppc64le-clang@14.0.5-gcc@8.3.1.cmake @@ -11,6 +11,10 @@ set(CMAKE_C_COMPILER "/usr/tce/packages/clang/clang-14.0.5-gcc-8.3.1/bin/clang" CACHE PATH "") set(CMAKE_CXX_COMPILER "/usr/tce/packages/clang/clang-14.0.5-gcc-8.3.1/bin/clang++" CACHE PATH "") set(LLVM_DIR "/usr/tce/packages/clang/clang-ibm-14.0.5-gcc-8.3.1/lib/cmake/llvm" CACHE PATH "") + +# Clang 14 supports both legacy and new pass manager. +# Use the -flegacy-pass-manager if you want to use the legacy pass. +# Use -fpass-plugin= to use the new pass # Use both C and CXX flags to support both targets. -set(CMAKE_C_FLAGS "-flegacy-pass-manager" CACHE STRING "") -set(CMAKE_CXX_FLAGS "-flegacy-pass-manager" CACHE STRING "") +# set(CMAKE_C_FLAGS "-flegacy-pass-manager" CACHE STRING "") +# set(CMAKE_CXX_FLAGS "-flegacy-pass-manager" CACHE STRING "") diff --git a/src/c/test/CMakeLists.txt b/src/c/test/CMakeLists.txt index 754e231f..2b2781e4 100644 --- a/src/c/test/CMakeLists.txt +++ b/src/c/test/CMakeLists.txt @@ -11,14 +11,22 @@ message(STATUS "Adding CXX unit tests") foreach(TEST ${SMOKETESTS}) message(STATUS " [*] Adding test: ${TEST}") add_executable(${TEST} ${TEST}.cpp) - set_source_files_properties(${TEST}.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + if (PERFFLOWASPECT_CLANG_14_NEWER) + set_source_files_properties(${TEST}.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fpass-plugin=../weaver/weave/libWeavePass.so -fPIC") + else() + set_source_files_properties(${TEST}.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + endif() target_link_libraries(${TEST} ${perfflow_deps}) endforeach() if(PERFFLOWASPECT_WITH_MULTITHREADS) message(STATUS " [*] Adding test: smoketest_MT") add_executable(smoketest_MT smoketest_MT.cpp) - set_source_files_properties(smoketest_MT.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + if (PERFFLOWASPECT_CLANG_14_NEWER) + set_source_files_properties(smoketest_MT.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fpass-plugin=../weaver/weave/libWeavePass.so -fPIC") + else() + set_source_files_properties(smoketest_MT.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + endif() set(THREADS_PREFER_PTHREAD_FLAG ON) target_link_libraries(smoketest_MT ${perfflow_deps} pthread) endif() @@ -26,14 +34,22 @@ endif() if(PERFFLOWASPECT_WITH_MPI) message(STATUS " [*] Adding test: smoketest_MPI") add_executable(smoketest_MPI smoketest_MPI.cpp) - set_source_files_properties(smoketest_MPI.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + if (PERFFLOWASPECT_CLANG_14_NEWER) + set_source_files_properties(smoketest_MPI.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fpass-plugin=../weaver/weave/libWeavePass.so -fPIC") + else() + set_source_files_properties(smoketest_MPI.cpp COMPILE_FLAGS "-Xclang -load -Xclang ../weaver/weave/libWeavePass.so -fPIC") + endif() include_directories(${MPI_INCLUDE_PATH}) target_link_libraries(smoketest_MPI ${perfflow_deps} ${MPI_LIBRARIES}) endif() if(PERFFLOWASPECT_WITH_CUDA) message(STATUS " [*] Adding test: smoketest_cuda") - set(CUDA_NVCC_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler=-Xclang -Xcompiler=-load -Xcompiler=-Xclang -Xcompiler=../../../weaver/weave/libWeavePass.so") + if (PERFFLOWASPECT_CLANG_14_NEWER) + set(CUDA_NVCC_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler=-Xclang -Xcompiler=-load -Xcompiler=-Xclang -Xcompiler=../../../weaver/weave/libWeavePass.so -Xcompiler=-fpass-plugin=../../../weaver/weave/libWeavePass.so") + else() + set(CUDA_NVCC_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler=-Xclang -Xcompiler=-load -Xcompiler=-Xclang -Xcompiler=../../../weaver/weave/libWeavePass.so") + endif() cuda_add_executable(smoketest_cuda smoketest_cuda_wrapper.cpp smoketest_cuda_kernel.cu) target_link_libraries(smoketest_cuda ${perfflow_deps} ${CUDA_LIBRARIES}) endif() diff --git a/src/c/weaver/weave/CMakeLists.txt b/src/c/weaver/weave/CMakeLists.txt index 1702a662..30aebd1e 100644 --- a/src/c/weaver/weave/CMakeLists.txt +++ b/src/c/weaver/weave/CMakeLists.txt @@ -1,7 +1,16 @@ -add_library(WeavePass MODULE - # List your source files here. - perfflow_weave.cpp -) +if (PERFFLOWASPECT_CLANG_14_NEWER) + # Add the new pass + add_library(WeavePass MODULE + # List your source files here. + perfflow_weave_new_pass.cpp + ) +else() + # Add the legacy pass if we have Clang < 14. + add_library(WeavePass MODULE + # List your source files here. + perfflow_weave_legacy_pass.cpp + ) +endif() # Use C++11 to compile our pass (i.e., supply -std=c++11). target_compile_features(WeavePass PRIVATE cxx_range_for cxx_auto_type) diff --git a/src/c/weaver/weave/perfflow_weave.cpp b/src/c/weaver/weave/perfflow_weave_common.cpp similarity index 84% rename from src/c/weaver/weave/perfflow_weave.cpp rename to src/c/weaver/weave/perfflow_weave_common.cpp index 4e81003c..21d07fc6 100644 --- a/src/c/weaver/weave/perfflow_weave.cpp +++ b/src/c/weaver/weave/perfflow_weave_common.cpp @@ -8,34 +8,87 @@ * SPDX-License-Identifier: LGPL-3.0 \************************************************************/ -#include "llvm/IR/Value.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/LegacyPassManager.h" -#ifdef PERFFLOWASPECT_CLANG_11_NEWER -#include "llvm/IR/AbstractCallSite.h" -#else -#include "llvm/IR/CallSite.h" -#endif -#include "llvm/IR/Module.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Support/raw_ostream.h" - -#include "../../parser/perfflow_parser.hpp" -#include "perfflow_weave.hpp" - -using namespace llvm; +#include "perfflow_weave_common.hpp" + +/****************************************************************************** + * * + * Public Method of WeaveCommon Class * + * * + ******************************************************************************/ + +bool WeaveCommon::modifyAnnotatedFunctions(Module &m) +{ + auto annotations = m.getNamedGlobal("llvm.global.annotations"); + if (!annotations) + { + return false; + } + + bool changed = false; + auto a = cast (annotations->getOperand(0)); + for (unsigned int i = 0; i < a->getNumOperands(); i++) + { + auto e = cast (a->getOperand(i)); + if (auto *fn = dyn_cast (e->getOperand(0)->getOperand(0))) + { + auto anno = cast( + cast(e->getOperand(1)->getOperand(0)) + ->getOperand(0)) + ->getAsCString(); + std::string pcut, scope, flow; + if (perfflow_parser_parse(anno.data(), pcut, scope, flow) == 0) + { + if (pcut == "around" || pcut == "before") + changed = insertBefore(m, *fn, + anno, 0, scope, flow, pcut) || changed; + else if (pcut == "around_async" || pcut == "before_async") + { + changed = insertBefore(m, *fn, + anno, 1, scope, flow, pcut) || changed; + } + if (pcut == "around" || pcut == "after") + { + if (pcut == "around") + { + if (flow == "in" || flow == "out") + { + flow = "NA"; + } + } + changed = insertAfter(m, *fn, + anno, 0, scope, flow, pcut) || changed; + } + else if (pcut == "around_async" || pcut == "after_async") + { + if (pcut == "around") + { + if (flow == "in" || flow == "out") + { + flow = "NA"; + } + } + changed = insertAfter(m, *fn, + anno, 1, scope, flow, pcut) || changed; + } + } + else + { + errs() << "WeavePass[WARN]: Ignoring " << anno << "\n"; + } + } + } + return changed; + +} /****************************************************************************** * * - * Private Methods of WeavingPass Class * + * Private Methods of WeaveCommon Class * * * ******************************************************************************/ -bool WeavingPass::insertAfter(Module &m, Function &f, StringRef &a, +bool WeaveCommon::insertAfter(Module &m, Function &f, StringRef &a, int async, std::string &scope, std::string &flow, std::string pcut) { if (m.empty() || f.empty()) @@ -88,7 +141,7 @@ bool WeavingPass::insertAfter(Module &m, Function &f, StringRef &a, return true; } -bool WeavingPass::insertBefore(Module &m, Function &f, StringRef &a, +bool WeaveCommon::insertBefore(Module &m, Function &f, StringRef &a, int async, std::string &scope, std::string &flow, std::string pcut) { if (m.empty() || f.empty()) @@ -135,98 +188,6 @@ bool WeavingPass::insertBefore(Module &m, Function &f, StringRef &a, return true; } - -/****************************************************************************** - * * - * Public Methods of WeavingPass Class * - * * - ******************************************************************************/ - -bool WeavingPass::doInitialization(Module &m) -{ - outs() << "WeavePass loaded successfully. \n"; - - auto annotations = m.getNamedGlobal("llvm.global.annotations"); - if (!annotations) - { - return false; - } - - bool changed = false; - auto a = cast (annotations->getOperand(0)); - for (unsigned int i = 0; i < a->getNumOperands(); i++) - { - auto e = cast (a->getOperand(i)); - if (auto *fn = dyn_cast (e->getOperand(0)->getOperand(0))) - { - auto anno = cast( - cast(e->getOperand(1)->getOperand(0)) - ->getOperand(0)) - ->getAsCString(); - std::string pcut, scope, flow; - if (perfflow_parser_parse(anno.data(), pcut, scope, flow) == 0) - { - if (pcut == "around" || pcut == "before") - changed = insertBefore(m, *fn, - anno, 0, scope, flow, pcut) || changed; - else if (pcut == "around_async" || pcut == "before_async") - { - changed = insertBefore(m, *fn, - anno, 1, scope, flow, pcut) || changed; - } - if (pcut == "around" || pcut == "after") - { - if (pcut == "around") - { - if (flow == "in" || flow == "out") - { - flow = "NA"; - } - } - changed = insertAfter(m, *fn, - anno, 0, scope, flow, pcut) || changed; - } - else if (pcut == "around_async" || pcut == "after_async") - { - if (pcut == "around") - { - if (flow == "in" || flow == "out") - { - flow = "NA"; - } - } - changed = insertAfter(m, *fn, - anno, 1, scope, flow, pcut) || changed; - } - } - else - { - errs() << "WeavePass[WARN]: Ignoring " << anno << "\n"; - } - } - } - return changed; -} - -bool WeavingPass::runOnFunction(Function &F) -{ - return false; -} - -char WeavingPass::ID = 0; - -// Automatically enable the pass. -// http://adriansampson.net/blog/clangpass.html -static void registerWeavingPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) -{ - PM.add(new WeavingPass()); -} - -static RegisterStandardPasses -RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, - registerWeavingPass); - /* * vi:tabstop=4 shiftwidth=4 expandtab */ diff --git a/src/c/weaver/weave/perfflow_weave_common.hpp b/src/c/weaver/weave/perfflow_weave_common.hpp new file mode 100644 index 00000000..4881c560 --- /dev/null +++ b/src/c/weaver/weave/perfflow_weave_common.hpp @@ -0,0 +1,229 @@ +/************************************************************\ + * Copyright 2021 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\************************************************************/ + +#ifndef PERFFLOW_WEAVE_COMMON_H +#define PERFFLOW_WEAVE_COMMON_H + +#include "llvm/IR/Value.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/LegacyPassManager.h" +#if defined(PERFFLOWASPECT_CLANG_11_NEWER) || defined(PERFFLOWASPECT_CLANG_14_NEWER) +#include "llvm/IR/AbstractCallSite.h" +#else +#include "llvm/IR/CallSite.h" +#endif +#include "llvm/IR/Module.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Support/raw_ostream.h" + +#include "../../parser/perfflow_parser.hpp" + +namespace { + +class WeaveCommon +{ +private: + bool insertAfter(Module &m, Function &f, StringRef &a, + int async, std::string &scope, std::string &flow, std::string pcut); + + + bool insertBefore(Module &m, Function &f, StringRef &a, + int async, std::string &scope, std::string &flow, std::string pcut); + +public: + bool modifyAnnotatedFunctions(Module &m); + +}; + +/* +Public Member definition. +Need to clean this up so it reads better, and doesn't look like C++ jargon with random casts and is explainable. +*/ + +bool WeaveCommon::modifyAnnotatedFunctions(Module &m) +{ + auto annotations = m.getNamedGlobal("llvm.global.annotations"); + if (!annotations) + { + return false; + } + + bool changed = false; + auto a = cast (annotations->getOperand(0)); + for (unsigned int i = 0; i < a->getNumOperands(); i++) + { + auto e = cast (a->getOperand(i)); + if (auto *fn = dyn_cast (e->getOperand(0)->getOperand(0))) + { + auto anno = cast( + cast(e->getOperand(1)->getOperand(0)) + ->getOperand(0)) + ->getAsCString(); + std::string pcut, scope, flow; + if (perfflow_parser_parse(anno.data(), pcut, scope, flow) == 0) + { + if (pcut == "around" || pcut == "before") + changed = insertBefore(m, *fn, + anno, 0, scope, flow, pcut) || changed; + else if (pcut == "around_async" || pcut == "before_async") + { + changed = insertBefore(m, *fn, + anno, 1, scope, flow, pcut) || changed; + } + if (pcut == "around" || pcut == "after") + { + if (pcut == "around") + { + if (flow == "in" || flow == "out") + { + flow = "NA"; + } + } + changed = insertAfter(m, *fn, + anno, 0, scope, flow, pcut) || changed; + } + else if (pcut == "around_async" || pcut == "after_async") + { + if (pcut == "around") + { + if (flow == "in" || flow == "out") + { + flow = "NA"; + } + } + changed = insertAfter(m, *fn, + anno, 1, scope, flow, pcut) || changed; + } + } + else + { + errs() << "WeavePass[WARN]: Ignoring " << anno << "\n"; + } + } + } + return changed; + +} + +/* +Private Member Function Definitions +*/ + +bool WeaveCommon::insertAfter(Module &m, Function &f, StringRef &a, + int async, std::string &scope, std::string &flow, std::string pcut) +{ + if (m.empty() || f.empty()) + { + return false; + } + + auto &context = m.getContext(); + Type *voidType = Type::getVoidTy(context); + Type *int32Type = Type::getInt32Ty(context); + Type *int8PtrType = Type::getInt8PtrTy(context); + std::vector params; + params.push_back(int32Type); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + + // voidType is return type, params are parameters and no variable length args + FunctionType *weaveFuncTy = FunctionType::get(voidType, params, false); + // Note: Use FunctionCallee after for Clang 9 or higher + FunctionCallee after = m.getOrInsertFunction("perfflow_weave_after", + weaveFuncTy); + // Constant *after = m.getOrInsertFunction("perfflow_weave_after", + // weaveFuncTy); + + // iterate through blocks + for (BasicBlock &bb : f) + { + Instruction *inst = bb.getTerminator(); + if (isa(inst) || isa(inst)) + { + IRBuilder<> builder(inst); + Value *v1 = builder.CreateGlobalStringPtr(m.getName(), "str"); + Value *v2 = builder.CreateGlobalStringPtr(f.getName(), "str"); + Value *v3 = builder.CreateGlobalStringPtr(StringRef(scope), "str"); + Value *v4 = builder.CreateGlobalStringPtr(StringRef(flow), "str"); + Value *v5 = builder.CreateGlobalStringPtr(StringRef(pcut), "str"); + std::vector args; + args.push_back(ConstantInt::get(Type::getInt32Ty(context), async)); + args.push_back(v1); + args.push_back(v2); + args.push_back(v3); + args.push_back(v4); + args.push_back(v5); + builder.CreateCall(after, args); + } + } + return true; +} + +bool WeaveCommon::insertBefore(Module &m, Function &f, StringRef &a, + int async, std::string &scope, std::string &flow, std::string pcut) +{ + if (m.empty() || f.empty()) + { + return false; + } + + auto &context = m.getContext(); + Type *voidType = Type::getVoidTy(context); + Type *int32Type = Type::getInt32Ty(context); + Type *int8PtrType = Type::getInt8PtrTy(context); + std::vector params; + params.push_back(int32Type); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + params.push_back(int8PtrType); + + // voidType is return type, params are parameters and no variable length args + FunctionType *weaveFuncTy = FunctionType::get(voidType, params, false); + // Note: User FunctionCallee before for Clang >= 9.0 + FunctionCallee before = m.getOrInsertFunction("perfflow_weave_before", + weaveFuncTy); + //Constant *before = m.getOrInsertFunction ("perfflow_weave_before", + // weaveFuncTy); + auto &entry = f.getEntryBlock(); + IRBuilder<> builder(&entry); + Value *v1 = builder.CreateGlobalStringPtr(m.getName(), "str"); + Value *v2 = builder.CreateGlobalStringPtr(f.getName(), "str"); + Value *v3 = builder.CreateGlobalStringPtr(StringRef(scope), "str"); + Value *v4 = builder.CreateGlobalStringPtr(StringRef(flow), "str"); + Value *v5 = builder.CreateGlobalStringPtr(StringRef(pcut), "str"); + builder.SetInsertPoint(&entry, entry.begin()); + std::vector args; + args.push_back(ConstantInt::get(Type::getInt32Ty(context), async)); + args.push_back(v1); + args.push_back(v2); + args.push_back(v3); + args.push_back(v4); + args.push_back(v5); + builder.CreateCall(before, args); + + return true; +} + +} // End namespace + +#endif // PERFFLOW_WEAVE_COMMON_H + + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/c/weaver/weave/perfflow_weave_legacy_pass.cpp b/src/c/weaver/weave/perfflow_weave_legacy_pass.cpp new file mode 100644 index 00000000..11d317b7 --- /dev/null +++ b/src/c/weaver/weave/perfflow_weave_legacy_pass.cpp @@ -0,0 +1,59 @@ +/************************************************************\ + * Copyright 2021 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\************************************************************/ + +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Support/raw_ostream.h" + +#include "perfflow_weave_legacy_pass.hpp" +#include "perfflow_weave_common.hpp" + +using namespace llvm; + +/****************************************************************************** + * * + * Public Methods of LegacyWeavingPass Class * + * * + ******************************************************************************/ + +bool LegacyWeavingPass::doInitialization(Module &m) +{ + outs() << "WeavePass loaded successfully. \n"; + + bool changed = false; + + WeaveCommon weaver; + changed = weaver.modifyAnnotatedFunctions(m); + + return changed; +} + +bool LegacyWeavingPass::runOnFunction(Function &F) +{ + return false; +} + +char LegacyWeavingPass::ID = 0; + +// Automatically enable the pass. +// http://adriansampson.net/blog/clangpass.html +static void registerWeavingPass(const PassManagerBuilder &, + legacy::PassManagerBase &PM) +{ + PM.add(new LegacyWeavingPass()); +} + +static RegisterStandardPasses +RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, + registerWeavingPass); + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/c/weaver/weave/perfflow_weave.hpp b/src/c/weaver/weave/perfflow_weave_legacy_pass.hpp similarity index 63% rename from src/c/weaver/weave/perfflow_weave.hpp rename to src/c/weaver/weave/perfflow_weave_legacy_pass.hpp index 3db17445..8ce6a41c 100644 --- a/src/c/weaver/weave/perfflow_weave.hpp +++ b/src/c/weaver/weave/perfflow_weave_legacy_pass.hpp @@ -8,8 +8,8 @@ * SPDX-License-Identifier: LGPL-3.0 \************************************************************/ -#ifndef PERFFLOW_WEAVE_H -#define PERFFLOW_WEAVE_H +#ifndef PERFFLOW_WEAVE_LEGACY_PASS_H +#define PERFFLOW_WEAVE_LEGACY_PASS_H #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" @@ -21,24 +21,17 @@ using namespace llvm; namespace { -class WeavingPass : public FunctionPass +class LegacyWeavingPass : public FunctionPass { public: static char ID; WeavingPass () : FunctionPass (ID) {} virtual bool doInitialization (Module &m); virtual bool runOnFunction (Function &F); - -private: - bool insertAfter (Module &m, Function &f, StringRef &a, - int async, std::string &scope, std::string &flow, std::string pcut); - bool insertBefore (Module &m, Function &f, StringRef &a, - int async, std::string &scope, std::string &flow, std::string pcut); }; - } -#endif // PERFFLOW_WEAVE_H +#endif // PERFFLOW_WEAVE_LEGACY_PASS_H /* diff --git a/src/c/weaver/weave/perfflow_weave_new_pass.cpp b/src/c/weaver/weave/perfflow_weave_new_pass.cpp new file mode 100644 index 00000000..95d14723 --- /dev/null +++ b/src/c/weaver/weave/perfflow_weave_new_pass.cpp @@ -0,0 +1,100 @@ +/************************************************************\ + * Copyright 2021 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\************************************************************/ + +#include "llvm/IR/PassManager.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Support/raw_ostream.h" + +#include "perfflow_weave_new_pass.hpp" +#include "perfflow_weave_common.hpp" +#include +#include + +using namespace llvm; + +/****************************************************************************** + * * + * Public Methods of NewWeavingPass Class * + * * + ******************************************************************************/ + +// Implement the runOnModule Function +bool NewWeavingPass::runOnModule(Module &M) +{ + bool changed = false; + outs() << "NewWeavePass loaded successfully! \n"; + + WeaveCommon weaver; + changed = weaver.modifyAnnotatedFunctions(M); + + // Placeholder: search for the main() function to insert an Adiak call + // Todo: Test Main Entry and Exit here + // Test an Adiak Callback + // Test writing to the metadata in object format + for (auto &F : M) + { + if (F.isDeclaration()) + { + continue; + } + + if (F.getName().str() == "main") + { + outs() << "We found main! We will insert Adiak call here eventually.\n"; + continue; + } + } + + return changed; +} + +// Run on module function. +PreservedAnalyses NewWeavingPass::run(Module &M, + ModuleAnalysisManager &) +{ + bool changed = runOnModule(M); + + return (changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all()); +} + +// Register the new pass. +// See docs here: https://github.com/banach-space/llvm-tutor/blob/main/lib/InjectFuncCall.cpp#L139 +// And here: https://rocmdocs.amd.com/projects/llvm-project/en/latest/LLVM/llvm/html/WritingAnLLVMNewPMPass.html +// https://stackoverflow.com/questions/54447985/how-to-automatically-register-and-load-modern-pass-in-clang/75999804#75999804 +// https://github.com/llvm/llvm-project/issues/56137 + +PassPluginLibraryInfo getNewWeavingPassPluginInfo() +{ + + const auto pass_callback = [](PassBuilder & PB) + { + PB.registerPipelineEarlySimplificationEPCallback( + [&](ModulePassManager & MPM, auto) + { + MPM.addPass(NewWeavingPass()); + return true; + } + ); + }; + + return {LLVM_PLUGIN_API_VERSION, "new-weaving-pass", LLVM_VERSION_STRING, pass_callback}; +} + +extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() +{ + return getNewWeavingPassPluginInfo(); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/c/weaver/weave/perfflow_weave_new_pass.hpp b/src/c/weaver/weave/perfflow_weave_new_pass.hpp new file mode 100644 index 00000000..b93c3e6d --- /dev/null +++ b/src/c/weaver/weave/perfflow_weave_new_pass.hpp @@ -0,0 +1,41 @@ +/************************************************************\ + * Copyright 2021 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\************************************************************/ + +#ifndef PERFFLOW_WEAVE_NEW_PASS_H +#define PERFFLOW_WEAVE_NEW_PASS_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +#include + +using namespace llvm; + +namespace { + +class NewWeavingPass : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); + bool runOnModule(Module &M); + + // Without isRequired returning true, this pass will be skipped for functions + // decorated with the optnone LLVM attribute. Note that clang -O0 decorates + // all functions with optnone. + static bool isRequired() { return true; } + +}; + +} + +#endif // PERFFLOW_WEAVE_NEW_PASS_H + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */