Commit 6b90bd4b authored by Emese Revfy's avatar Emese Revfy Committed by Michal Marek

GCC plugin infrastructure

This patch allows to build the whole kernel with GCC plugins. It was ported from
grsecurity/PaX. The infrastructure supports building out-of-tree modules and
building in a separate directory. Cross-compilation is supported too.
Currently the x86, arm, arm64 and uml architectures enable plugins.

The directory of the gcc plugins is scripts/gcc-plugins. You can use a file or a directory
there. The plugins compile with these options:
 * -fno-rtti: gcc is compiled with this option so the plugins must use it too
 * -fno-exceptions: this is inherited from gcc too
 * -fasynchronous-unwind-tables: this is inherited from gcc too
 * -ggdb: it is useful for debugging a plugin (better backtrace on internal
    errors)
 * -Wno-narrowing: to suppress warnings from gcc headers (ipa-utils.h)
 * -Wno-unused-variable: to suppress warnings from gcc headers (gcc_version
    variable, plugin-version.h)

The infrastructure introduces a new Makefile target called gcc-plugins. It
supports all gcc versions from 4.5 to 6.0. The scripts/gcc-plugin.sh script
chooses the proper host compiler (gcc-4.7 can be built by either gcc or g++).
This script also checks the availability of the included headers in
scripts/gcc-plugins/gcc-common.h.

The gcc-common.h header contains frequently included headers for GCC plugins
and it has a compatibility layer for the supported gcc versions.

The gcc-generate-*-pass.h headers automatically generate the registration
structures for GIMPLE, SIMPLE_IPA, IPA and RTL passes.

Note that 'make clean' keeps the *.so files (only the distclean or mrproper
targets clean all) because they are needed for out-of-tree modules.

Based on work created by the PaX Team.
Signed-off-by: 's avatarEmese Revfy <re.emese@gmail.com>
Acked-by: 's avatarKees Cook <keescook@chromium.org>
Signed-off-by: 's avatarMichal Marek <mmarek@suse.com>
parent 24403874
......@@ -37,6 +37,7 @@ modules.builtin
Module.symvers
*.dwo
*.su
*.c.[012]*.*
#
# Top-level generic files
......
......@@ -3,6 +3,7 @@
*.bc
*.bin
*.bz2
*.c.[012]*.*
*.cis
*.cpio
*.csp
......
GCC plugin infrastructure
=========================
1. Introduction
===============
GCC plugins are loadable modules that provide extra features to the
compiler [1]. They are useful for runtime instrumentation and static analysis.
We can analyse, change and add further code during compilation via
callbacks [2], GIMPLE [3], IPA [4] and RTL passes [5].
The GCC plugin infrastructure of the kernel supports all gcc versions from
4.5 to 6.0, building out-of-tree modules, cross-compilation and building in a
separate directory.
Plugin source files have to be compilable by both a C and a C++ compiler as well
because gcc versions 4.5 and 4.6 are compiled by a C compiler,
gcc-4.7 can be compiled by a C or a C++ compiler,
and versions 4.8+ can only be compiled by a C++ compiler.
Currently the GCC plugin infrastructure supports only the x86, arm and arm64
architectures.
This infrastructure was ported from grsecurity [6] and PaX [7].
--
[1] https://gcc.gnu.org/onlinedocs/gccint/Plugins.html
[2] https://gcc.gnu.org/onlinedocs/gccint/Plugin-API.html#Plugin-API
[3] https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html
[4] https://gcc.gnu.org/onlinedocs/gccint/IPA.html
[5] https://gcc.gnu.org/onlinedocs/gccint/RTL.html
[6] https://grsecurity.net/
[7] https://pax.grsecurity.net/
2. Files
========
$(src)/scripts/gcc-plugins
This is the directory of the GCC plugins.
$(src)/scripts/gcc-plugins/gcc-common.h
This is a compatibility header for GCC plugins.
It should be always included instead of individual gcc headers.
$(src)/scripts/gcc-plugin.sh
This script checks the availability of the included headers in
gcc-common.h and chooses the proper host compiler to build the plugins
(gcc-4.7 can be built by either gcc or g++).
$(src)/scripts/gcc-plugins/gcc-generate-gimple-pass.h
$(src)/scripts/gcc-plugins/gcc-generate-ipa-pass.h
$(src)/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
$(src)/scripts/gcc-plugins/gcc-generate-rtl-pass.h
These headers automatically generate the registration structures for
GIMPLE, SIMPLE_IPA, IPA and RTL passes. They support all gcc versions
from 4.5 to 6.0.
They should be preferred to creating the structures by hand.
3. Usage
========
You must install the gcc plugin headers for your gcc version,
e.g., on Ubuntu for gcc-4.9:
apt-get install gcc-4.9-plugin-dev
Enable a GCC plugin based feature in the kernel config:
CONFIG_GCC_PLUGIN_CYC_COMPLEXITY = y
To compile only the plugin(s):
make gcc-plugins
or just run the kernel make and compile the whole kernel with
the cyclomatic complexity GCC plugin.
4. How to add a new GCC plugin
==============================
The GCC plugins are in $(src)/scripts/gcc-plugins/. You can use a file or a directory
here. It must be added to $(src)/scripts/gcc-plugins/Makefile,
$(src)/scripts/Makefile.gcc-plugins and $(src)/arch/Kconfig.
See the cyc_complexity_plugin.c (CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) GCC plugin.
......@@ -4979,6 +4979,15 @@ L: linux-scsi@vger.kernel.org
S: Odd Fixes (e.g., new signatures)
F: drivers/scsi/fdomain.*
GCC PLUGINS
M: Kees Cook <keescook@chromium.org>
R: Emese Revfy <re.emese@gmail.com>
L: kernel-hardening@lists.openwall.com
S: Maintained
F: scripts/gcc-plugins/
F: scripts/gcc-plugin.sh
F: Documentation/gcc-plugins.txt
GCOV BASED KERNEL PROFILING
M: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
S: Maintained
......
......@@ -552,7 +552,7 @@ ifeq ($(KBUILD_EXTMOD),)
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
asm-generic
asm-generic gcc-plugins
$(Q)$(MAKE) $(build)=$(@)
# Objects we will link into vmlinux / subdirs we need to visit
......@@ -631,6 +631,15 @@ endif
# Tell gcc to never replace conditional load with a non-conditional one
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
PHONY += gcc-plugins
gcc-plugins: scripts_basic
ifdef CONFIG_GCC_PLUGINS
$(Q)$(MAKE) $(build)=scripts/gcc-plugins
endif
@:
include scripts/Makefile.gcc-plugins
ifdef CONFIG_READABLE_ASM
# Disable optimizations that make assembler listings hard to read.
# reorder blocks reorders the control in the function
......@@ -1026,7 +1035,7 @@ prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
archprepare: archheaders archscripts prepare1 scripts_basic
prepare0: archprepare
prepare0: archprepare gcc-plugins
$(Q)$(MAKE) $(build)=.
# All the preparing..
......@@ -1507,6 +1516,7 @@ clean: $(clean-dirs)
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-o -name '*.symtypes' -o -name 'modules.order' \
-o -name modules.builtin -o -name '.tmp_*.o.*' \
-o -name '*.c.[012]*.*' \
-o -name '*.gcno' \) -type f -print | xargs rm -f
# Generate tags for editors
......
......@@ -357,6 +357,21 @@ config SECCOMP_FILTER
See Documentation/prctl/seccomp_filter.txt for details.
config HAVE_GCC_PLUGINS
bool
help
An arch should select this symbol if it supports building with
GCC plugins.
menuconfig GCC_PLUGINS
bool "GCC plugins"
depends on HAVE_GCC_PLUGINS
help
GCC plugins are loadable modules that provide extra features to the
compiler. They are useful for runtime instrumentation and static analysis.
See Documentation/gcc-plugins.txt for details.
config HAVE_CC_STACKPROTECTOR
bool
help
......
......@@ -54,6 +54,7 @@ config ARM
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
select HAVE_IDE if PCI || ISA || PCMCIA
......
......@@ -76,6 +76,7 @@ config ARM64
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
......
......@@ -9,6 +9,7 @@ config UML
select GENERIC_CPU_DEVICES
select GENERIC_IO
select GENERIC_CLOCKEVENTS
select HAVE_GCC_PLUGINS
select TTY # Needed for line.c
config MMU
......
......@@ -111,6 +111,7 @@ config X86
select HAVE_FUNCTION_GRAPH_FP_TEST
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT if X86_32
select HAVE_HW_BREAKPOINT
select HAVE_IDE
......
......@@ -75,7 +75,7 @@ CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
-fno-omit-frame-pointer -foptimize-sibling-calls \
-DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
$(vobjs): KBUILD_CFLAGS += $(CFL)
$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
#
# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
......@@ -145,6 +145,7 @@ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 := $(filter-out -mfentry,$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic
KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
......
......@@ -47,4 +47,4 @@ subdir-$(CONFIG_DTC) += dtc
subdir-$(CONFIG_GDB_SCRIPTS) += gdb
# Let clean descend into subdirs
subdir- += basic kconfig package
subdir- += basic kconfig package gcc-plugins
ifdef CONFIG_GCC_PLUGINS
__PLUGINCC := $(call cc-ifversion, -ge, 0408, $(HOSTCXX), $(HOSTCC))
PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
GCC_PLUGINS_CFLAGS := $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y))
export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN
ifeq ($(PLUGINCC),)
ifneq ($(GCC_PLUGINS_CFLAGS),)
ifeq ($(call cc-ifversion, -ge, 0405, y), y)
PLUGINCC := $(shell $(CONFIG_SHELL) -x $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
$(warning warning: your gcc installation does not support plugins, perhaps the necessary headers are missing?)
else
$(warning warning: your gcc version does not support plugins, you should upgrade it to gcc 4.5 at least)
endif
endif
endif
KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
GCC_PLUGIN := $(gcc-plugin-y)
endif
#!/bin/sh
srctree=$(dirname "$0")
gccplugins_dir=$($3 -print-file-name=plugin)
plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
#include "gcc-common.h"
#if BUILDING_GCC_VERSION >= 4008 || defined(ENABLE_BUILD_WITH_CXX)
#warning $2 CXX
#else
#warning $1 CC
#endif
EOF
)
if [ $? -ne 0 ]
then
exit 1
fi
case "$plugincc" in
*"$1 CC"*)
echo "$1"
exit 0
;;
*"$2 CXX"*)
# the c++ compiler needs another test, see below
;;
*)
exit 1
;;
esac
# we need a c++ compiler that supports the designated initializer GNU extension
plugincc=$($2 -c -x c++ -std=gnu++98 - -fsyntax-only -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
#include "gcc-common.h"
class test {
public:
int test;
} test = {
.test = 1
};
EOF
)
if [ $? -eq 0 ]
then
echo "$2"
exit 0
fi
exit 1
GCC_PLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
ifeq ($(PLUGINCC),$(HOSTCC))
HOSTLIBS := hostlibs
HOST_EXTRACFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu99 -ggdb
export HOST_EXTRACFLAGS
else
HOSTLIBS := hostcxxlibs
HOST_EXTRACXXFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti
HOST_EXTRACXXFLAGS += -fno-exceptions -fasynchronous-unwind-tables -ggdb
HOST_EXTRACXXFLAGS += -Wno-narrowing -Wno-unused-variable
export HOST_EXTRACXXFLAGS
endif
export GCCPLUGINS_DIR HOSTLIBS
$(HOSTLIBS)-y := $(GCC_PLUGIN)
always := $($(HOSTLIBS)-y)
clean-files += *.so
This diff is collapsed.
/*
* Generator for GIMPLE pass related boilerplate code/data
*
* Supports gcc 4.5-6
*
* Usage:
*
* 1. before inclusion define PASS_NAME
* 2. before inclusion define NO_* for unimplemented callbacks
* NO_GATE
* NO_EXECUTE
* 3. before inclusion define PROPERTIES_* and TODO_FLAGS_* to override
* the default 0 values
* 4. for convenience, all the above will be undefined after inclusion!
* 5. the only exported name is make_PASS_NAME_pass() to register with gcc
*/
#ifndef PASS_NAME
#error at least PASS_NAME must be defined
#else
#define __GCC_PLUGIN_STRINGIFY(n) #n
#define _GCC_PLUGIN_STRINGIFY(n) __GCC_PLUGIN_STRINGIFY(n)
#define _GCC_PLUGIN_CONCAT2(x, y) x ## y
#define _GCC_PLUGIN_CONCAT3(x, y, z) x ## y ## z
#define __PASS_NAME_PASS_DATA(n) _GCC_PLUGIN_CONCAT2(n, _pass_data)
#define _PASS_NAME_PASS_DATA __PASS_NAME_PASS_DATA(PASS_NAME)
#define __PASS_NAME_PASS(n) _GCC_PLUGIN_CONCAT2(n, _pass)
#define _PASS_NAME_PASS __PASS_NAME_PASS(PASS_NAME)
#define _PASS_NAME_NAME _GCC_PLUGIN_STRINGIFY(PASS_NAME)
#define __MAKE_PASS_NAME_PASS(n) _GCC_PLUGIN_CONCAT3(make_, n, _pass)
#define _MAKE_PASS_NAME_PASS __MAKE_PASS_NAME_PASS(PASS_NAME)
#ifdef NO_GATE
#define _GATE NULL
#define _HAS_GATE false
#else
#define __GATE(n) _GCC_PLUGIN_CONCAT2(n, _gate)
#define _GATE __GATE(PASS_NAME)
#define _HAS_GATE true
#endif
#ifdef NO_EXECUTE
#define _EXECUTE NULL
#define _HAS_EXECUTE false
#else
#define __EXECUTE(n) _GCC_PLUGIN_CONCAT2(n, _execute)
#define _EXECUTE __EXECUTE(PASS_NAME)
#define _HAS_EXECUTE true
#endif
#ifndef PROPERTIES_REQUIRED
#define PROPERTIES_REQUIRED 0
#endif
#ifndef PROPERTIES_PROVIDED
#define PROPERTIES_PROVIDED 0
#endif
#ifndef PROPERTIES_DESTROYED
#define PROPERTIES_DESTROYED 0
#endif
#ifndef TODO_FLAGS_START
#define TODO_FLAGS_START 0
#endif
#ifndef TODO_FLAGS_FINISH
#define TODO_FLAGS_FINISH 0
#endif
#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
#else
static struct gimple_opt_pass _PASS_NAME_PASS = {
.pass = {
#endif
.type = GIMPLE_PASS,
.name = _PASS_NAME_NAME,
#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
.has_execute = _HAS_EXECUTE,
#else
.gate = _GATE,
.execute = _EXECUTE,
.sub = NULL,
.next = NULL,
.static_pass_number = 0,
#endif
.tv_id = TV_NONE,
.properties_required = PROPERTIES_REQUIRED,
.properties_provided = PROPERTIES_PROVIDED,
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
#if BUILDING_GCC_VERSION < 4009
}
#endif
};
#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public gimple_opt_pass {
public:
_PASS_NAME_PASS() : gimple_opt_pass(_PASS_NAME_PASS_DATA, g) {}
#ifndef NO_GATE
#if BUILDING_GCC_VERSION >= 5000
virtual bool gate(function *) { return _GATE(); }
#else
virtual bool gate(void) { return _GATE(); }
#endif
#endif
virtual opt_pass * clone () { return new _PASS_NAME_PASS(); }
#ifndef NO_EXECUTE
#if BUILDING_GCC_VERSION >= 5000
virtual unsigned int execute(function *) { return _EXECUTE(); }
#else
virtual unsigned int execute(void) { return _EXECUTE(); }
#endif
#endif
};
}
opt_pass *_MAKE_PASS_NAME_PASS(void)
{
return new _PASS_NAME_PASS();
}
#else
struct opt_pass *_MAKE_PASS_NAME_PASS(void)
{
return &_PASS_NAME_PASS.pass;
}
#endif
/* clean up user provided defines */
#undef PASS_NAME
#undef NO_GATE
#undef NO_EXECUTE
#undef PROPERTIES_DESTROYED
#undef PROPERTIES_PROVIDED
#undef PROPERTIES_REQUIRED
#undef TODO_FLAGS_FINISH
#undef TODO_FLAGS_START
/* clean up generated defines */
#undef _EXECUTE
#undef __EXECUTE
#undef _GATE
#undef __GATE
#undef _GCC_PLUGIN_CONCAT2
#undef _GCC_PLUGIN_CONCAT3
#undef _GCC_PLUGIN_STRINGIFY
#undef __GCC_PLUGIN_STRINGIFY
#undef _HAS_EXECUTE
#undef _HAS_GATE
#undef _MAKE_PASS_NAME_PASS
#undef __MAKE_PASS_NAME_PASS
#undef _PASS_NAME_NAME
#undef _PASS_NAME_PASS
#undef __PASS_NAME_PASS
#undef _PASS_NAME_PASS_DATA
#undef __PASS_NAME_PASS_DATA
#endif /* PASS_NAME */
/*
* Generator for IPA pass related boilerplate code/data
*
* Supports gcc 4.5-6
*
* Usage:
*
* 1. before inclusion define PASS_NAME
* 2. before inclusion define NO_* for unimplemented callbacks
* NO_GENERATE_SUMMARY
* NO_READ_SUMMARY
* NO_WRITE_SUMMARY
* NO_READ_OPTIMIZATION_SUMMARY
* NO_WRITE_OPTIMIZATION_SUMMARY
* NO_STMT_FIXUP
* NO_FUNCTION_TRANSFORM
* NO_VARIABLE_TRANSFORM
* NO_GATE
* NO_EXECUTE
* 3. before inclusion define PROPERTIES_* and *TODO_FLAGS_* to override
* the default 0 values
* 4. for convenience, all the above will be undefined after inclusion!
* 5. the only exported name is make_PASS_NAME_pass() to register with gcc
*/
#ifndef PASS_NAME
#error at least PASS_NAME must be defined
#else
#define __GCC_PLUGIN_STRINGIFY(n) #n
#define _GCC_PLUGIN_STRINGIFY(n) __GCC_PLUGIN_STRINGIFY(n)
#define _GCC_PLUGIN_CONCAT2(x, y) x ## y
#define _GCC_PLUGIN_CONCAT3(x, y, z) x ## y ## z
#define __PASS_NAME_PASS_DATA(n) _GCC_PLUGIN_CONCAT2(n, _pass_data)
#define _PASS_NAME_PASS_DATA __PASS_NAME_PASS_DATA(PASS_NAME)
#define __PASS_NAME_PASS(n) _GCC_PLUGIN_CONCAT2(n, _pass)
#define _PASS_NAME_PASS __PASS_NAME_PASS(PASS_NAME)
#define _PASS_NAME_NAME _GCC_PLUGIN_STRINGIFY(PASS_NAME)
#define __MAKE_PASS_NAME_PASS(n) _GCC_PLUGIN_CONCAT3(make_, n, _pass)
#define _MAKE_PASS_NAME_PASS __MAKE_PASS_NAME_PASS(PASS_NAME)
#ifdef NO_GENERATE_SUMMARY
#define _GENERATE_SUMMARY NULL
#else
#define __GENERATE_SUMMARY(n) _GCC_PLUGIN_CONCAT2(n, _generate_summary)
#define _GENERATE_SUMMARY __GENERATE_SUMMARY(PASS_NAME)
#endif
#ifdef NO_READ_SUMMARY
#define _READ_SUMMARY NULL
#else
#define __READ_SUMMARY(n) _GCC_PLUGIN_CONCAT2(n, _read_summary)
#define _READ_SUMMARY __READ_SUMMARY(PASS_NAME)
#endif
#ifdef NO_WRITE_SUMMARY
#define _WRITE_SUMMARY NULL
#else
#define __WRITE_SUMMARY(n) _GCC_PLUGIN_CONCAT2(n, _write_summary)
#define _WRITE_SUMMARY __WRITE_SUMMARY(PASS_NAME)
#endif
#ifdef NO_READ_OPTIMIZATION_SUMMARY
#define _READ_OPTIMIZATION_SUMMARY NULL
#else
#define __READ_OPTIMIZATION_SUMMARY(n) _GCC_PLUGIN_CONCAT2(n, _read_optimization_summary)
#define _READ_OPTIMIZATION_SUMMARY __READ_OPTIMIZATION_SUMMARY(PASS_NAME)
#endif
#ifdef NO_WRITE_OPTIMIZATION_SUMMARY
#define _WRITE_OPTIMIZATION_SUMMARY NULL
#else
#define __WRITE_OPTIMIZATION_SUMMARY(n) _GCC_PLUGIN_CONCAT2(n, _write_optimization_summary)
#define _WRITE_OPTIMIZATION_SUMMARY __WRITE_OPTIMIZATION_SUMMARY(PASS_NAME)
#endif
#ifdef NO_STMT_FIXUP
#define _STMT_FIXUP NULL
#else
#define __STMT_FIXUP(n) _GCC_PLUGIN_CONCAT2(n, _stmt_fixup)
#define _STMT_FIXUP __STMT_FIXUP(PASS_NAME)
#endif
#ifdef NO_FUNCTION_TRANSFORM
#define _FUNCTION_TRANSFORM NULL
#else
#define __FUNCTION_TRANSFORM(n) _GCC_PLUGIN_CONCAT2(n, _function_transform)
#define _FUNCTION_TRANSFORM __FUNCTION_TRANSFORM(PASS_NAME)
#endif
#ifdef NO_VARIABLE_TRANSFORM
#define _VARIABLE_TRANSFORM NULL
#else
#define __VARIABLE_TRANSFORM(n) _GCC_PLUGIN_CONCAT2(n, _variable_transform)
#define _VARIABLE_TRANSFORM __VARIABLE_TRANSFORM(PASS_NAME)
#endif
#ifdef NO_GATE
#define _GATE NULL
#define _HAS_GATE false
#else
#define __GATE(n) _GCC_PLUGIN_CONCAT2(n, _gate)
#define _GATE __GATE(PASS_NAME)
#define _HAS_GATE true
#endif
#ifdef NO_EXECUTE
#define _EXECUTE NULL
#define _HAS_EXECUTE false
#else
#define __EXECUTE(n) _GCC_PLUGIN_CONCAT2(n, _execute)
#define _EXECUTE __EXECUTE(PASS_NAME)
#define _HAS_EXECUTE true
#endif
#ifndef PROPERTIES_REQUIRED
#define PROPERTIES_REQUIRED 0
#endif
#ifndef PROPERTIES_PROVIDED
#define PROPERTIES_PROVIDED 0
#endif
#ifndef PROPERTIES_DESTROYED
#define PROPERTIES_DESTROYED 0
#endif
#ifndef TODO_FLAGS_START
#define TODO_FLAGS_START 0
#endif
#ifndef TODO_FLAGS_FINISH
#define TODO_FLAGS_FINISH 0
#endif
#ifndef FUNCTION_TRANSFORM_TODO_FLAGS_START
#define FUNCTION_TRANSFORM_TODO_FLAGS_START 0
#endif
#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
#else
static struct ipa_opt_pass_d _PASS_NAME_PASS = {
.pass = {
#endif
.type = IPA_PASS,
.name = _PASS_NAME_NAME,
#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
.has_execute = _HAS_EXECUTE,
#else
.gate = _GATE,
.execute = _EXECUTE,
.sub = NULL,
.next = NULL,
.static_pass_number = 0,
#endif
.tv_id = TV_NONE,
.properties_required = PROPERTIES_REQUIRED,
.properties_provided = PROPERTIES_PROVIDED,
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
#if BUILDING_GCC_VERSION < 4009
},
.generate_summary = _GENERATE_SUMMARY,
.write_summary = _WRITE_SUMMARY,
.read_summary = _READ_SUMMARY,
#if BUILDING_GCC_VERSION >= 4006
.write_optimization_summary = _WRITE_OPTIMIZATION_SUMMARY,
.read_optimization_summary = _READ_OPTIMIZATION_SUMMARY,
#endif
.stmt_fixup = _STMT_FIXUP,
.function_transform_todo_flags_start = FUNCTION_TRANSFORM_TODO_FLAGS_START,
.function_transform = _FUNCTION_TRANSFORM,
.variable_transform = _VARIABLE_TRANSFORM,
#endif
};
#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public ipa_opt_pass_d {
public:
_PASS_NAME_PASS() : ipa_opt_pass_d(_PASS_NAME_PASS_DATA,
g,
_GENERATE_SUMMARY,
_WRITE_SUMMARY,
_READ_SUMMARY,
_WRITE_OPTIMIZATION_SUMMARY,
_READ_OPTIMIZATION_SUMMARY,
_STMT_FIXUP,
FUNCTION_TRANSFORM_TODO_FLAGS_START,
_FUNCTION_TRANSFORM,
_VARIABLE_TRANSFORM) {}
#ifndef NO_GATE
#if BUILDING_GCC_VERSION >= 5000
virtual bool gate(function *) { return _GATE(); }
#else
virtual bool gate(void) { return _GATE(); }
#endif
#endif
virtual opt_pass *clone() { return new _PASS_NAME_PASS(); }
#ifndef NO_EXECUTE
#if BUILDING_GCC_VERSION >= 5000
virtual unsigned int execute(function *) { return _EXECUTE(); }
#else
virtual unsigned int execute(void) { return _EXECUTE(); }
#endif
#endif
};
}
opt_pass *_MAKE_PASS_NAME_PASS(void)