REE: fix uninitialized registers handling

gcc/ChangeLog:

	PR rtl-optimization/66790
	* df.h (DF_MIR): New macro.
	(DF_LAST_PROBLEM_PLUS1): Update to be past DF_MIR
	(DF_MIR_INFO_BB): New macro.
	(DF_MIR_IN, DF_MIR_OUT): New macros.
	(struct df_mir_bb_info): New.
	(df_mir): New macro.
	(df_mir_add_problem, df_mir_simulate_one_insn): New forward
	declarations.
	(df_mir_get_bb_info): New.
	* df-problems.c (struct df_mir_problem_data): New.
	(df_mir_free_bb_info, df_mir_alloc, df_mir_reset,
	df_mir_bb_local_compute, df_mir_local_compute, df_mir_init,
	df_mir_confluence_0, df_mir_confluence_n,
	df_mir_transfer_function, df_mir_free, df_mir_top_dump,
	df_mir_bottom_dump, df_mir_verify_solution_start,
	df_mir_verify_solution_end): New.
	(problem_MIR): New.
	(df_mir_add_problem, df_mir_simulate_one_insn): New.
	* timevar.def (TV_DF_MIR): New.
	* ree.c: Include bitmap.h
	(add_removable_extension): Add an INIT_REGS parameter.  Use it
	to skip zero-extensions that may get an uninitialized register.
	(find_removable_extensions): Compute must-initialized registers
	using the MIR dataflow problem. Update the call to
	add_removable_extension.
	(find_and_remove_re): Call df_mir_add_problem.

gcc/testsuite/ChangeLog:

	* gnat.dg/opt50.adb: New test.
	* gnat.dg/opt50_pkg.adb: New helper.
	* gnat.dg/opt50_pkg.ads: New helper.

From-SVN: r229008
This commit is contained in:
Pierre-Marie de Rodat 2015-10-19 23:47:35 +00:00 committed by Pierre-Marie de Rodat
parent 32308c8db4
commit 524d9b4b90
9 changed files with 605 additions and 14 deletions

View File

@ -1,3 +1,33 @@
2015-10-19 Pierre-Marie de Rodat <derodat@adacore.com>
PR rtl-optimization/66790
* df.h (DF_MIR): New macro.
(DF_LAST_PROBLEM_PLUS1): Update to be past DF_MIR
(DF_MIR_INFO_BB): New macro.
(DF_MIR_IN, DF_MIR_OUT): New macros.
(struct df_mir_bb_info): New.
(df_mir): New macro.
(df_mir_add_problem, df_mir_simulate_one_insn): New forward
declarations.
(df_mir_get_bb_info): New.
* df-problems.c (struct df_mir_problem_data): New.
(df_mir_free_bb_info, df_mir_alloc, df_mir_reset,
df_mir_bb_local_compute, df_mir_local_compute, df_mir_init,
df_mir_confluence_0, df_mir_confluence_n,
df_mir_transfer_function, df_mir_free, df_mir_top_dump,
df_mir_bottom_dump, df_mir_verify_solution_start,
df_mir_verify_solution_end): New.
(problem_MIR): New.
(df_mir_add_problem, df_mir_simulate_one_insn): New.
* timevar.def (TV_DF_MIR): New.
* ree.c: Include bitmap.h
(add_removable_extension): Add an INIT_REGS parameter. Use it
to skip zero-extensions that may get an uninitialized register.
(find_removable_extensions): Compute must-initialized registers
using the MIR dataflow problem. Update the call to
add_removable_extension.
(find_and_remove_re): Call df_mir_add_problem.
2015-10-19 Segher Boessenkool <segher@kernel.crashing.org>
* common/config/mn10300/mn10300-common.c

View File

@ -1848,6 +1848,409 @@ df_live_verify_transfer_functions (void)
bitmap_clear (&all_blocks);
}
/*----------------------------------------------------------------------------
MUST-INITIALIZED REGISTERS.
----------------------------------------------------------------------------*/
/* Private data used to verify the solution for this problem. */
struct df_mir_problem_data
{
bitmap_head *in;
bitmap_head *out;
/* An obstack for the bitmaps we need for this problem. */
bitmap_obstack mir_bitmaps;
};
/* Free basic block info. */
static void
df_mir_free_bb_info (basic_block bb ATTRIBUTE_UNUSED,
void *vbb_info)
{
struct df_mir_bb_info *bb_info = (struct df_mir_bb_info *) vbb_info;
if (bb_info)
{
bitmap_clear (&bb_info->gen);
bitmap_clear (&bb_info->kill);
bitmap_clear (&bb_info->in);
bitmap_clear (&bb_info->out);
}
}
/* Allocate or reset bitmaps for DF_MIR blocks. The solution bits are
not touched unless the block is new. */
static void
df_mir_alloc (bitmap all_blocks)
{
unsigned int bb_index;
bitmap_iterator bi;
struct df_mir_problem_data *problem_data;
if (df_mir->problem_data)
problem_data = (struct df_mir_problem_data *) df_mir->problem_data;
else
{
problem_data = XNEW (struct df_mir_problem_data);
df_mir->problem_data = problem_data;
problem_data->out = NULL;
problem_data->in = NULL;
bitmap_obstack_initialize (&problem_data->mir_bitmaps);
}
df_grow_bb_info (df_mir);
EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index);
/* When bitmaps are already initialized, just clear them. */
if (bb_info->kill.obstack)
{
bitmap_clear (&bb_info->kill);
bitmap_clear (&bb_info->gen);
}
else
{
bitmap_initialize (&bb_info->kill, &problem_data->mir_bitmaps);
bitmap_initialize (&bb_info->gen, &problem_data->mir_bitmaps);
bitmap_initialize (&bb_info->in, &problem_data->mir_bitmaps);
bitmap_initialize (&bb_info->out, &problem_data->mir_bitmaps);
bitmap_set_range (&bb_info->in, 0, DF_REG_SIZE (df));
bitmap_set_range (&bb_info->out, 0, DF_REG_SIZE (df));
}
}
df_mir->optional_p = 1;
}
/* Reset the global solution for recalculation. */
static void
df_mir_reset (bitmap all_blocks)
{
unsigned int bb_index;
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index);
gcc_assert (bb_info);
bitmap_clear (&bb_info->in);
bitmap_set_range (&bb_info->in, 0, DF_REG_SIZE (df));
bitmap_clear (&bb_info->out);
bitmap_set_range (&bb_info->out, 0, DF_REG_SIZE (df));
}
}
/* Compute local uninitialized register info for basic block BB. */
static void
df_mir_bb_local_compute (unsigned int bb_index)
{
basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index);
rtx_insn *insn;
int luid = 0;
/* Ignoring artificial defs is intentional: these often pretend that some
registers carry incoming arguments (when they are FUNCTION_ARG_REGNO) even
though they are not used for that. As a result, conservatively assume
they may be uninitialized. */
FOR_BB_INSNS (bb, insn)
{
unsigned int uid = INSN_UID (insn);
struct df_insn_info *insn_info = DF_INSN_UID_GET (uid);
/* Inserting labels does not always trigger the incremental
rescanning. */
if (!insn_info)
{
gcc_assert (!INSN_P (insn));
insn_info = df_insn_create_insn_record (insn);
}
DF_INSN_INFO_LUID (insn_info) = luid;
if (!INSN_P (insn))
continue;
luid++;
df_mir_simulate_one_insn (bb, insn, &bb_info->kill, &bb_info->gen);
}
}
/* Compute local uninitialized register info. */
static void
df_mir_local_compute (bitmap all_blocks)
{
unsigned int bb_index;
bitmap_iterator bi;
df_grow_insn_info ();
EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{
df_mir_bb_local_compute (bb_index);
}
}
/* Initialize the solution vectors. */
static void
df_mir_init (bitmap all_blocks)
{
df_mir_reset (all_blocks);
}
/* Initialize IN sets for blocks with no predecessors: when landing on such
blocks, assume all registers are uninitialized. */
static void
df_mir_confluence_0 (basic_block bb)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index);
bitmap_clear (&bb_info->in);
}
/* Forward confluence function that ignores fake edges. */
static bool
df_mir_confluence_n (edge e)
{
bitmap op1 = &df_mir_get_bb_info (e->dest->index)->in;
bitmap op2 = &df_mir_get_bb_info (e->src->index)->out;
if (e->flags & EDGE_FAKE)
return false;
/* A register is must-initialized at the entry of a basic block iff it is
must-initialized at the exit of all the predecessors. */
return bitmap_and_into (op1, op2);
}
/* Transfer function for the forwards must-initialized problem. */
static bool
df_mir_transfer_function (int bb_index)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index);
bitmap in = &bb_info->in;
bitmap out = &bb_info->out;
bitmap gen = &bb_info->gen;
bitmap kill = &bb_info->kill;
return bitmap_ior_and_compl (out, gen, in, kill);
}
/* Free all storage associated with the problem. */
static void
df_mir_free (void)
{
struct df_mir_problem_data *problem_data
= (struct df_mir_problem_data *) df_mir->problem_data;
if (df_mir->block_info)
{
df_mir->block_info_size = 0;
free (df_mir->block_info);
df_mir->block_info = NULL;
bitmap_obstack_release (&problem_data->mir_bitmaps);
free (problem_data);
df_mir->problem_data = NULL;
}
free (df_mir);
}
/* Debugging info at top of bb. */
static void
df_mir_top_dump (basic_block bb, FILE *file)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index);
if (!bb_info)
return;
fprintf (file, ";; mir in \t");
df_print_regset (file, &bb_info->in);
fprintf (file, ";; mir kill\t");
df_print_regset (file, &bb_info->kill);
fprintf (file, ";; mir gen \t");
df_print_regset (file, &bb_info->gen);
}
/* Debugging info at bottom of bb. */
static void
df_mir_bottom_dump (basic_block bb, FILE *file)
{
struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index);
if (!bb_info)
return;
fprintf (file, ";; mir out \t");
df_print_regset (file, &bb_info->out);
}
/* Build the datastructure to verify that the solution to the dataflow
equations is not dirty. */
static void
df_mir_verify_solution_start (void)
{
basic_block bb;
struct df_mir_problem_data *problem_data;
if (df_mir->solutions_dirty)
return;
/* Set it true so that the solution is recomputed. */
df_mir->solutions_dirty = true;
problem_data = (struct df_mir_problem_data *) df_mir->problem_data;
problem_data->in = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
problem_data->out = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
bitmap_obstack_initialize (&problem_data->mir_bitmaps);
FOR_ALL_BB_FN (bb, cfun)
{
bitmap_initialize (&problem_data->in[bb->index], &problem_data->mir_bitmaps);
bitmap_initialize (&problem_data->out[bb->index], &problem_data->mir_bitmaps);
bitmap_copy (&problem_data->in[bb->index], DF_MIR_IN (bb));
bitmap_copy (&problem_data->out[bb->index], DF_MIR_OUT (bb));
}
}
/* Compare the saved datastructure and the new solution to the dataflow
equations. */
static void
df_mir_verify_solution_end (void)
{
struct df_mir_problem_data *problem_data;
basic_block bb;
problem_data = (struct df_mir_problem_data *) df_mir->problem_data;
if (!problem_data->out)
return;
FOR_ALL_BB_FN (bb, cfun)
{
if ((!bitmap_equal_p (&problem_data->in[bb->index], DF_MIR_IN (bb)))
|| (!bitmap_equal_p (&problem_data->out[bb->index], DF_MIR_OUT (bb))))
gcc_unreachable ();
}
/* Cannot delete them immediately because you may want to dump them
if the comparison fails. */
FOR_ALL_BB_FN (bb, cfun)
{
bitmap_clear (&problem_data->in[bb->index]);
bitmap_clear (&problem_data->out[bb->index]);
}
free (problem_data->in);
free (problem_data->out);
bitmap_obstack_release (&problem_data->mir_bitmaps);
free (problem_data);
df_mir->problem_data = NULL;
}
/* All of the information associated with every instance of the problem. */
static struct df_problem problem_MIR =
{
DF_MIR, /* Problem id. */
DF_FORWARD, /* Direction. */
df_mir_alloc, /* Allocate the problem specific data. */
df_mir_reset, /* Reset global information. */
df_mir_free_bb_info, /* Free basic block info. */
df_mir_local_compute, /* Local compute function. */
df_mir_init, /* Init the solution specific data. */
df_worklist_dataflow, /* Worklist solver. */
df_mir_confluence_0, /* Confluence operator 0. */
df_mir_confluence_n, /* Confluence operator n. */
df_mir_transfer_function, /* Transfer function. */
NULL, /* Finalize function. */
df_mir_free, /* Free all of the problem information. */
df_mir_free, /* Remove this problem from the stack of dataflow problems. */
NULL, /* Debugging. */
df_mir_top_dump, /* Debugging start block. */
df_mir_bottom_dump, /* Debugging end block. */
NULL, /* Debugging start insn. */
NULL, /* Debugging end insn. */
df_mir_verify_solution_start, /* Incremental solution verify start. */
df_mir_verify_solution_end, /* Incremental solution verify end. */
NULL, /* Dependent problem. */
sizeof (struct df_mir_bb_info),/* Size of entry of block_info array. */
TV_DF_MIR, /* Timing variable. */
false /* Reset blocks on dropping out of blocks_to_analyze. */
};
/* Create a new DATAFLOW instance and add it to an existing instance
of DF. */
void
df_mir_add_problem (void)
{
df_add_problem (&problem_MIR);
/* These will be initialized when df_scan_blocks processes each
block. */
df_mir->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack);
}
/* Apply the effects of the gen/kills in INSN to the corresponding bitmaps. */
void
df_mir_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx_insn *insn,
bitmap kill, bitmap gen)
{
df_ref def;
FOR_EACH_INSN_DEF (def, insn)
{
unsigned int regno = DF_REF_REGNO (def);
/* The order of GENs/KILLs matters, so if this def clobbers a reg, any
previous gen is irrelevant (and reciprocally). Also, claim that a
register is GEN only if it is in all cases. */
if (DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
{
bitmap_set_bit (kill, regno);
bitmap_clear_bit (gen, regno);
}
/* In the worst case, partial and conditional defs can leave bits
uninitialized, so assume they do not change anything. */
else if (!DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL | DF_REF_CONDITIONAL))
{
bitmap_set_bit (gen, regno);
bitmap_clear_bit (kill, regno);
}
}
}
/*----------------------------------------------------------------------------
CREATE DEF_USE (DU) and / or USE_DEF (UD) CHAINS

View File

@ -51,8 +51,9 @@ union df_ref_d;
#define DF_WORD_LR 5 /* Subreg tracking lr. */
#define DF_NOTE 6 /* REG_DEAD and REG_UNUSED notes. */
#define DF_MD 7 /* Multiple Definitions. */
#define DF_MIR 8 /* Must-initialized Registers. */
#define DF_LAST_PROBLEM_PLUS1 (DF_MD + 1)
#define DF_LAST_PROBLEM_PLUS1 (DF_MIR + 1)
/* Dataflow direction. */
enum df_flow_dir
@ -612,12 +613,16 @@ struct df_d
#define DF_LIVE_BB_INFO(BB) (df_live_get_bb_info ((BB)->index))
#define DF_WORD_LR_BB_INFO(BB) (df_word_lr_get_bb_info ((BB)->index))
#define DF_MD_BB_INFO(BB) (df_md_get_bb_info ((BB)->index))
#define DF_MIR_BB_INFO(BB) (df_mir_get_bb_info ((BB)->index))
/* Most transformations that wish to use live register analysis will
use these macros. This info is the and of the lr and live sets. */
#define DF_LIVE_IN(BB) (&DF_LIVE_BB_INFO (BB)->in)
#define DF_LIVE_OUT(BB) (&DF_LIVE_BB_INFO (BB)->out)
#define DF_MIR_IN(BB) (&DF_MIR_BB_INFO (BB)->in)
#define DF_MIR_OUT(BB) (&DF_MIR_BB_INFO (BB)->out)
/* These macros are used by passes that are not tolerant of
uninitialized variables. This intolerance should eventually
be fixed. */
@ -896,6 +901,21 @@ struct df_word_lr_bb_info
bitmap_head out; /* At the bottom of the block. */
};
/* Must-initialized registers. All bitmaps are referenced by the
register number. */
struct df_mir_bb_info
{
/* Local sets to describe the basic blocks. */
bitmap_head kill; /* The set of registers unset in this block. Calls,
for instance, unset registers. */
bitmap_head gen; /* The set of registers set in this block, excluding the
ones killed later on in this block. */
/* The results of the dataflow problem. */
bitmap_head in; /* At the top of the block. */
bitmap_head out; /* At the bottom of the block. */
};
/* This is used for debugging and for the dumpers to find the latest
instance so that the df info can be added to the dumps. This
@ -909,6 +929,7 @@ extern struct df_d *df;
#define df_word_lr (df->problems_by_index[DF_WORD_LR])
#define df_note (df->problems_by_index[DF_NOTE])
#define df_md (df->problems_by_index[DF_MD])
#define df_mir (df->problems_by_index[DF_MIR])
/* This symbol turns on checking that each modification of the cfg has
been identified to the appropriate df routines. It is not part of
@ -1005,6 +1026,8 @@ extern void df_note_add_problem (void);
extern void df_md_add_problem (void);
extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
extern void df_md_simulate_one_insn (basic_block, rtx_insn *, bitmap);
extern void df_mir_add_problem (void);
extern void df_mir_simulate_one_insn (basic_block, rtx_insn *, bitmap, bitmap);
extern void df_simulate_find_noclobber_defs (rtx_insn *, bitmap);
extern void df_simulate_find_defs (rtx_insn *, bitmap);
extern void df_simulate_defs (rtx_insn *, bitmap);
@ -1111,6 +1134,15 @@ df_word_lr_get_bb_info (unsigned int index)
return NULL;
}
static inline struct df_mir_bb_info *
df_mir_get_bb_info (unsigned int index)
{
if (index < df_mir->block_info_size)
return &((struct df_mir_bb_info *) df_mir->block_info)[index];
else
return NULL;
}
/* Get the live at out set for BB no matter what problem happens to be
defined. This function is used by the register allocators who
choose different dataflow problems depending on the optimization

View File

@ -246,6 +246,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-pass.h"
#include "cgraph.h"
#include "bitmap.h"
/* This structure represents a candidate for elimination. */
@ -973,7 +974,8 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
static void
add_removable_extension (const_rtx expr, rtx_insn *insn,
vec<ext_cand> *insn_list,
unsigned *def_map)
unsigned *def_map,
bitmap init_regs)
{
enum rtx_code code;
machine_mode mode;
@ -993,11 +995,29 @@ add_removable_extension (const_rtx expr, rtx_insn *insn,
&& (code == SIGN_EXTEND || code == ZERO_EXTEND)
&& REG_P (XEXP (src, 0)))
{
rtx reg = XEXP (src, 0);
struct df_link *defs, *def;
ext_cand *cand;
/* First, make sure we can get all the reaching definitions. */
defs = get_defs (insn, XEXP (src, 0), NULL);
/* Zero-extension of an undefined value is partly defined (it's
completely undefined for sign-extension, though). So if there exists
a path from the entry to this zero-extension that leaves this register
uninitialized, removing the extension could change the behavior of
correct programs. So first, check it is not the case. */
if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))
{
if (dump_file)
{
fprintf (dump_file, "Cannot eliminate extension:\n");
print_rtl_single (dump_file, insn);
fprintf (dump_file, " because it can operate on uninitialized"
" data\n");
}
return;
}
/* Second, make sure we can get all the reaching definitions. */
defs = get_defs (insn, reg, NULL);
if (!defs)
{
if (dump_file)
@ -1009,7 +1029,7 @@ add_removable_extension (const_rtx expr, rtx_insn *insn,
return;
}
/* Second, make sure the reaching definitions don't feed another and
/* Third, make sure the reaching definitions don't feed another and
different extension. FIXME: this obviously can be improved. */
for (def = defs; def; def = def->next)
if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
@ -1099,18 +1119,33 @@ find_removable_extensions (void)
rtx_insn *insn;
rtx set;
unsigned *def_map = XCNEWVEC (unsigned, max_insn_uid);
bitmap_head init, kill, gen, tmp;
bitmap_initialize (&init, NULL);
bitmap_initialize (&kill, NULL);
bitmap_initialize (&gen, NULL);
bitmap_initialize (&tmp, NULL);
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
{
if (!NONDEBUG_INSN_P (insn))
continue;
{
bitmap_copy (&init, DF_MIR_IN (bb));
bitmap_clear (&kill);
bitmap_clear (&gen);
set = single_set (insn);
if (set == NULL_RTX)
continue;
add_removable_extension (set, insn, &insn_list, def_map);
}
FOR_BB_INSNS (bb, insn)
{
if (NONDEBUG_INSN_P (insn))
{
set = single_set (insn);
if (set != NULL_RTX)
add_removable_extension (set, insn, &insn_list, def_map,
&init);
df_mir_simulate_one_insn (bb, insn, &kill, &gen);
bitmap_ior_and_compl (&tmp, &gen, &init, &kill);
bitmap_copy (&init, &tmp);
}
}
}
XDELETEVEC (def_map);
@ -1135,6 +1170,7 @@ find_and_remove_re (void)
extension instruction. */
df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
df_mir_add_problem ();
df_analyze ();
df_set_flags (DF_DEFER_INSN_RESCAN);

View File

@ -1,3 +1,9 @@
2015-10-19 Pierre-Marie de Rodat <derodat@adacore.com>
* gnat.dg/opt50.adb: New test.
* gnat.dg/opt50_pkg.adb: New helper.
* gnat.dg/opt50_pkg.ads: New helper.
2015-10-19 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/68019

View File

@ -0,0 +1,23 @@
-- { dg-do run }
-- { dg-options "-O3 -gnatn" }
with Opt50_Pkg; use Opt50_Pkg;
procedure Opt50 is
B : Boolean;
E : Enum;
begin
Get ("four", E, B);
if B = True then
raise Program_Error;
end if;
Get ("three", E, B);
if B = False then
raise Program_Error;
end if;
declare
A : Enum_Boolean_Array (One .. E) := (others => True);
begin
Set (A);
end;
end Opt50;

View File

@ -0,0 +1,48 @@
with Ada.Characters.Handling;
with Ada.Containers;
with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings.Hash;
package body Opt50_Pkg is
type Enum_Name is array (Enum) of access constant String;
Enum_Name_Table : constant Enum_Name := (
One => new String'("one"),
Two => new String'("two"),
Three => new String'("three"));
package String_To_Enum_Map is new Ada.Containers.Indefinite_Hashed_Maps
(Key_Type => String, Element_Type => Enum,
Hash => Ada.Strings.Hash, Equivalent_Keys => "=");
function Fill_Hashed_Map return String_To_Enum_Map.Map is
Res : String_To_Enum_Map.Map;
use String_To_Enum_Map;
begin
for I in Enum_Name_Table'Range loop
declare
Kind : constant String := Enum_Name_Table (I).all;
begin
Res.Insert(Key => Kind, New_Item => I);
end;
end loop;
return Res;
end;
String_To_Enum : constant String_To_Enum_Map.Map := Fill_Hashed_Map;
procedure Get (Kind : String; Result : out Enum; Success : out Boolean) is
X : constant String := Ada.Characters.Handling.To_Lower (Kind);
use String_To_Enum_Map;
Curs : constant Cursor := String_To_Enum.Find (X);
begin
Success := Curs /= No_Element;
if Success then
Result := Element(Curs);
end if;
end;
procedure Set (A : Enum_Boolean_Array) is null;
end Opt50_Pkg;

View File

@ -0,0 +1,12 @@
package Opt50_Pkg is
type Enum is (One, Two, Three);
for Enum'Size use 16;
type Enum_Boolean_Array is array (Enum range <>) of Boolean;
procedure Get (Kind : String; Result : out Enum; Success : out Boolean);
procedure Set (A : Enum_Boolean_Array);
end Opt50_Pkg;

View File

@ -115,6 +115,7 @@ DEFTIMEVAR (TV_DF_MD , "df multiple defs")
DEFTIMEVAR (TV_DF_RD , "df reaching defs")
DEFTIMEVAR (TV_DF_LR , "df live regs")
DEFTIMEVAR (TV_DF_LIVE , "df live&initialized regs")
DEFTIMEVAR (TV_DF_MIR , "df must-initialized regs")
DEFTIMEVAR (TV_DF_CHAIN , "df use-def / def-use chains")
DEFTIMEVAR (TV_DF_WORD_LR , "df live reg subwords")
DEFTIMEVAR (TV_DF_NOTE , "df reg dead/unused notes")