Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/compiler extension #36

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/llvm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on: [push]

jobs:
build_llvm:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
- macOS-latest
cmake_args:
- "-DLLVM_ENABLE_PROJECTS:STRING=clang;polly"
steps:
- name: Setup Windows
if: startsWith(matrix.os, 'windows')
uses: tstellar/actions/setup-windows@master
with:
arch: amd64
- uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Install Ninja
uses: tstellar/actions/install-ninja@master
with:
os: ${{ runner.os }}
- name: Test LLVM
uses: tstellar/actions/build-test-llvm-project@master
with:
cmake_args: -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}
os: ${{ runner.os }}
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
using namespace clang;
using namespace llvm;

#define HANDLE_EXTENSION(Ext) \
llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
#include "llvm/Support/Extension.def"

namespace {

// Default filename used for profile generation.
Expand Down Expand Up @@ -1086,6 +1090,9 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
<< PluginFN << toString(PassPlugin.takeError());
}
}
#define HANDLE_EXTENSION(Ext) \
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"

LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager);
FunctionAnalysisManager FAM(CodeGenOpts.DebugPassManager);
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ add_clang_library(clangCodeGen
TargetInfo.cpp
VarBypassDetector.cpp

ENABLE_PLUGINS

DEPENDS
${codegen_deps}

Expand Down
4 changes: 0 additions & 4 deletions clang/tools/driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,3 @@ if(CLANG_ORDER_FILE AND
set_target_properties(clang PROPERTIES LINK_DEPENDS ${CLANG_ORDER_FILE})
endif()
endif()

if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
target_link_libraries(clang PRIVATE Polly)
endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
11 changes: 0 additions & 11 deletions clang/tools/driver/cc1_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
exit(GenCrashDiag ? 70 : 1);
}

#ifdef LINK_POLLY_INTO_TOOLS
namespace polly {
void initializePollyPasses(llvm::PassRegistry &Registry);
}
#endif

#ifdef CLANG_HAVE_RLIMITS
#if defined(__linux__) && defined(__PIE__)
static size_t getCurrentStackAllocation() {
Expand Down Expand Up @@ -203,11 +197,6 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();

#ifdef LINK_POLLY_INTO_TOOLS
llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
polly::initializePollyPasses(Registry);
#endif

// Buffer diagnostics from argument parsing so that we can output them using a
// well formed diagnostic object.
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
Expand Down
25 changes: 2 additions & 23 deletions llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -465,29 +465,6 @@ set(LLVM_LIB_FUZZING_ENGINE "" CACHE PATH
option(LLVM_USE_SPLIT_DWARF
"Use -gsplit-dwarf when compiling llvm." OFF)

option(LLVM_POLLY_LINK_INTO_TOOLS "Statically link Polly into tools (if available)" ON)
option(LLVM_POLLY_BUILD "Build LLVM with Polly" ON)

if (EXISTS ${LLVM_MAIN_SRC_DIR}/tools/polly/CMakeLists.txt)
set(POLLY_IN_TREE TRUE)
elseif(LLVM_EXTERNAL_POLLY_SOURCE_DIR)
set(POLLY_IN_TREE TRUE)
else()
set(POLLY_IN_TREE FALSE)
endif()

if (LLVM_POLLY_BUILD AND POLLY_IN_TREE)
set(WITH_POLLY ON)
else()
set(WITH_POLLY OFF)
endif()

if (LLVM_POLLY_LINK_INTO_TOOLS AND WITH_POLLY)
set(LINK_POLLY_INTO_TOOLS ON)
else()
set(LINK_POLLY_INTO_TOOLS OFF)
endif()

# Define an option controlling whether we should build for 32-bit on 64-bit
# platforms, where supported.
if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 )
Expand Down Expand Up @@ -1109,3 +1086,5 @@ endif()
if (LLVM_INCLUDE_UTILS AND LLVM_INCLUDE_TOOLS)
add_subdirectory(utils/llvm-locstats)
endif()

process_llvm_pass_plugins()
75 changes: 73 additions & 2 deletions llvm/cmake/modules/AddLLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ endfunction(set_windows_version_resource_properties)
# )
function(llvm_add_library name)
cmake_parse_arguments(ARG
"MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH"
"MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH;ENABLE_PLUGINS"
"OUTPUT_NAME;PLUGIN_TOOL;ENTITLEMENTS;BUNDLE_PATH"
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS"
${ARGN})
Expand All @@ -414,6 +414,9 @@ function(llvm_add_library name)
else()
llvm_process_sources(ALL_FILES ${ARG_UNPARSED_ARGUMENTS} ${ARG_ADDITIONAL_HEADERS})
endif()
if(ARG_ENABLE_PLUGINS)
set_property(GLOBAL APPEND PROPERTY LLVM_PLUGIN_TARGETS ${name})
endif()

if(ARG_MODULE)
if(ARG_SHARED OR ARG_STATIC)
Expand Down Expand Up @@ -732,7 +735,7 @@ endmacro(add_llvm_library name)

macro(add_llvm_executable name)
cmake_parse_arguments(ARG
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS"
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;ENABLE_PLUGINS"
"ENTITLEMENTS;BUNDLE_PATH"
"DEPENDS"
${ARGN})
Expand Down Expand Up @@ -819,10 +822,78 @@ macro(add_llvm_executable name)
# API for all shared libaries loaded by this executable.
target_link_libraries(${name} PRIVATE ${LLVM_PTHREAD_LIB})
endif()
if(ARG_ENABLE_PLUGINS)
set_property(GLOBAL APPEND PROPERTY LLVM_PLUGIN_TARGETS ${name})
endif()

llvm_codesign(${name} ENTITLEMENTS ${ARG_ENTITLEMENTS} BUNDLE_PATH ${ARG_BUNDLE_PATH})
endmacro(add_llvm_executable name)

# add_llvm_pass_plugin(name)
# Add ${name} as an llvm plugin.
# If option LLVM_${name_upper}_LINK_INTO_TOOLS is set to ON, the plugin is registered statically.
# Otherwise a pluggable shared library is registered.
function(add_llvm_pass_plugin name)

string(TOUPPER ${name} name_upper)

option(LLVM_${name_upper}_LINK_INTO_TOOLS "Statically link ${name} into tools (if available)" OFF)

# process_llvm_pass_plugins takes care of the actual linking, just create an
# object library as of now
add_llvm_library(${name} OBJECT ${ARGN})

if(LLVM_${name_upper}_LINK_INTO_TOOLS)
target_compile_definitions(${name} PRIVATE LLVM_${name_upper}_LINK_INTO_TOOLS)
set_property(TARGET ${name} APPEND PROPERTY COMPILE_DEFINITIONS LLVM_LINK_INTO_TOOLS)
if (TARGET intrinsics_gen)
add_dependencies(obj.${name} intrinsics_gen)
endif()
endif()

message(STATUS "Registering ${name} as a pass plugin (static build: ${LLVM_${name_upper}_LINK_INTO_TOOLS})")
if(LLVM_${name_upper}_LINK_INTO_TOOLS)
set_property(GLOBAL APPEND PROPERTY LLVM_COMPILE_EXTENSIONS ${name})
endif()
endfunction(add_llvm_pass_plugin)

# Generate X Macro file for extension handling. It provides a
# HANDLE_EXTENSION(extension_namespace, ExtensionProject) call for each extension
# allowing client code to define HANDLE_EXTENSION to have a specific code be run for
# each extension.
#
# Also correctly set lib dependencies between plugins and tools.
function(process_llvm_pass_plugins)
get_property(LLVM_EXTENSIONS GLOBAL PROPERTY LLVM_COMPILE_EXTENSIONS)
file(WRITE "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "//extension handlers\n")
foreach(llvm_extension ${LLVM_EXTENSIONS})
string(TOLOWER ${llvm_extension} llvm_extension_lower)

string(TOUPPER ${llvm_extension} llvm_extension_upper)
string(SUBSTRING ${llvm_extension_upper} 0 1 llvm_extension_upper_first)
string(SUBSTRING ${llvm_extension_lower} 1 -1 llvm_extension_lower_tail)
string(CONCAT llvm_extension_project ${llvm_extension_upper_first} ${llvm_extension_lower_tail})

if(LLVM_${llvm_extension_upper}_LINK_INTO_TOOLS)
file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "HANDLE_EXTENSION(${llvm_extension_project})\n")

get_property(llvm_plugin_targets GLOBAL PROPERTY LLVM_PLUGIN_TARGETS)
foreach(llvm_plugin_target ${llvm_plugin_targets})
set_property(TARGET ${llvm_plugin_target} APPEND PROPERTY LINK_LIBRARIES ${llvm_extension})
set_property(TARGET ${llvm_plugin_target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${llvm_extension})
endforeach()
else()
add_llvm_library(${llvm_extension_lower} MODULE obj.${llvm_extension_lower})
endif()

endforeach()
file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "#undef HANDLE_EXTENSION\n")

# only replace if there's an actual change
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def")
file(REMOVE "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp")
endfunction()

function(export_executable_symbols target)
if (LLVM_EXPORTED_SYMBOL_FILE)
# The symbol file should contain the symbols we want the executable to
Expand Down
26 changes: 26 additions & 0 deletions llvm/docs/WritingAnLLVMPass.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,32 @@ implement ``releaseMemory`` to, well, release the memory allocated to maintain
this internal state. This method is called after the ``run*`` method for the
class, before the next call of ``run*`` in your pass.

Building pass plugins
=====================

As an alternative to using ``PLUGIN_TOOL``, LLVM provides a mechanism to
automatically register pass plugins within ``clang``, ``opt`` and ``bugpoint``.
One first needs to create an independent project and add it to either ``tools/``
or, using the MonoRepo layout, at the root of the repo alongside other projects.
This project must contain the following minimal ``CMakeLists.txt``:

.. code-block:: cmake

add_llvm_pass_plugin(Name source0.cpp)

The pass must provide two entry points for the new pass manager, one for static
registration and one for dynamically loaded plugins:

- ``llvm::PassPluginLibraryInfo get##Name##PluginInfo();``
- ``extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() LLVM_ATTRIBUTE_WEAK;``

Pass plugins are compiled and link dynamically by default, but it's
possible to set the following variables to change this behavior:

- ``LLVM_${NAME}_LINK_INTO_TOOLS``, when sets to ``ON``, turns the project into
a statically linked extension


Registering dynamically loaded passes
=====================================

Expand Down
69 changes: 69 additions & 0 deletions llvm/examples/Bye/Bye.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Pass.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace llvm;

static cl::opt<bool> Wave("wave-goodbye", cl::init(false),
cl::desc("wave good bye"));

namespace {

bool runBye(Function &F) {
if (Wave) {
errs() << "Bye: ";
errs().write_escaped(F.getName()) << '\n';
}
return false;
}

struct LegacyBye : public FunctionPass {
static char ID;
LegacyBye() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override { return runBye(F); }
};

struct Bye : PassInfoMixin<Bye> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {
if (!runBye(F))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
};

} // namespace

char LegacyBye::ID = 0;

static RegisterPass<LegacyBye> X("goodbye", "Good Bye World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);

/* Legacy PM Registration */
static llvm::RegisterStandardPasses RegisterBye(
llvm::PassManagerBuilder::EP_EarlyAsPossible,
[](const llvm::PassManagerBuilder &Builder,
llvm::legacy::PassManagerBase &PM) { PM.add(new LegacyBye()); });

/* New PM Registration */
llvm::PassPluginLibraryInfo getByePluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "Bye", LLVM_VERSION_STRING,
[](PassBuilder &PB) {
PB.registerVectorizerStartEPCallback(
[](llvm::FunctionPassManager &PM,
llvm::PassBuilder::OptimizationLevel Level) {
PM.addPass(Bye());
});
}};
}

#ifndef LLVM_BYE_LINK_INTO_TOOLS
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getByePluginInfo();
}
#endif
13 changes: 13 additions & 0 deletions llvm/examples/Bye/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
add_llvm_pass_plugin(Bye Bye.cpp)
if (LLVM_LINK_LLVM_DYLIB)
target_link_libraries(Bye PUBLIC LLVM)
else()
target_link_libraries(Bye
PUBLIC
LLVMSupport
LLVMCore
LLVMipo
LLVMPasses
)
endif()

1 change: 1 addition & 0 deletions llvm/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_subdirectory(LLJITExamples)
add_subdirectory(Kaleidoscope)
add_subdirectory(ModuleMaker)
add_subdirectory(SpeculativeJIT)
add_subdirectory(Bye)

if(LLVM_ENABLE_EH AND (NOT WIN32) AND (NOT "${LLVM_NATIVE_ARCH}" STREQUAL "ARM"))
add_subdirectory(ExceptionDemo)
Expand Down
3 changes: 0 additions & 3 deletions llvm/include/llvm/Config/llvm-config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
/* Define if LLVM_ENABLE_DUMP is enabled */
#cmakedefine LLVM_ENABLE_DUMP

/* Define if we link Polly to the tools */
#cmakedefine LINK_POLLY_INTO_TOOLS

/* Target triple LLVM will generate code for by default */
#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}"

Expand Down
11 changes: 11 additions & 0 deletions llvm/test/Feature/load_extension.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
; RUN: opt %s -load=%llvmshlibdir/libBye%shlibext -goodbye -wave-goodbye \
; RUN: -disable-output 2>&1 | FileCheck %s
; REQUIRES: plugins
; CHECK: Bye

@junk = global i32 0

define i32* @somefunk() {
ret i32* @junk
}

Loading