Commit ba38d76b authored by Matthias Braun's avatar Matthias Braun
Browse files

rework verify code

The new code has less options and variants, if you call irg_verify()
verification is performed, regardless of DEBUG_libfirm, or NDEBUG being
set and regardless of firm verification setting switches. On the other
side no atomic dump and abort is performed anymore, the call has to do
this, though an irg_assert_verify() function has been added as a
convenience measure.
There has also been a complete rewrite of the actual checking performed.
The new code is simpler, should produce more consistent output and
can report more than one error.
parent 872780dd
......@@ -6,7 +6,7 @@
/**
* @file
* @brief Check irnodes for correctness.
* @author Christian Schaefer, Goetz Lindenmaier, Till Riedel
* @author Christian Schaefer, Goetz Lindenmaier, Till Riedel, Matthias Braun
*/
#ifndef FIRM_IR_IRVERIFY_H
#define FIRM_IR_IRVERIFY_H
......@@ -20,66 +20,35 @@
*/
/**
* Tests the modes of checknode and its predecessors.
*
* @return NON-zero on success
* Tests @p node for well-formedness.
* This mostly tests modes of inputs/outputs. Only local properties are tested
* global properties are only checked by irg_verify().
* @return NON-zero if no problems were found
*/
FIRM_API int irn_verify(const ir_node *checknode);
FIRM_API int irn_verify(const ir_node *node);
/**
* Tests the modes of checknode and its predecessors.
* checknode must be in given ir_graph.
*
* @return NON-zero on success
* Tests @p node for well-formedness assuming that it is part of graph @p irg.
* @see irn_verify()
* @return NON-zero if no problems were found
*/
FIRM_API int irn_verify_irg(const ir_node *checknode, ir_graph *irg);
/**
* Same as irn_verify_irg, but temporary sets verification mode to
* NODE_VERIFICATION_ERROR_ONLY.
* @return NON-zero on success
*/
FIRM_API int irn_verify_irg_dump(const ir_node *checknode, ir_graph *irg,
const char **bad_string);
/**
* Flags for irg_verify().
*/
typedef enum irg_verify_flags_t {
VERIFY_NORMAL = 0, /**< check SSA property only if dominance information is available */
VERIFY_ENFORCE_SSA = 1 /**< check SSA property by enforcing the dominance information recalculation */
} irg_verify_flags_t;
/**
* Calls irn_verify() for each node in irg.
* Graph must be in state "op_pin_state_pinned".
*
* @param irg the IR-graph t check
* @param flags one of irg_verify_flags_t
* Calls irn_verify() for each node in irg. Also checks some global properties
* like all (non-phi) operands dominating their points of usage; Also checks
* if the control flow parts of a graph are valid.
*
* @return NON-zero on success.
*/
FIRM_API int irg_verify(ir_graph *irg, unsigned flags);
/**
* Possible flags for irg_verify_bads().
* @param irg the IR-graph to check
* @return NON-zero if no problems were found
*/
enum verify_bad_flags_t {
BAD_CF = 1, /**< Bad nodes are allowed as predecessors of Blocks and Phis. */
BAD_DF = 2, /**< Bad nodes are allowed as dataflow predecessors. */
BAD_BLOCK = 4, /**< Bad nodes are allowed as Block input. */
TUPLE = 8 /**< Tuple nodes are allowed. */
};
FIRM_API int irg_verify(ir_graph *irg);
/**
* Verify occurrence of bad nodes in a graph.
*
* @param irg The graph to verify
* @param flags combination of verify_bad_flags_t flags describing
* which Bads are allowed
* @returns a value combined of verify_bad_flags_t indicating the problems found.
* Checks graph for errors, in case of error the graph is dumped and the
* aborted. This is a convenience function for irg_verify().
*/
FIRM_API int irg_verify_bads(ir_graph *irg, int flags);
FIRM_API void irg_assert_verify(ir_graph *irg);
/** @} */
......
......@@ -536,7 +536,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
/* Verify the initial graph */
if (be_options.do_verify) {
be_timer_push(T_VERIFY);
irg_verify(irg, VERIFY_ENFORCE_SSA);
irg_assert_verify(irg);
be_timer_pop(T_VERIFY);
}
......
......@@ -1090,7 +1090,7 @@ ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
for (i = 0; i < n_ins; ++i) {
info->in_reqs[i] = req;
}
irn_verify_irg(phi, irg);
verify_new_node(irg, phi);
phi = optimize_node(phi);
return phi;
}
......
......@@ -425,7 +425,7 @@ EOF
$temp .= <<EOF;
/* optimize node */
res = optimize_node(res);
irn_verify_irg(res, irg);
verify_new_node(irg, res);
return res;
EOF
......
......@@ -65,7 +65,7 @@ ir_node *new_rd_ASM(dbg_info *db, ir_node *block, ir_node *mem,
memcpy(res->attr.assem.output_constraints, outputs, sizeof(outputs[0]) * n_outs);
memcpy(res->attr.assem.clobbers, clobber, sizeof(clobber[0]) * n_clobber);
irn_verify_irg(res, irg);
verify_new_node(irg, res);
res = optimize_node(res);
return res;
}
......@@ -84,7 +84,7 @@ ir_node *new_rd_SymConst(dbg_info *db, ir_graph *irg, ir_mode *mode,
res->attr.symc.kind = symkind;
res->attr.symc.sym = value;
irn_verify_irg(res, irg);
verify_new_node(irg, res);
res = optimize_node(res);
return res;
}
......@@ -146,7 +146,7 @@ static inline ir_node *new_rd_Phi0(dbg_info *dbgi, ir_node *block,
ir_graph *irg = get_irn_irg(block);
ir_node *res = new_ir_node(dbgi, irg, block, op_Phi, mode, 0, NULL);
res->attr.phi.u.pos = pos;
irn_verify_irg(res, irg);
verify_new_node(irg, res);
return res;
}
......@@ -220,7 +220,7 @@ static ir_node *set_phi_arguments(ir_node *phi, int pos)
phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), arity);
set_irn_in(phi, arity, in);
irn_verify_irg(phi, irg);
verify_new_node(irg, phi);
try_remove_unnecessary_phi(phi);
return phi;
......@@ -335,7 +335,7 @@ void mature_immBlock(ir_node *block)
nodes refer to the unoptimized node.
We can call optimize_in_place_2(), as global cse has no effect on blocks.
*/
irn_verify_irg(block, irg);
verify_new_node(irg, block);
optimize_in_place_2(block);
}
......@@ -384,7 +384,7 @@ ir_node *new_rd_DivRL(dbg_info *dbgi, ir_node *block, ir_node * irn_mem, ir_node
res->attr.div.resmode = resmode;
res->attr.div.no_remainder = 1;
res->attr.div.exc.pin_state = pin_state;
irn_verify_irg(res, irg);
verify_new_node(irg, res);
res = optimize_node(res);
return res;
}
......@@ -427,7 +427,7 @@ ir_node *new_rd_immBlock(dbg_info *dbgi, ir_graph *irg)
res->attr.block.graph_arr = NEW_ARR_DZ(ir_node*, get_irg_obstack(irg), irg->n_loc);
/* Immature block may not be optimized! */
irn_verify_irg(res, irg);
verify_new_node(irg, res);
return res;
}
......@@ -699,6 +699,6 @@ ir_node *new_r_Block_noopt(ir_graph *irg, int arity, ir_node *in[])
if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION)) {
res->attr.block.graph_arr = NEW_ARR_DZ(ir_node*, get_irg_obstack(irg), irg->n_loc);
}
irn_verify_irg(res, irg);
verify_new_node(irg, res);
return res;
}
......@@ -12,8 +12,11 @@
#ifndef FIRM_IR_IRCONS_T_H
#define FIRM_IR_IRCONS_T_H
#include <assert.h>
#include "ircons.h"
#include "irgraph_t.h"
#include "irverify_t.h"
#include "compiler.h"
#define get_cur_block() _get_cur_block()
......@@ -22,6 +25,14 @@ static inline ir_node *_get_cur_block(void)
return current_ir_graph->current_block;
}
static inline void verify_new_node(ir_graph *irg, ir_node *node)
{
#ifdef DEBUG_libfirm
if (UNLIKELY(!irn_verify_irg(node, irg)))
abort();
#endif
}
/**
* Creates a new Anchor node.
*/
......
......@@ -1111,17 +1111,6 @@ static void dump_const_block_local(FILE *F, const ir_node *n)
}
}
/**
* prints the error message of a node to a file F as info2.
*/
static void print_node_error(FILE *F, const char *err_msg)
{
if (! err_msg)
return;
fprintf(F, " info2: \"%s\"", err_msg);
}
/**
* prints debug messages of a node to file F as info3.
*/
......@@ -1147,10 +1136,6 @@ static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
*/
void dump_node(FILE *F, const ir_node *n)
{
int bad = 0;
const char *p;
ir_graph *irg;
if (get_opt_dump_const_local() && is_constlike_node(n))
return;
......@@ -1159,15 +1144,12 @@ void dump_node(FILE *F, const ir_node *n)
print_nodeid(F, n);
fputs(" label: \"", F);
irg = get_irn_irg(n);
bad = ! irn_verify_irg_dump(n, irg, &p);
dump_node_label(F, n);
fputs("\" ", F);
dump_node_info(F, n);
print_node_error(F, p);
print_dbg_info(F, get_irn_dbg_info(n));
dump_node_vcgattr(F, n, NULL, bad);
dump_node_vcgattr(F, n, NULL, 0);
fputs("}\n", F);
dump_const_node_local(F, n);
......
......@@ -6763,7 +6763,7 @@ ir_node *optimize_in_place_2(ir_node *n)
#ifdef DEBUG_libfirm
/* Now we can verify the node, as it has no dead inputs any more. */
irn_verify(n);
assert(irn_verify(n));
#endif
/* Now we have a legal, useful node. Enter it in hash table for cse.
......
This diff is collapsed.
......@@ -11,36 +11,7 @@
#ifndef FIRM_IR_IRVERIFY_T_H
#define FIRM_IR_IRVERIFY_T_H
#include "irflag_t.h"
#include "irverify.h"
#include "irdump.h"
#include "beutil.h"
extern const char *firm_verify_failure_msg;
#define ASSERT_AND_RET(expr, string, ret) \
do { \
if (!(expr) && current_ir_graph != get_const_code_irg()) \
dump_ir_graph(current_ir_graph, "assert"); \
assert((expr) && string); \
if (!(expr)) { \
firm_verify_failure_msg = #expr " && " string; \
return (ret); \
} \
} while(0)
#define ASSERT_AND_RET_DBG(expr, string, ret, blk) \
do { \
if (!(expr)) { \
firm_verify_failure_msg = #expr " && " string; \
blk \
if (!(expr) && current_ir_graph != get_const_code_irg()) \
dump_ir_graph(current_ir_graph, "assert"); \
assert((expr) && string); \
return (ret); \
} \
} while(0)
/**
* Set the default verify_node and verify_proj_node operations.
......
......@@ -22,13 +22,6 @@
#include "irgopt.h"
{% endif %}
static void verify_new_node(ir_graph *irg, ir_node *node)
{
#ifdef DEBUG_libfirm
irn_verify_irg(node, irg);
#endif
}
{% if spec.external %}
static unsigned {{spec.name}}_opcode_start;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment