From 78c929fb325927a103d239e8181abdb0524f9dca Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Fri, 17 Jul 2020 10:52:39 +0200 Subject: [PATCH] wip --- src/bin/eolian/sources.c | 72 +++++++++++++--- src/compiler-plugins/myplugin.cc | 139 +++++++++++++++++-------------- 2 files changed, 140 insertions(+), 71 deletions(-) diff --git a/src/bin/eolian/sources.c b/src/bin/eolian/sources.c index 0837777440..f4f5185476 100644 --- a/src/bin/eolian/sources.c +++ b/src/bin/eolian/sources.c @@ -504,7 +504,7 @@ _emit_class_function(Eina_Strbuf *buf, const Eolian_Function *fid, const char *r static void _gen_func(const Eolian_Class *cl, const Eolian_Function *fid, Eolian_Function_Type ftype, Eina_Strbuf *buf, - const Eolian_Implement *impl, Eina_Hash *refh) + const Eolian_Implement *impl, Eina_Hash *refh, Eina_Bool internal) { Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype); Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype); @@ -927,6 +927,51 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid, if (impl_same_class && eolian_function_is_static(fid)) _emit_class_function(buf, fid, rtpn, params_full, ocnamel, func_suffix, params, eolian_function_full_c_name_get(fid, ftype)); + if (internal && !eolian_function_is_static(fid) && !eolian_implement_is_pure_virtual(impl, ftype) && !is_empty) + { + /* T _class_name[_orig_class]_func_name_suffix */ + eina_strbuf_append(buf, "EAPI "); + eina_strbuf_append(buf, rtpn); + if (rtpn[strlen(rtpn) - 1] != '*') + eina_strbuf_append_char(buf, ' '); + eina_strbuf_append(buf, "_NEVA_USE_ME_internal_"); + eina_strbuf_append(buf, cnamel); + if (!impl_same_class) + eina_strbuf_append_printf(buf, "_%s", ocnamel); + eina_strbuf_append_char(buf, '_'); + eina_strbuf_append(buf, eolian_function_name_get(fid)); + eina_strbuf_append(buf, func_suffix); + /* ([const ]Eo *obj, Data_Type *pd, impl_full_params); */ + eina_strbuf_append_char(buf, '('); + if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid)) + eina_strbuf_append(buf, "const "); + eina_strbuf_append(buf, "Eo *obj, "); + eina_strbuf_append(buf, eolian_class_c_data_type_get(cl)); + eina_strbuf_append(buf, " *pd"); + eina_strbuf_append(buf, eina_strbuf_string_get(params_full_imp)); + if (eina_strbuf_length_get(params_full_imp) == 0 && eolian_function_is_static(fid)) + eina_strbuf_append(buf, "void"); + eina_strbuf_append(buf, ") {\n"); + if (rtp) + eina_strbuf_append(buf, " return "); + else + eina_strbuf_append(buf, " "); + eina_strbuf_append(buf, "_"); + eina_strbuf_append(buf, cnamel); + if (!impl_same_class) + eina_strbuf_append_printf(buf, "_%s", ocnamel); + eina_strbuf_append_char(buf, '_'); + eina_strbuf_append(buf, eolian_function_name_get(fid)); + eina_strbuf_append(buf, func_suffix); + eina_strbuf_append(buf, "(obj, pd"); + if (eina_strbuf_length_get(params) > 0) + eina_strbuf_append(buf, ", "); + eina_strbuf_append_buffer(buf, params); + /* params here */ + eina_strbuf_append(buf, ");\n"); + eina_strbuf_append(buf, "}\n\n"); + } + free(cname); free(cnamel); free(ocnamel); @@ -1137,10 +1182,8 @@ _is_function_type_compatible(const Eolian_Function_Type t1, const Eolian_Functio * */ static void -_gen_next_super_implementation_registering(Eina_Array *call_chain, const Eolian_Class *impl_klass, const Eolian_Implement *impl, Eina_Strbuf *buf) +_gen_next_super_implementation_registering(Eina_Array *call_chain, const Eolian_Class *impl_klass, const Eolian_Implement *impl, const Eolian_Function_Type ftype, const Eolian_Function *fid, Eina_Strbuf *buf) { - Eolian_Function_Type ftype; - const Eolian_Function *fid = eolian_implement_function_get(impl, &ftype); const Eolian_Class *next_implemen_class = NULL; const Eolian_Class *definition_class = eolian_function_class_get(fid); char *impl_name; @@ -1183,7 +1226,7 @@ _gen_next_super_implementation_registering(Eina_Array *call_chain, const Eolian_ prefix = "_set"; eina_strbuf_append_printf(buf, "COMPILER_PLUGIN_REGISTER_NEXT(\"%s\", \"%s\", ", eolian_function_full_c_name_get(fid, ftype), class_name); - eina_strbuf_append_printf(buf, "\"_%s", impl_name); + eina_strbuf_append_printf(buf, "\"_NEVA_USE_ME_internal_%s", impl_name); if (definition_class != next_implemen_class) eina_strbuf_append_printf(buf, "_%s", defi_name); eina_strbuf_append_printf(buf, "_%s%s\"", eolian_function_name_get(fid), prefix); @@ -1281,18 +1324,19 @@ eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf) { Eolian_Function_Type ftype = EOLIAN_UNRESOLVED; const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype); + Eina_Bool internal_redirection = EINA_TRUE; //eolian_function_class_get(fid) != cl; switch (ftype) { case EOLIAN_PROP_GET: case EOLIAN_PROP_SET: - _gen_func(cl, fid, ftype, buf, imp, refh); + _gen_func(cl, fid, ftype, buf, imp, refh, internal_redirection); break; case EOLIAN_PROPERTY: - _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp, refh); - _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp, refh); + _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp, refh, internal_redirection); + _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp, refh, internal_redirection); break; default: - _gen_func(cl, fid, EOLIAN_METHOD, buf, imp, refh); + _gen_func(cl, fid, EOLIAN_METHOD, buf, imp, refh, internal_redirection); } } eina_iterator_free(itr); @@ -1391,7 +1435,15 @@ eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf) if (eolian_function_is_static(fid)) continue; if (icl == cl) continue; - _gen_next_super_implementation_registering(call_chain, cl, imp, buf); + if (ftype == EOLIAN_PROPERTY) + { + _gen_next_super_implementation_registering(call_chain, cl, imp, EOLIAN_PROP_SET, fid, buf); + _gen_next_super_implementation_registering(call_chain, cl, imp, EOLIAN_PROP_GET, fid, buf); + } + else + { + _gen_next_super_implementation_registering(call_chain, cl, imp, ftype, fid, buf); + } } eina_iterator_free(itr); diff --git a/src/compiler-plugins/myplugin.cc b/src/compiler-plugins/myplugin.cc index 339b23e64a..b183432f6e 100644 --- a/src/compiler-plugins/myplugin.cc +++ b/src/compiler-plugins/myplugin.cc @@ -35,7 +35,6 @@ static void super2_add(gimple_stmt_iterator *gsi) 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); @@ -45,7 +44,7 @@ static void super2_add(gimple_stmt_iterator *gsi) 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, + cgraph_create_edge(cgraph_node::get(current_function_decl), node, super2_func, bb->count, frequency); } @@ -55,13 +54,16 @@ struct Caller { const char *klass; tree klass_decl; tree called_api_decl; + tree klass_call; + gimple efl_super_call; + gimple class_get_call; }; typedef struct _Fetch_Result { bool valid; const char *api_name; tree api; - const_gimple first_argument; + gimple first_argument; } Fetch_Result; static Fetch_Result @@ -105,6 +107,7 @@ static Caller fetch_efl_super_class(const_gimple stmt) if (!first.valid) return ret; ret.called_api = IDENTIFIER_POINTER(DECL_NAME(called_api_tree)); ret.called_api_decl = called_api_tree; + ret.efl_super_call = first.first_argument; if (!!strncmp(first.api_name, "efl_super", 9)) return ret; //copy the name we have inside efl_super @@ -112,16 +115,53 @@ static Caller fetch_efl_super_class(const_gimple stmt) if (!argument_efl_super.valid) return ret; ret.klass = argument_efl_super.api_name; ret.klass_decl = argument_efl_super.api; + ret.klass_call = gimple_call_arg(first.first_argument, 0); + ret.class_get_call = argument_efl_super.first_argument; ret.valid = true; return ret; } +struct Registered_Api{ + bool valid; + tree replacement_candidate; + tree provider_of_replacement_candidate; +}; + +static Registered_Api +fetch_replacement_api(tree klass_decl, const char* called_api) +{ + Registered_Api result = {false, 0, 0}; + for (tree attribute = DECL_ATTRIBUTES(klass_decl); attribute != NULL_TREE; attribute = TREE_CHAIN(attribute)) + { + tree attribute_name = TREE_PURPOSE(attribute); + if (!attribute_name) + { + fprintf(stderr, "Error, expected name\n"); + continue; + } + if (!!strncmp(IDENTIFIER_POINTER(attribute_name), "register_next", strlen("register_next"))) + continue; + //this here assumes a special tree_list structure + tree attribute_arguments = TREE_VALUE(attribute); + tree call = TREE_VALUE(attribute_arguments); + tree providing_class = TREE_VALUE(TREE_CHAIN(attribute_arguments)); + tree implementation = TREE_VALUE(TREE_CHAIN(TREE_CHAIN(attribute_arguments))); + if (!!strncmp(TREE_STRING_POINTER(call), called_api, strlen(called_api))) continue; + result.provider_of_replacement_candidate = providing_class; + result.replacement_candidate = implementation; + result.valid = true; + break; + } + return result; +} + static unsigned int eo_execute(void) { basic_block bb, entry_bb; gimple_stmt_iterator gsi; + unsigned int length = 0; //fprintf(stderr, "Function %s eval\n", get_name(cfun->decl)); @@ -131,47 +171,32 @@ static unsigned int eo_execute(void) gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); entry_bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); + for (tree argument = DECL_ARGUMENTS(cfun->decl); argument; argument = DECL_CHAIN(argument)) + { + length ++; + } + if (length < 2) return 0; //not considering functions that are invalid here + FOR_EACH_BB_FN(bb, cfun) { - const_gimple stmt; + gimple stmt; for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { stmt = gsi_stmt(gsi); + if (!stmt || !is_gimple_call(stmt)) continue; struct Caller c = fetch_efl_super_class(stmt); - tree replacement_candidate = NULL; - tree provider_of_replacement_candidate = NULL; if (!c.klass) continue; - for (tree attribute = DECL_ATTRIBUTES(c.klass_decl); attribute != NULL_TREE; attribute = TREE_CHAIN(attribute)) - { - tree attribute_name = TREE_PURPOSE(attribute); - if (!attribute_name) - { - fprintf(stderr, "Error, expected name\n"); - continue; - } - if (!!strncmp(IDENTIFIER_POINTER(attribute_name), "register_next", strlen("register_next"))) - continue; + Registered_Api api = fetch_replacement_api(c.klass_decl, c.called_api); - //this here assumes a special tree_list structure - tree attribute_arguments = TREE_VALUE(attribute); - tree call = TREE_VALUE(attribute_arguments); - tree providing_class = TREE_VALUE(TREE_CHAIN(attribute_arguments)); - tree implementation = TREE_VALUE(TREE_CHAIN(TREE_CHAIN(attribute_arguments))); + if (!api.valid) continue; - if (!!strncmp(TREE_STRING_POINTER(call), c.called_api, strlen(c.called_api))) continue; - - provider_of_replacement_candidate = providing_class; - replacement_candidate = implementation; - } - if (!replacement_candidate) continue; - fprintf(stderr, "Replace! %s %s\n", c.called_api, TREE_STRING_POINTER(replacement_candidate)); + fprintf(stderr, "Replace! %s %s\n", c.called_api, TREE_STRING_POINTER(api.replacement_candidate)); //Create a new call to the found replacement candidate - #if 1 //FIXME we need here: //add another argument "pd - _pd_offset + _pd_offset" (TODO check if these are mixins) @@ -183,14 +208,9 @@ static unsigned int eo_execute(void) argument_types.create(10); for (tree argument = DECL_ARGUMENTS(c.called_api_decl); argument; argument = TREE_CHAIN(argument), i++) { - if (!argument_types.space(i + 1)) - argument_types.safe_grow(i + 1); - if (i == 0) { - argument_types[i] = argument; - } else { - argument_types[i + 1] = argument; - } - fprintf(stderr, "COPY\n"); + argument_types.safe_push(argument); + if (i == 0) + argument_types.safe_push(void_type_node); } tree pd_type = void_type_node;//the pd argument is interpreted as void pointer here. @@ -198,49 +218,47 @@ static unsigned int eo_execute(void) tree result = DECL_RESULT(c.called_api_decl); if (!result) result = void_type_node; - fprintf(stderr, "----> %d\n", i); - tree implementation_function_types = build_function_type_array(result, i + 1, argument_types.address()); - tree implementation_function_declaration = build_fn_decl(TREE_STRING_POINTER(replacement_candidate), implementation_function_types); - + tree implementation_function_types = build_function_type_array(result, i + 1, &argument_types.address()[0]); + tree implementation_function_declaration = build_fn_decl(TREE_STRING_POINTER(api.replacement_candidate), implementation_function_types); /** * Create function call */ vec new_arguments; new_arguments.create(gimple_call_num_args(stmt) + 1); - new_arguments[0] = gimple_call_arg(stmt, 0); - tree pd_value = new_arguments[0]; //FIXME create calls to second argument of cfun pd + and - - new_arguments[1] = pd_value; + new_arguments.safe_push(DECL_ARGUMENTS(cfun->decl)); + + tree field1 = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier("efl_object_pd_offset"), integer_type_node); //FIXME wrong field + DECL_EXTERNAL(field1) = 1; + TREE_PUBLIC(field1) = 1; + tree field2 = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier("efl_loop_consumer_pd_offset"), integer_type_node); //FIXME wrong field + DECL_EXTERNAL(field2) = 1; + TREE_PUBLIC(field2) = 1; + tree tmp1 = build2(MINUS_EXPR, integer_type_node, DECL_CHAIN(DECL_ARGUMENTS(cfun->decl)), field1); + tree tmp2 = build2(PLUS_EXPR, integer_type_node, tmp1, field2); + new_arguments.safe_push(tmp2); for (unsigned int i = 1; i < gimple_call_num_args(stmt); ++i) { - new_arguments[i + 1] = gimple_call_arg(stmt, i); - fprintf(stderr, "COPY2\n"); + new_arguments.safe_push(gimple_call_arg(stmt, i)); } gcall *new_call = gimple_build_call_vec(implementation_function_declaration, new_arguments); + const greturn *ret = as_a (stmt); tree return_val = gimple_return_retval(ret); gimple_return_set_retval(as_a(new_call), return_val); + gsi_replace(&gsi, new_call, true); + + auto removal = gsi_for_stmt(c.efl_super_call); + gsi_remove(&removal, false); + removal = gsi_for_stmt(c.class_get_call); + gsi_remove(&removal, false); #endif } } 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; -} - static tree handle_user_attribute (tree *node, tree name, tree args, int flags, bool *no_add_attrs) @@ -287,7 +305,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, 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); register_callback (plugin_name, PLUGIN_ATTRIBUTES, register_next_hop_attribute, NULL); return 0;