Updated for openjdk-19-internal
[panamaz] / src / export.cc
index 17d4dad..4a34c58 100644 (file)
    https://blog.adacore.com/bindings-gcc-plugins
  */
 
+/*
+  TODO: get header name from tree
+ */
+
 /*
 
 function declarations, i think
@@ -46,6 +50,7 @@ FUNCTION_DECL     DECL_ARGUENTS    TREE_TYPE(item):PARM_DECL   DECL_NAME(item)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <gcc-plugin.h>
 #include <tree.h>
@@ -68,6 +73,8 @@ extern const char *tree_codes[];
 int plugin_is_GPL_compatible; // must be defined for the plugin to run
 
 static FILE *output_file;
+static int output_enabled = 1;
+
 static int debug_level = 0;
 
 static void debug_tree_helper(tree t, const char *msg) {
@@ -89,6 +96,17 @@ static struct list parameters;       // last list of params
 
 static struct hash forward_types;
 
+static int generate(const char *fmt, ...) {
+       int res = 0;
+       if (output_enabled) {
+               va_list ap;
+               va_start(ap, fmt);
+               res = vfprintf(output_file, fmt, ap);
+               va_end(ap);
+       }
+       return res;
+}
+
 /*
   Join all names in the stack, in reverse order.
 */
@@ -127,8 +145,10 @@ static bool is_struct_or_union(const_tree type) {
 }
 
 static void print_spaces(int n) {
-       for (int i = 0; i < n; ++i)
-               fputc('\t', output_file);
+       if (output_enabled) {
+               for (int i = 0; i < n; ++i)
+                       fputc('\t', output_file);
+       }
 }
 
 static int is_ref_type(tree type) {
@@ -409,7 +429,7 @@ static void export_param(tree field, tree field_type, size_t field_size) {
 
                buffer_init(&b, 256);
                export_desc(field, field_type, &b);
-               fprintf(output_file, " deref => '%s',", b.data);
+               generate(" deref => '%s',", b.data);
                free(b.data);
 
                field_type = simple_type(field_type);
@@ -419,17 +439,17 @@ static void export_param(tree field, tree field_type, size_t field_size) {
                break;
        }
        case VOID_TYPE:
-               fprintf(output_file, " type => 'void',");
-               fprintf(output_file, " ctype => 'void',");
+               generate(" type => 'void',");
+               generate(" ctype => 'void',");
                break;
        case ENUMERAL_TYPE: {
 #if defined(TYPED_ENUMS)
                const char *names = TYPE_IDENTIFIER(field_type) ? value_name(field_type) : "enum";
-               fprintf(output_file, " type => 'enum:%s',", names);
+               generate(" type => 'enum:%s',", names);
 #else
-               fprintf(output_file, " type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', field_size);
+               generate(" type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', field_size);
 #endif
-               fprintf(output_file, " ctype => 'enum %s',", value_name(field_type));
+               generate(" ctype => 'enum %s',", value_name(field_type));
                break;
        }
        case FUNCTION_TYPE: {
@@ -438,13 +458,14 @@ static void export_param(tree field, tree field_type, size_t field_size) {
 
                // If this is a typedef we might have a name for the type, otherwise it's a signature based name
                if (root_type && TYPE_IDENTIFIER(root_type)) {
-                       fprintf(output_file, " type => 'call:%s', ", value_name(root_type));
+                       generate(" type => 'call:%s', ", value_name(root_type));
                } else {
-                       fprintf(stderr, "save for later param type %p\n", field_type);
+                       if (debug_level > 0)
+                               fprintf(stderr, "save for later param type %p\n", field_type);
                        buffer_init(&b, 256);
                        export_desc(field, field_type, &b);
                        list_add(&todump, node_alloc(field_type, b.data));
-                       fprintf(output_file, " type => 'call:%s', ", b.data);
+                       generate(" type => 'call:%s', ", b.data);
                }
 
                buffer_init(&b, 256);
@@ -454,16 +475,16 @@ static void export_param(tree field, tree field_type, size_t field_size) {
                break;
        }
        case REAL_TYPE:
-               fprintf(output_file, " ctype => '%s',", value_name(field_type));
-               fprintf(output_file, " type => 'f%zu',", field_size);
+               generate(" ctype => '%s',", value_name(field_type));
+               generate(" type => 'f%zu',", field_size);
                break;
        case INTEGER_TYPE:
                if (TREE_CODE(field) == FIELD_DECL && DECL_BIT_FIELD(field)) {
-                       fprintf(output_file, " ctype => 'bitfield',");
-                       fprintf(output_file, " type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', value_size(DECL_SIZE(field)));
+                       generate(" ctype => 'bitfield',");
+                       generate(" type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', value_size(DECL_SIZE(field)));
                } else {
-                       fprintf(output_file, " ctype => '%s',", value_name(field_type));
-                       fprintf(output_file, " type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', field_size);
+                       generate(" ctype => '%s',", value_name(field_type));
+                       generate(" type => '%c%zu',", TYPE_UNSIGNED(field_type) ? 'u' : 'i', field_size);
                }
                break;
        case RECORD_TYPE:
@@ -471,12 +492,12 @@ static void export_param(tree field, tree field_type, size_t field_size) {
                const char *us = TREE_CODE(field_type) == RECORD_TYPE ? "struct" : "union";
 
                if (TYPE_IDENTIFIER(field_type)) {
-                       fprintf(output_file, " type => '%s:%s',", us, value_name(field_type));
+                       generate(" type => '%s:%s',", us, value_name(field_type));
                } else {
                        char *name = stack_path(&context_stack, "_");
 
                        list_add(&todump, node_alloc(field_type, name));
-                       fprintf(output_file, " type => '%s:%s',", us, name);
+                       generate(" type => '%s:%s',", us, name);
                        free(name);
                }
                break;
@@ -499,7 +520,8 @@ static void export_params(tree func) {
 
        if (fwd) {
                // use the forward reference to find the names
-               fprintf(stderr, "found forward reference @ %p\n", fwd);
+               if (debug_level > 0)
+                       fprintf(stderr, "found forward reference @ %p\n", fwd);
                name = fwd->list.head;
        } else {
                // paramter names are in the paramters list
@@ -513,7 +535,8 @@ static void export_params(tree func) {
 
                        struct node *decl = stack_pull(&parameters);
                        if (decl) {
-                               fprintf(stderr, "(pull parameter '%s')\n", decl->name);
+                               if (debug_level > 0)
+                                       fprintf(stderr, "(pull parameter '%s')\n", decl->name);
                                stack_push(&args, decl);
                        } else
                                fprintf(stderr, "ERROR: parameter %d missing parameter declaration\n", id);
@@ -531,10 +554,10 @@ static void export_params(tree func) {
                if (!TREE_CHAIN(param) && TREE_CODE(param_type) == VOID_TYPE)
                        break;
 
-               fprintf(output_file, "\t\t{");
+               generate("\t\t{");
 
                // size: do we need it?
-               fprintf(output_file, " size => %zu,", data_size);
+               generate(" size => %zu,", data_size);
 
                if (name) {
                        // this should be a parm_decl with an identifier of the name
@@ -545,11 +568,11 @@ static void export_params(tree func) {
                }
 
                if (!names || !names[0]) {
-                       sprintf(nameb, "arg_%d", id);
+                       sprintf(nameb, "arg$%d", id);
                        names = nameb;
                }
 
-               fprintf(output_file, " name => '%s',", names);
+               generate(" name => '%s',", names);
                stack_push(&context_stack, node_alloc(param, names));
 
                // value: details
@@ -557,7 +580,7 @@ static void export_params(tree func) {
 
                free(stack_pull(&context_stack));
 
-               fprintf(output_file, "},\n");
+               generate("},\n");
                id++;
        }
 
@@ -585,7 +608,7 @@ static void export_fields(tree first_field, size_t base_offset, int indent) {
                        if (debug_level > 1)
                                fprintf(stderr, "   field: %s\n", names);
                        print_spaces(indent+1);
-                       fprintf(output_file, "{ name => '%s', size => %zu, offset => %zu,", names, field_size, offset);
+                       generate("{ name => '%s', size => %zu, offset => %zu,", names, field_size, offset);
                        stack_push(&context_stack, node_alloc(field, names));
 
                        // value: details
@@ -593,7 +616,7 @@ static void export_fields(tree first_field, size_t base_offset, int indent) {
 
                        free(stack_pull(&context_stack));
 
-                       fprintf(output_file, "},\n");
+                       generate("},\n");
                }
        }
 }
@@ -630,7 +653,7 @@ static void export_type(tree type, const char *names) {
                case FUNCTION_TYPE: {
                        // function pointer typdef
                        // I don't know if i even want this
-                       fprintf(output_file, "'call:%s' => { name => '%s', type => 'call',", names, names);
+                       generate("'call:%s' => { name => '%s', type => 'call',", names, names);
 
                        // the deftype is always a pointer for a function_type
 
@@ -638,24 +661,24 @@ static void export_type(tree type, const char *names) {
 
                        buffer_init(&b, 256);
                        export_desc(type, deftype, &b);
-                       fprintf(output_file, " deref => '%s',", b.data);
+                       generate(" deref => '%s',", b.data);
                        free(b.data);
 
-                       fprintf(output_file, " ctype => '%s',", print_generic_expr_to_str(target));
+                       generate(" ctype => '%s',", print_generic_expr_to_str(target));
 
                        // TODO: cleanup
                        {
                                tree result_type = TREE_TYPE(target);
                                const size_t data_size = value_size(TYPE_SIZE(result_type));
 
-                               fprintf(output_file, "\n\tresult => {");
+                               generate("\n\tresult => {");
                                export_param(target, result_type, data_size);
-                               fprintf(output_file, " },");
+                               generate(" },");
                        }
 
-                       fprintf(output_file, "\n\targuments => [\n");
+                       generate("\n\targuments => [\n");
                        export_params(target);
-                       fprintf(output_file, "]},\n");
+                       generate("]},\n");
                        break;
                }
                case ENUMERAL_TYPE: {
@@ -670,15 +693,15 @@ static void export_type(tree type, const char *names) {
                                return;
                        }
 
-                       fprintf(output_file, "'enum:%s' => { name => '%s', type => 'enum', size => %zu, value_type => '%c%zu', values => [\n",
+                       generate("'enum:%s' => { name => '%s', type => 'enum', size => %zu, value_type => '%c%zu', values => [\n",
                                names, names, size, TYPE_UNSIGNED(target) ? 'u' : 'i', size);
 
                        for (tree v = TYPE_VALUES(target); v != NULL; v = TREE_CHAIN (v)) {
-                               fprintf(output_file, "\t{ label => '%s', value => '%ld' },\n",
+                               generate("\t{ label => '%s', value => '%ld' },\n",
                                        IDENTIFIER_POINTER(TREE_PURPOSE(v)),
                                        tree_to_shwi(TREE_VALUE(v)));
                        }
-                       fprintf(output_file, "]},\n");
+                       generate("]},\n");
                        break;
                }
                case RECORD_TYPE: // forward declaration or opaque types
@@ -710,12 +733,12 @@ static void export_type(tree type, const char *names) {
                if (debug_level > 1)
                        fprintf(stderr, "export type func decl %s\n", names);
 
-               fprintf(output_file, "'func:%s' => { name => '%s', type => 'func',", names, names);
+               generate("'func:%s' => { name => '%s', type => 'func',", names, names);
 
                // FUNCTION_DECL -> FUNCTION_TYPE -> RESULT_TYPE, get FUNCTION_TYPE
                type = TREE_TYPE(type);
 
-               fprintf(output_file, " ctype => '%s',", print_generic_expr_to_str(type));
+               generate(" ctype => '%s',", print_generic_expr_to_str(type));
 
                // TODO: cleanup
                debug_tree_helper(type, "function 1");
@@ -723,15 +746,15 @@ static void export_type(tree type, const char *names) {
                        tree result_type = TREE_TYPE(type);
                        const size_t data_size = value_size(TYPE_SIZE(result_type));
 
-                       fprintf(output_file, "\n\tresult => {");
+                       generate("\n\tresult => {");
                        export_param(type, result_type, data_size);
-                       fprintf(output_file, " },");
+                       generate(" },");
                }
 
-               fprintf(output_file, "\n\targuments => [\n");
+               generate("\n\targuments => [\n");
                //export_decl_params(DECL_ARGUMENTS(type), 0);
                export_params(type);
-               fprintf(output_file, "]},\n");
+               generate("]},\n");
                break;
        }
        case FUNCTION_TYPE: {
@@ -750,8 +773,8 @@ static void export_type(tree type, const char *names) {
                if (debug_level > 1)
                        fprintf(stderr, "export: %s %s\n", names, ZTREE_CODE(type));
 
-               fprintf(output_file, "'call:%s' => { name => '%s', type => 'call',", names, names);
-               fprintf(output_file, " ctype => '%s',", print_generic_expr_to_str(type));
+               generate("'call:%s' => { name => '%s', type => 'call',", names, names);
+               generate(" ctype => '%s',", print_generic_expr_to_str(type));
 
                debug_tree_helper(type, "function type");
 
@@ -765,16 +788,16 @@ static void export_type(tree type, const char *names) {
 
                        if (debug_level > 2)
                                fprintf(stderr, " result size %zu\n", data_size);
-                       fprintf(output_file, "\n\tresult => {");
+                       generate("\n\tresult => {");
                        export_param(type, result, data_size);
-                       fprintf(output_file, " },");
+                       generate(" },");
                }
 
                stack_push(&context_stack, node_alloc(type, names));
-               fprintf(output_file, "\n\targuments => [\n");
+               generate("\n\targuments => [\n");
                export_params(type);
                free(stack_pull(&context_stack));
-               fprintf(output_file, "]},\n");
+               generate("]},\n");
                break;
        }
        case RECORD_TYPE: // struct
@@ -798,14 +821,14 @@ static void export_type(tree type, const char *names) {
                if (debug_level > 1)
                        fprintf(stderr, "export: %s %s\n", names, ZTREE_CODE(type));
 
-               fprintf(output_file, "'%s:%s' => { name => '%s', type => '%s', size => %zu, fields => [\n",
+               generate("'%s:%s' => { name => '%s', type => '%s', size => %zu, fields => [\n",
                        su, names, names, su, tree_to_uhwi(TYPE_SIZE(type)));
 
                stack_push(&context_stack, node_alloc(type, names));
                export_fields(TYPE_FIELDS(type), 0, 0);
                free(stack_pull(&context_stack));
 
-               fprintf(output_file, "]},\n");
+               generate("]},\n");
                break;
        }
        case ENUMERAL_TYPE: {
@@ -846,15 +869,15 @@ static void export_type(tree type, const char *names) {
                if (debug_level > 1)
                        fprintf(stderr, "export: %s %s\n", names, ZTREE_CODE(type));
 
-               fprintf(output_file, "'enum:%s' => { name => '%s', type => 'enum', size => %zu, value_type => '%c%zu', values => [\n",
+               generate("'enum:%s' => { name => '%s', type => 'enum', size => %zu, value_type => '%c%zu', values => [\n",
                        names, names, size, TYPE_UNSIGNED(type) ? 'u' : 'i', size);
 
                for (tree v = TYPE_VALUES(type); v != NULL; v = TREE_CHAIN (v)) {
-                       fprintf(output_file, "\t{ label => '%s', value => '%ld' },\n",
+                       generate("\t{ label => '%s', value => '%ld' },\n",
                                IDENTIFIER_POINTER(TREE_PURPOSE(v)),
                                tree_to_shwi(TREE_VALUE(v)));
                }
-               fprintf(output_file, "]},\n");
+               generate("]},\n");
                break;
        }
        case FIELD_DECL:
@@ -879,7 +902,8 @@ static void export_type(tree type, const char *names) {
                        // it's keyed on target
                        struct node *fwd = node_alloc(target, NULL);
 
-                       fprintf(stderr, "save forward reference function type %p\n", target);
+                       if (debug_level > 0)
+                               fprintf(stderr, "save forward reference function type %p\n", target);
 
                        for (tree param = TYPE_ARG_TYPES(target); param != NULL; param = TREE_CHAIN(param)) {
                                tree param_type = TREE_VALUE(param);
@@ -889,16 +913,18 @@ static void export_type(tree type, const char *names) {
 
                                struct node *decl = stack_pull(&parameters);
                                if (decl) {
-                                       fprintf(stderr, "(pull parameter '%s')\n", decl->name);
+                                       if (debug_level > 0)
+                                               fprintf(stderr, "(pull parameter '%s')\n", decl->name);
                                        stack_push(&fwd->list, decl);
                                } else
-                                       fprintf(stderr, " missing parameter name\n");
+                                       fprintf(stderr, "WARNING: stack is missing parameter name function %s\n", names);
                        }
 
                        hash_put_bytype(&forward_types, fwd);
                }
 
-               fprintf(stderr, "(push parameter '%s')\n", names);
+               if (debug_level > 0)
+                       fprintf(stderr, "(push parameter '%s')\n", names);
                stack_push(&parameters, node_alloc(type, names));
 
                break; }
@@ -935,7 +961,8 @@ static void plugin_finish_decl(void *event_data, void *user_data) {
 }
 
 static void plugin_finish(void *event_data, void *user_data) {
-       fprintf(stderr, "plugin finish\n");
+       if (debug_level > 0)
+               fprintf(stderr, "plugin finish\n");
        for (struct node *n = todump.head; n; n=n->next) {
                if (COMPLETE_TYPE_P(n->type)) {
                        if (n->name[0]) {
@@ -946,14 +973,15 @@ static void plugin_finish(void *event_data, void *user_data) {
                }
        }
 
-       fprintf(output_file, "# dumped structs:\n");
+       generate("# dumped structs:\n");
        for (struct node *n = dumped.list.head; n; n=n->next)
-               fprintf(output_file, "# %s\n", n->name);
+               generate("# %s\n", n->name);
 
-       fprintf(output_file, ");\n");
+       generate(");\n");
        fclose(output_file);
 
-       fprintf(stderr, "unhandled paramters:\n");
+       if (debug_level > 0)
+               fprintf(stderr, "unhandled paramters:\n");
        list_clear(&parameters);
 }
 
@@ -979,7 +1007,7 @@ int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version
                exit(EXIT_FAILURE);
        }
 
-       fprintf(output_file, "%%data = (\n");
+       generate("%%data = (\n");
 
        register_callback(plugin_info->base_name, PLUGIN_FINISH_DECL, plugin_finish_decl, NULL);
        register_callback(plugin_info->base_name, PLUGIN_FINISH_TYPE, plugin_finish_type, NULL);