diff mbox

[PING] New plugin event when evaluating a constexpr call

Message ID CAJZwELnRxL54Z8GeXk1gTGY8qd8XeDsEXk-vAPJmMdjoyy-eqQ@mail.gmail.com
State New
Headers show

Commit Message

Andres Tiraboschi April 25, 2016, 2:08 p.m. UTC
Hi
 This patch adds a plugin event when evaluating a call expression in constexpr.
 The goal of this patch is to allow the plugins to analyze and or
modify the evaluation of constant expressions.


Changelog 2016-4-25  Andres Tiraboschi
<andres.tiraboschi@tallertechnologies.com>
    *gcc/plugin.c (PLUGIN_EVAL_CALL_CONSTEXPR): New event.
    *gcc/plugin.def (PLUGIN_EVAL_CALL_CONSTEXPR): New event.
    *gcc/cp/constexpr.c (constexpr_fundef): Moved to gcc/cp/cp-tree.h.
    *gcc/cp/constexpr.c (constexpr_call): Ditto.
    *gcc/cp/constexpr.c (constexpr_ctx): Ditto.
    *gcc/cp/constexpr.c (cxx_eval_constant_expression): Not static anymore.
    *gcc/pc/cp-tree.h (constexpr_call_info): New Type.
    *gcc/pc/cp-tree.h (constexpr_fundef): Moved type from gcc/cp/constexpr.c.
    *gcc/pc/cp-tree.h (constexpr_call): Ditto.
    *gcc/pc/cp-tree.h (constexpr_ctx): Ditto.
    *gcc/pc/cp-tree.h (cxx_eval_constant_expression): Declared.

Comments

Jason Merrill April 25, 2016, 7:21 p.m. UTC | #1
On 04/25/2016 10:08 AM, Andres Tiraboschi wrote:
>      *gcc/cp/constexpr.c (constexpr_fundef): Moved to gcc/cp/cp-tree.h.
>      *gcc/cp/constexpr.c (constexpr_call): Ditto.
>      *gcc/cp/constexpr.c (constexpr_ctx): Ditto.

Let's create a constexpr.h rather than expose constexpr internals to all 
of the front end.  Really, I'd prefer to avoid exposing them at all. 
Why does what you want to do require all this implementation detail?

>     bool non_constant_args = false;
>     cxx_bind_parameters_in_call (ctx, t, &new_call,
>                      non_constant_p, overflow_p, &non_constant_args);
> +
> +  constexpr_call_info call_info;
> +  call_info.function = t;
> +  call_info.lval = lval;
> +  call_info.call = &new_call;
> +  call_info.call_stack = call_stack;
> +  call_info.non_constant_args = &non_constant_args;
> +  call_info.non_const_p = non_constant_p;
> +  call_info.ctx = ctx;
> +  call_info.result = NULL_TREE;
> +  invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info);
> +  if (call_info.result != NULL_TREE)
> +    {
> +      return call_info.result;
> +    }
> +
>     if (*non_constant_p)
>       return t;

This is a curious place to invoke the callback.  Why before the 
*non_constant_p?  More generally, why between evaluating the arguments 
and evaluating the function body?

Jason
Andres Tiraboschi April 26, 2016, 1:41 p.m. UTC | #2
Hi, thanks for answering,

2016-04-25 16:21 GMT-03:00 Jason Merrill <jason@redhat.com>:
> Let's create a constexpr.h rather than expose constexpr internals to all of
> the front end.  Really, I'd prefer to avoid exposing them at all. Why does
> what you want to do require all this implementation detail?

Ok, you are right, I'll make a constexpr.h.

> This is a curious place to invoke the callback.  Why before the
> *non_constant_p?  More generally, why between evaluating the arguments and
> evaluating the function body?

That was because I was interested just in the functions and its
arguments, but you are right, I'll do the callback at the beginning of
the function.

Regards,
Andrés.
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5f97c9d..5562e44 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -31,6 +31,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "plugin-api.h"
+#include "plugin.h"

 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)                        \
@@ -112,13 +114,6 @@  ensure_literal_type_for_constexpr_object (tree decl)
   return decl;
 }

-/* Representation of entries in the constexpr function definition table.  */
-
-struct GTY((for_user)) constexpr_fundef {
-  tree decl;
-  tree body;
-};
-
 struct constexpr_fundef_hasher : ggc_ptr_hash<constexpr_fundef>
 {
   static hashval_t hash (constexpr_fundef *);
@@ -856,62 +851,12 @@  explain_invalid_constexpr_fn (tree fun)
   input_location = save_loc;
 }

-/* Objects of this type represent calls to constexpr functions
-   along with the bindings of parameters to their arguments, for
-   the purpose of compile time evaluation.  */
-
-struct GTY((for_user)) constexpr_call {
-  /* Description of the constexpr function definition.  */
-  constexpr_fundef *fundef;
-  /* Parameter bindings environment.  A TREE_LIST where each TREE_PURPOSE
-     is a parameter _DECL and the TREE_VALUE is the value of the parameter.
-     Note: This arrangement is made to accommodate the use of
-     iterative_hash_template_arg (see pt.c).  If you change this
-     representation, also change the hash calculation in
-     cxx_eval_call_expression.  */
-  tree bindings;
-  /* Result of the call.
-       NULL means the call is being evaluated.
-       error_mark_node means that the evaluation was erroneous;
-       otherwise, the actuall value of the call.  */
-  tree result;
-  /* The hash of this call; we remember it here to avoid having to
-     recalculate it when expanding the hash table.  */
-  hashval_t hash;
-};
-
 struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
 {
   static hashval_t hash (constexpr_call *);
   static bool equal (constexpr_call *, constexpr_call *);
 };

-/* The constexpr expansion context.  CALL is the current function
-   expansion, CTOR is the current aggregate initializer, OBJECT is the
-   object being initialized by CTOR, either a VAR_DECL or a _REF.  VALUES
-   is a map of values of variables initialized within the expression.  */
-
-struct constexpr_ctx {
-  /* The innermost call we're evaluating.  */
-  constexpr_call *call;
-  /* Values for any temporaries or local variables within the
-     constant-expression. */
-  hash_map<tree,tree> *values;
-  /* SAVE_EXPRs that we've seen within the current LOOP_EXPR.  NULL if we
-     aren't inside a loop.  */
-  hash_set<tree> *save_exprs;
-  /* The CONSTRUCTOR we're currently building up for an aggregate
-     initializer.  */
-  tree ctor;
-  /* The object we're building the CONSTRUCTOR for.  */
-  tree object;
-  /* Whether we should error on a non-constant expression or fail quietly.  */
-  bool quiet;
-  /* Whether we are strictly conforming to constant expression rules or
-     trying harder to get a constant value.  */
-  bool strict;
-};
-
 /* A table of all constexpr calls that have been evaluated by the
    compiler in this translation unit.  */

@@ -1303,6 +1248,22 @@  cxx_eval_call_expression (const constexpr_ctx
*ctx, tree t,
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
                    non_constant_p, overflow_p, &non_constant_args);
+
+  constexpr_call_info call_info;
+  call_info.function = t;
+  call_info.lval = lval;
+  call_info.call = &new_call;
+  call_info.call_stack = call_stack;
+  call_info.non_constant_args = &non_constant_args;
+  call_info.non_const_p = non_constant_p;
+  call_info.ctx = ctx;
+  call_info.result = NULL_TREE;
+  invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info);
+  if (call_info.result != NULL_TREE)
+    {
+      return call_info.result;
+    }
+
   if (*non_constant_p)
     return t;

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 15b004d..00856ec 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6946,6 +6946,77 @@  extern tree cp_ubsan_maybe_instrument_downcast
  (location_t, tree, tree, tree);
 extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
 extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);

+/* Representation of entries in the constexpr function definition table.  */
+
+struct GTY((for_user)) constexpr_fundef {
+  tree decl;
+  tree body;
+};
+
+/* Objects of this type represent calls to constexpr functions
+   along with the bindings of parameters to their arguments, for
+   the purpose of compile time evaluation.  */
+
+struct GTY((for_user)) constexpr_call {
+  /* Description of the constexpr function definition.  */
+  constexpr_fundef *fundef;
+  /* Parameter bindings environment.  A TREE_LIST where each TREE_PURPOSE
+     is a parameter _DECL and the TREE_VALUE is the value of the parameter.
+     Note: This arrangement is made to accommodate the use of
+     iterative_hash_template_arg (see pt.c).  If you change this
+     representation, also change the hash calculation in
+     cxx_eval_call_expression.  */
+  tree bindings;
+  /* Result of the call.
+       NULL means the call is being evaluated.
+       error_mark_node means that the evaluation was erroneous;
+       otherwise, the actuall value of the call.  */
+  tree result;
+  /* The hash of this call; we remember it here to avoid having to
+     recalculate it when expanding the hash table.  */
+  hashval_t hash;
+};
+
+/* The constexpr expansion context.  CALL is the current function
+   expansion, CTOR is the current aggregate initializer, OBJECT is the
+   object being initialized by CTOR, either a VAR_DECL or a _REF.  VALUES
+   is a map of values of variables initialized within the expression.  */
+
+struct constexpr_ctx {
+  /* The innermost call we're evaluating.  */
+  constexpr_call *call;
+  /* Values for any temporaries or local variables within the
+     constant-expression. */
+  hash_map<tree,tree> *values;
+  /* SAVE_EXPRs that we've seen within the current LOOP_EXPR.  NULL if we
+     aren't inside a loop.  */
+  hash_set<tree> *save_exprs;
+  /* The CONSTRUCTOR we're currently building up for an aggregate
+     initializer.  */
+  tree ctor;
+  /* The object we're building the CONSTRUCTOR for.  */
+  tree object;
+  /* Whether we should error on a non-constant expression or fail quietly.  */
+  bool quiet;
+  /* Whether we are strictly conforming to constant expression rules or
+     trying harder to get a constant value.  */
+  bool strict;
+};
+
+/* This type represents a function call into a constant expression.*/
+typedef struct constexpr_call_info_st
+{
+    tree function;                      //Function named in call.
+    tree result;                        //Function call result.
+    vec<tree> call_stack;               //Call stack.
+    bool lval;
+    bool* non_constant_args;            //The function arguments are constant.
+    bool* non_const_p;                  //Is constant.
+    bool* overflow;
+    constexpr_call* call;               //Call to the constexpr function.
+    const struct constexpr_ctx* ctx;    //constexpr expansion context.
+} constexpr_call_info;
+
 /* -- end of C++ */

 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 60081a5..34c60ed 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -427,6 +427,7 @@  register_callback (const char *plugin_name,
         return;
       }
       /* Fall through.  */
+      case PLUGIN_EVAL_CALL_CONSTEXPR:
       case PLUGIN_START_PARSE_FUNCTION:
       case PLUGIN_FINISH_PARSE_FUNCTION:
       case PLUGIN_FINISH_TYPE:
@@ -507,6 +508,7 @@  invoke_plugin_callbacks_full (int event, void *gcc_data)
     gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
     gcc_assert (event < event_last);
       /* Fall through.  */
+      case PLUGIN_EVAL_CALL_CONSTEXPR:
       case PLUGIN_START_PARSE_FUNCTION:
       case PLUGIN_FINISH_PARSE_FUNCTION:
       case PLUGIN_FINISH_TYPE:
diff --git a/gcc/plugin.def b/gcc/plugin.def
index c926d41..824f807 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -17,6 +17,9 @@  You should have received a copy of the GNU General
Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */

+/* Called when evaluating a constexpr call.  */
+DEFEVENT (PLUGIN_EVAL_CALL_CONSTEXPR)
+
 /* Called before parsing the body of a function.  */
 DEFEVENT (PLUGIN_START_PARSE_FUNCTION)