@@ -100,14 +100,16 @@ insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op)
else
gsi_insert_before (si_p, seq, GSI_NEW_STMT);
- /* The iterator points to the __builtin_trap. Advance the iterator
- and delete everything else in the block. */
- gsi_next (si_p);
- for (; !gsi_end_p (*si_p);)
+ /* We must remove statements from the end of the block so that we
+ never reference a released SSA_NAME. */
+ basic_block bb = gimple_bb (gsi_stmt (*si_p));
+ for (gimple_stmt_iterator si = gsi_last_bb (bb);
+ gsi_stmt (si) != gsi_stmt (*si_p);
+ si = gsi_last_bb (bb))
{
- stmt = gsi_stmt (*si_p);
+ stmt = gsi_stmt (si);
unlink_stmt_vdef (stmt);
- gsi_remove (si_p, true);
+ gsi_remove (&si, true);
release_defs (stmt);
}
}
@@ -192,40 +194,19 @@ isolate_path (basic_block bb, basic_block duplicate,
return duplicate;
}
-/* Search the function for statements which, if executed, would cause
- the program to fault such as a dereference of a NULL pointer.
-
- Such a program can't be valid if such a statement was to execute
- according to ISO standards.
-
- We detect explicit NULL pointer dereferences as well as those implied
- by a PHI argument having a NULL value which unconditionally flows into
- a dereference in the same block as the PHI.
-
- In the former case we replace the offending statement with an
- unconditional trap and eliminate the outgoing edges from the statement's
- basic block. This may expose secondary optimization opportunities.
-
- In the latter case, we isolate the path(s) with the NULL PHI
- feeding the dereference. We can then replace the offending statement
- and eliminate the outgoing edges in the duplicate. Again, this may
- expose secondary optimization opportunities.
+/* Look for PHI nodes which feed statements in the same block where
+ the value of the PHI node implies the statement is erroneous.
- A warning for both cases may be advisable as well.
+ For example, a NULL PHI arg value which then feeds a pointer
+ dereference.
- Other statically detectable violations of the ISO standard could be
- handled in a similar way, such as out-of-bounds array indexing. */
-
-static unsigned int
-gimple_ssa_isolate_erroneous_paths (void)
+ When found isolate and optimize the path associated with the PHI
+ argument feeding the erroneous statement. */
+static void
+find_implicit_erroneous_behaviour (void)
{
basic_block bb;
- initialize_original_copy_tables ();
-
- /* Search all the blocks for edges which, if traversed, will
- result in undefined behaviour. */
- cfg_altered = false;
FOR_EACH_BB (bb)
{
gimple_stmt_iterator si;
@@ -288,6 +269,21 @@ gimple_ssa_isolate_erroneous_paths (void)
}
}
}
+ }
+}
+
+/* Look for statements which exhibit erroneous behaviour. For example
+ a NULL pointer dereference.
+
+ When found, optimize the block containing the erroneous behaviour. */
+static void
+find_explicit_erroneous_behaviour (void)
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator si;
/* Now look at the statements in the block and see if any of
them explicitly dereference a NULL pointer. This happens
@@ -318,6 +314,56 @@ gimple_ssa_isolate_erroneous_paths (void)
}
}
}
+}
+/* Search the function for statements which, if executed, would cause
+ the program to fault such as a dereference of a NULL pointer.
+
+ Such a program can't be valid if such a statement was to execute
+ according to ISO standards.
+
+ We detect explicit NULL pointer dereferences as well as those implied
+ by a PHI argument having a NULL value which unconditionally flows into
+ a dereference in the same block as the PHI.
+
+ In the former case we replace the offending statement with an
+ unconditional trap and eliminate the outgoing edges from the statement's
+ basic block. This may expose secondary optimization opportunities.
+
+ In the latter case, we isolate the path(s) with the NULL PHI
+ feeding the dereference. We can then replace the offending statement
+ and eliminate the outgoing edges in the duplicate. Again, this may
+ expose secondary optimization opportunities.
+
+ A warning for both cases may be advisable as well.
+
+ Other statically detectable violations of the ISO standard could be
+ handled in a similar way, such as out-of-bounds array indexing. */
+
+static unsigned int
+gimple_ssa_isolate_erroneous_paths (void)
+{
+ initialize_original_copy_tables ();
+
+ /* Search all the blocks for edges which, if traversed, will
+ result in undefined behaviour. */
+ cfg_altered = false;
+
+ /* First handle cases where traversal of a particular edge
+ triggers undefined behaviour. These cases require creating
+ duplicate blocks and thus new SSA_NAMEs.
+
+ We want that process complete prior to the phase where we start
+ removing edges from the CFG. Edge removal may ultimately result in
+ removal of PHI nodes and thus releasing SSA_NAMEs back to the
+ name manager.
+
+ If the two processes run in parallel we could release an SSA_NAME
+ back to the manager but we could still have dangling references
+ to the released SSA_NAME in unreachable blocks.
+ that any released names not have dangling references in the IL. */
+ find_implicit_erroneous_behaviour ();
+ find_explicit_erroneous_behaviour ();
+
free_original_copy_tables ();
/* We scramble the CFG and loop structures a bit, clean up
new file mode 100644
@@ -0,0 +1,23 @@
+extern void *memmove (void *, const void *, __SIZE_TYPE__);
+extern void *memset (void *, int, __SIZE_TYPE__);
+
+typedef struct {
+ long n_prefix;
+ long n_spadding;
+} NumberFieldWidths;
+
+void
+fill_number(char *buf, const NumberFieldWidths *spec)
+{
+ if (spec->n_prefix) {
+ memmove(buf,
+ (char *) 0,
+ spec->n_prefix * sizeof(char));
+ buf += spec->n_prefix;
+ }
+ if (spec->n_spadding) {
+ memset(buf, 0, spec->n_spadding);
+ buf += spec->n_spadding;
+ }
+}
+