This commit is contained in:
Marcel Hollerbach 2020-07-17 10:52:39 +02:00
parent e14bac5270
commit 78c929fb32
2 changed files with 140 additions and 71 deletions

View File

@ -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);

View File

@ -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 - <my_class>_pd_offset + <providing_class>_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<tree> 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 <const greturn *> (stmt);
tree return_val = gimple_return_retval(ret);
gimple_return_set_retval(as_a<greturn *>(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;