From 9bcd901ae58054f4a13efc6bc6e198d56cbdba92 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Wed, 22 Jan 2020 14:18:23 +0100 Subject: [PATCH] ler-plugin: initial gcc plugin harness to be used in our build Ideas and some code from https://github.com/mesonbuild/meson/issues/5090 This is just an example plugin that cold be used as a starting point. Right now we find efl_super() with GIMPLE and add a efl_super2 call when it was defined and in code before to allow linking. --- meson.build | 9 ++- src/compiler-plugins/meson.build | 25 ++++++++ src/compiler-plugins/myplugin.cc | 104 +++++++++++++++++++++++++++++++ src/compiler-plugins/test-1.c | 11 ++++ src/lib/eo/Eo.h | 1 + src/lib/eo/eo.c | 4 ++ src/lib/eo/meson.build | 2 +- 7 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/compiler-plugins/meson.build create mode 100644 src/compiler-plugins/myplugin.cc create mode 100644 src/compiler-plugins/test-1.c diff --git a/meson.build b/meson.build index f820761ade..f0088b47d7 100644 --- a/meson.build +++ b/meson.build @@ -248,6 +248,11 @@ if get_option('tslib') == true config_h.set('HAVE_TSLIB', '1') endif +#if get_option('compiler-plugins') == true + #gcc_plugin = dependency('gcc-plugin') + subdir(join_paths('src', 'compiler-plugins')) +#endif + subdir('header_checks') subdir('po') @@ -313,7 +318,7 @@ subprojects = [ ['evil' ,[] , false, true, false, false, false, false, true, [], []], ['eina' ,[] , false, true, true, true, true, true, true, [], []], ['eolian' ,[] , false, true, true, false, true, false, false, ['eina'], []], -['eo' ,[] , false, true, false, true, true, false, true, ['eina'], []], +['eo' ,[] , false, true, false, true, true, false, true, ['eina', 'compiler_plugin'], []], ['efl' ,[] , false, true, false, false, true, false, true, ['eo'], []], ['emile' ,[] , false, true, false, false, true, true, true, ['eina', 'efl'], ['lz4', 'rg_etc']], ['eet' ,[] , false, true, true, false, true, true, true, ['eina', 'emile', 'efl'], []], @@ -420,6 +425,8 @@ foreach package : subprojects '-DNEED_RUN_IN_TREE=1', '-DEFL_BUILD=1', ] +# '-fdump-passes', +#'-fdump-tree-gimple', if (package[3]) subdir(join_paths(local_lib, package_name)) set_variable(package_name + '_eo_files', pub_eo_files) diff --git a/src/compiler-plugins/meson.build b/src/compiler-plugins/meson.build new file mode 100644 index 0000000000..8151e0e50e --- /dev/null +++ b/src/compiler-plugins/meson.build @@ -0,0 +1,25 @@ +cc = meson.get_compiler('c') +plugin_dev_path_result = run_command(cc.cmd_array(), '-print-file-name=plugin') +plugin_dev_path = plugin_dev_path_result.stdout().strip() +plugin_inc = include_directories([join_paths(plugin_dev_path, 'include')]) + +myplugin = shared_module('myplugin', + 'myplugin.cc', + cpp_args: [ '-fno-rtti' ], + include_directories: plugin_inc +) + +myplugin_dep = custom_target('myplugin', + input: myplugin, + output: 'myplugin_dep.h', + command: ['echo'], + capture: true +) + +compiler_plugin = declare_dependency() + +test_1 = executable('test-1', 'test-1.c', myplugin_dep, + c_args: [ '-fdump-passes', '-fplugin=' + myplugin.full_path() ], + native: true, +) +test('test_1', test_1) diff --git a/src/compiler-plugins/myplugin.cc b/src/compiler-plugins/myplugin.cc new file mode 100644 index 0000000000..6e67652930 --- /dev/null +++ b/src/compiler-plugins/myplugin.cc @@ -0,0 +1,104 @@ +#include +#include "gcc-common.h" + +/* TODO: + * Find all efl_super calls + * Traverse back to find function calling it (foo) + * Calculate the private data pointer diff + * Replace foo(efl_super(obj, MY_CLASS),...) calls with the next lower level function for foo and + * adjust private data with diff + * Make eolian more expressive (We need the implemented methods of classes, accross the tree) + */ + +__visible int plugin_is_GPL_compatible; + +static const char super2_function[] = "efl_super2"; +static GTY(()) tree super2_function_decl; + +static void super2_add(gimple_stmt_iterator *gsi) +{ + gimple stmt; + gcall *super2_func; + cgraph_node_ptr node; + int frequency; + basic_block bb; + + stmt = gimple_build_call(super2_function_decl, 0); + super2_func = as_a_gcall(stmt); + gsi_insert_after(gsi, super2_func, GSI_CONTINUE_LINKING); + + /* Update the cgraph */ + bb = gimple_bb(super2_func); + node = cgraph_get_create_node(super2_function_decl); + gcc_assert(node); + frequency = compute_call_stmt_bb_frequency(current_function_decl, bb); + cgraph_create_edge(cgraph_get_node(current_function_decl), node, + super2_func, bb->count, frequency); +} + +static unsigned int eo_execute(void) +{ + basic_block bb, entry_bb; + gimple_stmt_iterator gsi; + + //fprintf(stderr, "Function %s called\n", get_name(cfun->decl)); + + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + entry_bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); + + FOR_EACH_BB_FN(bb, cfun) { + const_gimple stmt; + for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + { + stmt = gsi_stmt(gsi); + if (is_gimple_call(stmt)){ + tree current_fn_decl = gimple_call_fndecl(stmt); + if (!current_fn_decl) + continue; + const char* name = IDENTIFIER_POINTER(DECL_NAME(current_fn_decl)); + if (!strncmp(name, "efl_super", 9)) { + fprintf(stderr, "Found function %s\n", name); + super2_add(&gsi); + } + } + } + } + return 0; +} + +static void super2_start_unit(void *gcc_data __unused, + void *user_data __unused) +{ + /* void efl_super2(void) */ + tree fntype = build_function_type_list(void_type_node, NULL_TREE); + super2_function_decl = build_fn_decl(super2_function, fntype); + DECL_ASSEMBLER_NAME(super2_function_decl); /* for LTO */ + TREE_PUBLIC(super2_function_decl) = 1; + TREE_USED(super2_function_decl) = 1; + DECL_EXTERNAL(super2_function_decl) = 1; + DECL_ARTIFICIAL(super2_function_decl) = 1; + DECL_PRESERVE_P(super2_function_decl) = 1; +} + +#define PASS_NAME eo +#define NO_GATE +#include "gcc-generate-gimple-pass.h" + +__visible int plugin_init(struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + const char *plugin_name = plugin_info->base_name; + + if (!plugin_default_version_check (version, &gcc_version)) + return 1; + + PASS_INFO(eo, "cfg", 1, PASS_POS_INSERT_AFTER); + + /* Register to be called before processing a translation unit */ + register_callback(plugin_name, PLUGIN_START_UNIT, + &super2_start_unit, NULL); + + register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &eo_pass_info); + + return 0; +} diff --git a/src/compiler-plugins/test-1.c b/src/compiler-plugins/test-1.c new file mode 100644 index 0000000000..a23f7c9c3a --- /dev/null +++ b/src/compiler-plugins/test-1.c @@ -0,0 +1,11 @@ +#include +void efl_super2(void){} + +int efl_super(void) { +} + +int main(void) +{ + efl_super(); + return 0; +} diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 0ebbd53e9c..12a29d0555 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -1458,6 +1458,7 @@ EAPI Eo * _efl_add_end(Eo *obj, Eina_Bool is_ref, Eina_Bool is_fallback); * @see efl_cast */ EAPI Eo *efl_super(const Eo *obj, const Efl_Class *cur_klass); +EAPI void efl_super2(void); /** * @brief Prepare a call to cast to a parent class implementation of a function. diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index f5d880918f..7f21e0c0f3 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -529,6 +529,10 @@ efl_super(const Eo *eo_id, const Efl_Class *cur_klass) { return _efl_super_cast(eo_id, cur_klass, EINA_TRUE); } +EAPI void +efl_super2(void) +{ +} EAPI Eo * efl_cast(const Eo *eo_id, const Efl_Class *cur_klass) diff --git a/src/lib/eo/meson.build b/src/lib/eo/meson.build index 9cd33775b0..85434b5079 100644 --- a/src/lib/eo/meson.build +++ b/src/lib/eo/meson.build @@ -1,4 +1,4 @@ -eo_deps = [] +eo_deps = [compiler_plugin] eo_pub_deps = [eina] eo_ext_deps = [valgrind, dl, execinfo]