This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[PATCH] Clean up the gimple type verifier [2/2]
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Diego Novillo <dnovillo at google dot com>, fortran at gcc dot gnu dot org
- Date: Wed, 3 Sep 2008 18:33:11 +0200 (CEST)
- Subject: [PATCH] Clean up the gimple type verifier [2/2]
This splits apart and "completes" verifying of GIMPLE_ASSIGN.
Unfortunately during the time the checks were incomplete/disabled
we have gathered some new problems (maybe due to tuplification of
the gimplifier, I'll have to investigate).
Bootstrapped on x86_64-unknown-linux-gnu, the C testsuite is clean,
as are the Ada, java, objc and libstdc++ ones. C++ has got one
problem (back?):
g++.old-deja/g++.law/casts2.C:30: error: non-register as LHS of unary
operation^M
q = (struct method1) m;^M
and similar
g++.dg/opt/ptrmem6.C:14: error: non-register as LHS of unary operation^M
D.2092 = (struct ^M
{^M
object:: * __pfn;^M
long int __delta;^M
}) iftmp.0;^M
(in multiple places). Also conversions from void * are missing, but
I guess this is a bug in the gimplifier.
GFortran has multiplie problems with integer sizes (again), like
gfortran.dg/optional_dim_2.f90:6: error: non-trivial conversion at
assignment^M
integer(kind=8)^M
integer(kind=4)^M
iftmp.26 = 1;^M
and the void * conversion as well. In addition to those there are
gfortran.dg/widechar_intrinsics_8.f90:11: error: non-trivial conversion at
assignment^M
character(kind=1)[1:_s1] &^M
character(kind=1)[1:_t1] &^M
iftmp.20 = t1;^M
and a strange one,
gfortran.fortran-torture/execute/intrinsic_si_kind.f90:2: error:
non-register as LHS of unary operation^M
D.1546 = (integer(kind=4)) t;^M
I didn't yet investigate the particular cases which is why I post
the patch now and say that any help is appreciated ;) (the patch
applies on [1/2] posted previously)
Thanks,
Richard.
2008-09-03 Richard Guenther <rguenther@suse.de>
* tree-cfg.c (verify_types_in_gimple_assign): Rename to ...
(verify_gimple_assign): ... this. Split into ...
(verify_gimple_assign_unary): ... this,
(verify_gimple_assign_binary): ... that,
(verify_gimple_assign_single): ... and this.
(verify_types_in_gimple_stmt): Call verify_gimple_assign.
* tree.def (PREDICT_EXPR): Change to tcc_expression.
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c 2008-09-03 15:33:30.000000000 +0200
--- trunk/gcc/tree-cfg.c 2008-09-03 15:33:51.000000000 +0200
*************** verify_gimple_comparison (tree type, tre
*** 3254,3290 ****
return false;
}
! /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
! is a problem, otherwise false.
!
! Verify that the types of the LHS and the RHS operands are
! compatible. This verification largely depends on what kind of
! operation is done on the RHS of the assignment. It is not always
! the case that all the types of the operands must match (e.g., 'a =
! (unsigned long) b' or 'ptr = ptr + 1'). */
static bool
! verify_types_in_gimple_assign (gimple stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs = gimple_assign_lhs (stmt);
- tree rhs1 = gimple_assign_rhs1 (stmt);
- tree rhs2 = (gimple_num_ops (stmt) == 3) ? gimple_assign_rhs2 (stmt) : NULL;
tree lhs_type = TREE_TYPE (lhs);
tree rhs1_type = TREE_TYPE (rhs1);
- tree rhs2_type = (rhs2) ? TREE_TYPE (rhs2) : NULL;
! /* Special codes we cannot handle via their class. */
switch (rhs_code)
{
CASE_CONVERT:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in conversion");
- return true;
- }
-
/* Allow conversions between integral types and pointers only if
there is no sign or zero extension involved. */
if (((POINTER_TYPE_P (lhs_type) && INTEGRAL_TYPE_P (rhs1_type))
--- 3254,3290 ----
return false;
}
! /* Verify a gimple assignment statement STMT with an unary rhs.
! Returns true if anything is wrong. */
static bool
! verify_gimple_assign_unary (gimple stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs = gimple_assign_lhs (stmt);
tree lhs_type = TREE_TYPE (lhs);
+ tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs1_type = TREE_TYPE (rhs1);
! if (!is_gimple_reg (lhs)
! && !(optimize == 0
! && TREE_CODE (lhs_type) == COMPLEX_TYPE))
! {
! error ("non-register as LHS of unary operation");
! return true;
! }
!
! if (!is_gimple_val (rhs1))
! {
! error ("invalid operand in unary operation");
! return true;
! }
!
! /* First handle conversions. */
switch (rhs_code)
{
CASE_CONVERT:
{
/* Allow conversions between integral types and pointers only if
there is no sign or zero extension involved. */
if (((POINTER_TYPE_P (lhs_type) && INTEGRAL_TYPE_P (rhs1_type))
*************** verify_types_in_gimple_assign (gimple st
*** 3317,3328 ****
case FIXED_CONVERT_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in conversion");
- return true;
- }
-
if (!valid_fixed_convert_types_p (lhs_type, rhs1_type)
&& !valid_fixed_convert_types_p (rhs1_type, lhs_type))
{
--- 3317,3322 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3337,3348 ****
case FLOAT_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in int to float conversion");
- return true;
- }
-
if (!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
{
error ("invalid types in conversion to floating point");
--- 3331,3336 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3356,3367 ****
case FIX_TRUNC_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in float to int conversion");
- return true;
- }
-
if (!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
{
error ("invalid types in conversion to integer");
--- 3344,3349 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3373,3386 ****
return false;
}
! case COMPLEX_EXPR:
{
! if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
! {
! error ("invalid operands in complex expression");
! return true;
! }
if (!TREE_CODE (lhs_type) == COMPLEX_TYPE
|| !(TREE_CODE (rhs1_type) == INTEGER_TYPE
|| SCALAR_FLOAT_TYPE_P (rhs1_type))
--- 3355,3429 ----
return false;
}
! case TRUTH_NOT_EXPR:
{
! }
!
! case NEGATE_EXPR:
! case ABS_EXPR:
! case BIT_NOT_EXPR:
! case PAREN_EXPR:
! case NON_LVALUE_EXPR:
! case CONJ_EXPR:
! case REDUC_MAX_EXPR:
! case REDUC_MIN_EXPR:
! case REDUC_PLUS_EXPR:
! case VEC_UNPACK_HI_EXPR:
! case VEC_UNPACK_LO_EXPR:
! case VEC_UNPACK_FLOAT_HI_EXPR:
! case VEC_UNPACK_FLOAT_LO_EXPR:
! break;
!
! default:
! gcc_unreachable ();
! }
!
! /* For the remaining codes assert there is no conversion involved. */
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion in unary operation");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
!
! return false;
! }
!
! /* Verify a gimple assignment statement STMT with a binary rhs.
! Returns true if anything is wrong. */
!
! static bool
! verify_gimple_assign_binary (gimple stmt)
! {
! enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
! tree lhs = gimple_assign_lhs (stmt);
! tree lhs_type = TREE_TYPE (lhs);
! tree rhs1 = gimple_assign_rhs1 (stmt);
! tree rhs1_type = TREE_TYPE (rhs1);
! tree rhs2 = gimple_assign_rhs2 (stmt);
! tree rhs2_type = TREE_TYPE (rhs2);
!
! if (!is_gimple_reg (lhs)
! && !(optimize == 0
! && TREE_CODE (lhs_type) == COMPLEX_TYPE))
! {
! error ("non-register as LHS of binary operation");
! return true;
! }
!
! if (!is_gimple_val (rhs1)
! || !is_gimple_val (rhs2))
! {
! error ("invalid operands in binary operation");
! return true;
! }
+ /* First handle operations that involve different types. */
+ switch (rhs_code)
+ {
+ case COMPLEX_EXPR:
+ {
if (!TREE_CODE (lhs_type) == COMPLEX_TYPE
|| !(TREE_CODE (rhs1_type) == INTEGER_TYPE
|| SCALAR_FLOAT_TYPE_P (rhs1_type))
*************** verify_types_in_gimple_assign (gimple st
*** 3397,3422 ****
return false;
}
- case CONSTRUCTOR:
- {
- /* In this context we know that we are on the RHS of an
- assignment, so CONSTRUCTOR operands are OK. */
- /* FIXME: verify constructor arguments. */
- return false;
- }
-
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in shift expression");
- return true;
- }
-
if (!TREE_CODE (rhs1_type) == INTEGER_TYPE
|| !useless_type_conversion_p (lhs_type, rhs1_type))
{
error ("type mismatch in shift expression");
--- 3440,3452 ----
return false;
}
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
{
if (!TREE_CODE (rhs1_type) == INTEGER_TYPE
+ || !TREE_CODE (rhs2_type) == INTEGER_TYPE
|| !useless_type_conversion_p (lhs_type, rhs1_type))
{
error ("type mismatch in shift expression");
*************** verify_types_in_gimple_assign (gimple st
*** 3429,3456 ****
return false;
}
- case PLUS_EXPR:
- case MINUS_EXPR:
- {
- if (POINTER_TYPE_P (lhs_type)
- || POINTER_TYPE_P (rhs1_type)
- || POINTER_TYPE_P (rhs2_type))
- {
- error ("invalid (pointer) operands to plus/minus");
- return true;
- }
-
- /* Continue with generic binary expression handling. */
- break;
- }
-
case POINTER_PLUS_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in pointer plus expression");
- return true;
- }
if (!POINTER_TYPE_P (rhs1_type)
|| !useless_type_conversion_p (lhs_type, rhs1_type)
|| !useless_type_conversion_p (sizetype, rhs2_type))
--- 3459,3466 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3465,3494 ****
return false;
}
- case ADDR_EXPR:
- {
- tree op = TREE_OPERAND (rhs1, 0);
- if (!is_gimple_addressable (op))
- {
- error ("invalid operand in unary expression");
- return true;
- }
-
- if (!one_pointer_to_useless_type_conversion_p (lhs_type, TREE_TYPE (op))
- /* FIXME: a longstanding wart, &a == &a[0]. */
- && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
- || !one_pointer_to_useless_type_conversion_p (lhs_type,
- TREE_TYPE (TREE_TYPE (op)))))
- {
- error ("type mismatch in address expression");
- debug_generic_stmt (lhs_type);
- debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
- return true;
- }
-
- return verify_types_in_gimple_reference (TREE_OPERAND (rhs1, 0));
- }
-
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
gcc_unreachable ();
--- 3475,3480 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3497,3508 ****
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in truth expression");
- return true;
- }
-
/* We allow any kind of integral typed argument and result. */
if (!INTEGRAL_TYPE_P (rhs1_type)
|| !INTEGRAL_TYPE_P (rhs2_type)
--- 3483,3488 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3518,3626 ****
return false;
}
! case TRUTH_NOT_EXPR:
{
! if (!is_gimple_val (rhs1))
{
! error ("invalid operand in unary not");
return true;
}
! /* For TRUTH_NOT_EXPR we can have any kind of integral
! typed arguments and results. */
! if (!INTEGRAL_TYPE_P (rhs1_type)
! || !INTEGRAL_TYPE_P (lhs_type))
{
! error ("type mismatch in not expression");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
return true;
}
! return false;
! }
! /* After gimplification we should not have any of these. */
! case ASM_EXPR:
! case BIND_EXPR:
! case CALL_EXPR:
! case COND_EXPR:
! case TREE_LIST:
! case COMPOUND_EXPR:
! case MODIFY_EXPR:
! case INIT_EXPR:
! case GOTO_EXPR:
! case LABEL_EXPR:
! case RETURN_EXPR:
! case TRY_FINALLY_EXPR:
! case TRY_CATCH_EXPR:
! case EH_FILTER_EXPR:
! case STATEMENT_LIST:
! {
! error ("tree node that should already be gimple.");
! return true;
}
case OBJ_TYPE_REF:
/* FIXME. */
! return false;
default:;
}
! /* Generic handling via classes. */
! switch (TREE_CODE_CLASS (rhs_code))
! {
! case tcc_exceptional: /* for SSA_NAME */
! case tcc_unary:
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
! break;
! case tcc_binary:
! if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
! {
! error ("invalid operands in binary expression");
! return true;
! }
! if (!useless_type_conversion_p (lhs_type, rhs1_type)
! || !useless_type_conversion_p (lhs_type, rhs2_type))
! {
! error ("type mismatch in binary expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (rhs1_type);
! debug_generic_stmt (rhs2_type);
! return true;
! }
! break;
! case tcc_reference:
! /* All tcc_reference trees are GIMPLE_SINGLE_RHS. Verify that
! no implicit type change happens here. */
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
! return verify_types_in_gimple_reference (rhs1);
! case tcc_comparison:
! return verify_gimple_comparison (lhs_type, rhs1, rhs2);
! default:;
! }
! return false;
}
-
/* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there
is a problem, otherwise false. */
--- 3498,3706 ----
return false;
}
! case LT_EXPR:
! case LE_EXPR:
! case GT_EXPR:
! case GE_EXPR:
! case EQ_EXPR:
! case NE_EXPR:
! case UNORDERED_EXPR:
! case ORDERED_EXPR:
! case UNLT_EXPR:
! case UNLE_EXPR:
! case UNGT_EXPR:
! case UNGE_EXPR:
! case UNEQ_EXPR:
! case LTGT_EXPR:
! /* Comparisons are also binary, but the result type is not
! connected to the operand types. */
! return verify_gimple_comparison (lhs_type, rhs1, rhs2);
!
! case PLUS_EXPR:
! case MINUS_EXPR:
{
! if (POINTER_TYPE_P (lhs_type)
! || POINTER_TYPE_P (rhs1_type)
! || POINTER_TYPE_P (rhs2_type))
{
! error ("invalid (pointer) operands to plus/minus");
return true;
}
! /* Continue with generic binary expression handling. */
! break;
! }
!
! case MULT_EXPR:
! case TRUNC_DIV_EXPR:
! case CEIL_DIV_EXPR:
! case FLOOR_DIV_EXPR:
! case ROUND_DIV_EXPR:
! case TRUNC_MOD_EXPR:
! case CEIL_MOD_EXPR:
! case FLOOR_MOD_EXPR:
! case ROUND_MOD_EXPR:
! case RDIV_EXPR:
! case EXACT_DIV_EXPR:
! case MIN_EXPR:
! case MAX_EXPR:
! case BIT_IOR_EXPR:
! case BIT_XOR_EXPR:
! case BIT_AND_EXPR:
! case WIDEN_SUM_EXPR:
! case WIDEN_MULT_EXPR:
! case VEC_LSHIFT_EXPR:
! case VEC_RSHIFT_EXPR:
! case VEC_WIDEN_MULT_HI_EXPR:
! case VEC_WIDEN_MULT_LO_EXPR:
! case VEC_PACK_TRUNC_EXPR:
! case VEC_PACK_SAT_EXPR:
! case VEC_PACK_FIX_TRUNC_EXPR:
! case VEC_EXTRACT_EVEN_EXPR:
! case VEC_EXTRACT_ODD_EXPR:
! case VEC_INTERLEAVE_HIGH_EXPR:
! case VEC_INTERLEAVE_LOW_EXPR:
! /* Continue with generic binary expression handling. */
! break;
!
! default:
! gcc_unreachable ();
! }
!
! if (!useless_type_conversion_p (lhs_type, rhs1_type)
! || !useless_type_conversion_p (lhs_type, rhs2_type))
! {
! error ("type mismatch in binary expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (rhs1_type);
! debug_generic_stmt (rhs2_type);
! return true;
! }
!
! return false;
! }
!
! /* Verify a gimple assignment statement STMT with a single rhs.
! Returns true if anything is wrong. */
!
! static bool
! verify_gimple_assign_single (gimple stmt)
! {
! enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
! tree lhs = gimple_assign_lhs (stmt);
! tree lhs_type = TREE_TYPE (lhs);
! tree rhs1 = gimple_assign_rhs1 (stmt);
! tree rhs1_type = TREE_TYPE (rhs1);
! bool res = false;
!
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
!
! if (handled_component_p (lhs))
! res |= verify_types_in_gimple_reference (lhs);
!
! /* Special codes we cannot handle via their class. */
! switch (rhs_code)
! {
! case ADDR_EXPR:
! {
! tree op = TREE_OPERAND (rhs1, 0);
! if (!is_gimple_addressable (op))
{
! error ("invalid operand in unary expression");
return true;
}
! if (!one_pointer_to_useless_type_conversion_p (lhs_type, TREE_TYPE (op))
! /* FIXME: a longstanding wart, &a == &a[0]. */
! && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
! || !one_pointer_to_useless_type_conversion_p (lhs_type,
! TREE_TYPE (TREE_TYPE (op)))))
! {
! error ("type mismatch in address expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
! return true;
! }
! return verify_types_in_gimple_reference (op);
}
+ /* tcc_reference */
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case TARGET_MEM_REF:
+ return res || verify_types_in_gimple_reference (rhs1);
+
+ /* tcc_constant */
+ case SSA_NAME:
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ case STRING_CST:
+ /* tcc_declaration */
+ case VAR_DECL:
+ case CONST_DECL:
+ case PARM_DECL:
+ return res;
+
+ case COND_EXPR:
+ case CONSTRUCTOR:
case OBJ_TYPE_REF:
+ case ASSERT_EXPR:
+ case WITH_SIZE_EXPR:
+ case EXC_PTR_EXPR:
+ case FILTER_EXPR:
+ case POLYNOMIAL_CHREC:
+ case DOT_PROD_EXPR:
+ case VEC_COND_EXPR:
+ case REALIGN_LOAD_EXPR:
/* FIXME. */
! return res;
default:;
}
! return res;
! }
! /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
! is a problem, otherwise false. */
! static bool
! verify_gimple_assign (gimple stmt)
! {
! switch (gimple_assign_rhs_class (stmt))
! {
! case GIMPLE_SINGLE_RHS:
! return verify_gimple_assign_single (stmt);
! case GIMPLE_UNARY_RHS:
! return verify_gimple_assign_unary (stmt);
! case GIMPLE_BINARY_RHS:
! return verify_gimple_assign_binary (stmt);
! default:
! gcc_unreachable ();
! }
}
/* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there
is a problem, otherwise false. */
*************** verify_types_in_gimple_stmt (gimple stmt
*** 3755,3761 ****
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
! return verify_types_in_gimple_assign (stmt);
case GIMPLE_LABEL:
return TREE_CODE (gimple_label_label (stmt)) != LABEL_DECL;
--- 3835,3841 ----
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
! return verify_gimple_assign (stmt);
case GIMPLE_LABEL:
return TREE_CODE (gimple_label_label (stmt)) != LABEL_DECL;
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def 2008-09-03 15:31:15.000000000 +0200
--- trunk/gcc/tree.def 2008-09-03 15:33:51.000000000 +0200
*************** DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "v
*** 1137,1143 ****
outcome (0 for not taken and 1 for taken). Once the profile is guessed
all conditional branches leading to execution paths executing the
PREDICT_EXPR will get predicted by the specified predictor. */
! DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_unary, 1)
/* OPTIMIZATION_NODE. Node to store the optimization options. */
DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
--- 1137,1143 ----
outcome (0 for not taken and 1 for taken). Once the profile is guessed
all conditional branches leading to execution paths executing the
PREDICT_EXPR will get predicted by the specified predictor. */
! DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_expression, 1)
/* OPTIMIZATION_NODE. Node to store the optimization options. */
DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)