mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-19 03:13:40 +00:00
083d376e6598628362ee91c2da170febd83590f4
29 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ea4f95a7ed |
Use var_tables in lco.m, and when dumping goals.
Since this is the first converted module that dumps out goals when
debugging trace flags are enabled, this required generalizing the code
that does that, to take either varsets or var_tables as a means of
specifying the names of variables. We do this via a new type,
var_name_source, which contains either a varset or a var_table.
Almost all of this diff is there to implement this generalization.
A large part of it affects code in the parse_tree package that we use
to write out the parts of HLDS goals that are defined by types defined
in that package. Since we want to avoid making any part of the parse_tree
package dependent on the hlds package, this required defining the
var_name_source type in the parse_tree package, which in turn requires
var_table.m to be in that same package.
compiler/lco.m:
Convert this module to use var_tables instead of varsets and vartypes.
compiler/var_table.m:
Move this module from the hlds package to the parse_tree package.
To make this, possible, move the parts that required access to the HLDS
to hlds_pred.m, from where it was usually invoked.
Export some utility predicates to allow the moved code to work
in hlds_pred.m without access to the actual definition of the
var_table type.
Define the var_name_source type.
Add some utility functions for use by code writing out variable names.
compiler/hlds_pred.m:
Add the code moved from var_table.m.
compiler/vartypes.m:
Move this module from the hlds package to the parse_tree package,
for symmetry with var_table.m. It did not depend on being in hlds
in any way.
compiler/hlds.m:
compiler/parse_tree.m:
Move vartypes.m and var_table.m from the hlds package
to the parse_tree package.
compiler/hlds_out_goal.m:
Change all the predicates in this module to take a var_name_source
instead of a prog_varset.
Fix some comments.
compiler/hlds_out_util.m:
Change some of the predicates in this module (those called from
hlds_out_goal.m) to take a var_name_source instead of a prog_varset.
compiler/parse_tree_out_term.m:
Provide variants of some existing predicates and functions that take
var_name_sources instead of varsets. The code of the copies
duplicates the logic of the originals, though I hope that this
duplication can be done away with at the end of the transition.
(The best solution would be to use a typeclass with methods
that convert vars to their names, but we would want to ensure
that the compiler can specialize all the affected predicates
and functions to the two instances of this typeclass, which is
something that we cannot do yet. In the meantime, the lack of
any generalization in the old versions preserves their performance.)
tools/sort_imports:
tools/filter_sort_imports:
A new tool that automatically sorts any occurrences of consecutive
":- import_module" declarations in the named files. The sorting is done
in filter_sort_imports; sort_imports loops over the named files.
After automatically replacing all occurrences of hlds.{vartypes,var_table}
in import_module declarations with their parse_tree versions, the updated
import_module declarations were usually out of order with respect to
their neighbours. I used this script to fix that, and some earlier
out-of-order imports.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_heap_ops.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_trail_ops.m:
compiler/analysis.m:
compiler/arg_info.m:
compiler/build_mode_constraints.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/check_promise.m:
compiler/closure_analysis.m:
compiler/closure_gen.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/common.m:
compiler/compile_target_code.m:
compiler/complexity.m:
compiler/const_prop.m:
compiler/constraint.m:
compiler/continuation_info.m:
compiler/convert_parse_tree.m:
compiler/coverage_profiling.m:
compiler/cse_detection.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.util.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/deforest.m:
compiler/delay_construct.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/det_util.m:
compiler/direct_arg_in_out.m:
compiler/disj_gen.m:
compiler/distance_granularity.m:
compiler/equiv_type_hlds.m:
compiler/exception_analysis.m:
compiler/file_names.m:
compiler/float_regs.m:
compiler/follow_vars.m:
compiler/format_call.m:
compiler/generate_dep_d_files.m:
compiler/get_dependencies.m:
compiler/goal_expr_to_goal.m:
compiler/goal_mode.m:
compiler/goal_path.m:
compiler/goal_store.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_clauses.m:
compiler/hlds_code_util.m:
compiler/hlds_error_util.m:
compiler/hlds_goal.m:
compiler/hlds_llds.m:
compiler/hlds_out_pred.m:
compiler/hlds_rtti.m:
compiler/hlds_statistics.m:
compiler/inlining.m:
compiler/inst_check.m:
compiler/inst_test.m:
compiler/inst_user.m:
compiler/instance_method_clauses.m:
compiler/instmap.m:
compiler/intermod.m:
compiler/intermod_analysis.m:
compiler/interval.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds.m:
compiler/llds_out_data.m:
compiler/llds_out_file.m:
compiler/llds_out_util.m:
compiler/lookup_switch.m:
compiler/loop_inv.m:
compiler/make.module_target.m:
compiler/make.util.m:
compiler/make_goal.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_types.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/middle_rec.m:
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_simplify_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_cs_class.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mmc_analysis.m:
compiler/mode_comparison.m:
compiler/mode_constraints.m:
compiler/mode_debug.m:
compiler/mode_errors.m:
compiler/mode_info.m:
compiler/mode_ordering.m:
compiler/modecheck_call.m:
compiler/modecheck_coerce.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/module_cmds.m:
compiler/old_type_constraints.m:
compiler/opt_debug.m:
compiler/optimize.m:
compiler/options_file.m:
compiler/ordering_mode_constraints.m:
compiler/par_loop_control.m:
compiler/parse_item.m:
compiler/parse_string_format.m:
compiler/parse_tree_out_inst.m:
compiler/parse_tree_to_term.m:
compiler/parse_util.m:
compiler/pd_debug.m:
compiler/pd_info.m:
compiler/pd_util.m:
compiler/peephole.m:
compiler/polymorphism.m:
compiler/polymorphism_info.m:
compiler/polymorphism_lambda.m:
compiler/polymorphism_type_class_info.m:
compiler/polymorphism_type_info.m:
compiler/post_typecheck.m:
compiler/pragma_c_gen.m:
compiler/pred_name.m:
compiler/pred_table.m:
compiler/prog_item.m:
compiler/prog_rep.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/push_goals_together.m:
compiler/qual_info.m:
compiler/quantification.m:
compiler/rbmm.execution_path.m:
compiler/rbmm.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.points_to_graph.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_resurrection_renaming.m:
compiler/rbmm.region_transformation.m:
compiler/recompilation.used_file.m:
compiler/recompilation.version.m:
compiler/recompute_instmap_deltas.m:
compiler/resolve_unify_functor.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/saved_vars.m:
compiler/set_of_var.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_conj.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/simplify_goal_scope.m:
compiler/simplify_goal_switch.m:
compiler/simplify_goal_unify.m:
compiler/simplify_info.m:
compiler/simplify_proc.m:
compiler/size_prof.m:
compiler/smm_common.m:
compiler/ssdebug.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/stack_opt.m:
compiler/stm_expand.m:
compiler/store_alloc.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.domain.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/superhomogeneous.m:
compiler/switch_detection.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_data.m:
compiler/term_constr_initial.m:
compiler/term_constr_main.m:
compiler/term_constr_main_types.m:
compiler/term_constr_util.m:
compiler/term_pass1.m:
compiler/term_traversal.m:
compiler/term_util.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/transform_llds.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/type_assign.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/typecheck_debug.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unify_gen_construct.m:
compiler/unify_gen_deconstruct.m:
compiler/unify_proc.m:
compiler/unique_modes.m:
compiler/unneeded_code.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/var_locn.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
|
||
|
|
8ebe125a6a |
Introduce var_table.m.
Most compiler passes need to know both the names and the types
of the variables they operate on. Until now, they had to pass along
two separate data structures for that, the varset and the vartypes,
and many operations required looking a variable up in both of these.
The var table is a single data structure that records for each variable
- its name, as the varset has traditionally done,
- its type, as the vartypes has traditionally done,
- the is_dummy_type flag which says whether its type is a dummy type,
which traditionally had to computed afresh at each lookup.
Switch the MLDS code generator to use var_tables instead of varsets and
vartypes. The code generator often needs to know the name and the type
of a variable at the same time, and it often needs to know which variables'
types are dummies, often enough that precomputing this info should be a win.
compiler/var_table.m:
Add this new module which defines the var_table.
Its operations are modelled after the operation in var_types.m.
compiler/hlds.m:
compiler/notes/compiler_design.html:
Add the new module to the hlds package.
compiler/prog_type.m:
compiler/type_util.m:
Move the is_dummy_type from type_util.m, which is in the
check_hlds package, to prog_type.m, which in the parse_tree package,
to avoid having this part of the hlds package depend on check_hlds.
(It already depends on parse_tree, for a lot of different things.)
Given a function and a predicate that each took a vartypes arg,
make new versions that take a var_table arg instead.
Rationalize the argument list of the function.
compiler/ml_gen_info.m:
Replace the varset and vartypes fields of the ml_gen_info with a
var_table field.
compiler/ml_code_util.m:
Replace code that used to operate on varsets and vartypes with code
that operates on var_tables.
Create new versions of a few operations to exploit the info in var_tables.
Give some predicates more meaningful names.
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/ml_unify_gen_util.m:
Replace code that used to operate on varsets and vartypes with code
that operates on var_tables.
In ml_switch_gen.m and ml_tag_switch.m, put some predicates' arguments
into an reasonable order by moving related args next to each other.
compiler/vartypes.m:
Delete an operation that was only needed in the MLDS backend,
in code that this diff replaces.
compiler/switch_util.m:
Put the larger input first in the arg list of a predicate.
compiler/closure_gen.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/export.m:
compiler/lambda.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds.m:
compiler/llds_out_instr.m:
compiler/mark_tail_calls.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/tag_switch.m:
compiler/term_constr_util.m:
compiler/tupling.m:
compiler/unify_gen.m:
compiler/unify_gen_deconstruct.m:
compiler/var_locn.m:
Conform to the changes above.
|
||
|
|
6a915eef05 |
Optimize field updates inside packed arg words.
Since june, we have been copying words containing packed-together
sub-word-sized arguments all in one piece if possible, for hlc grades.
This means that given a type such as
:- type t
---> f1(int8, bool, int8, int, bool, int8, bool).
whose first three and last three arguments are packed into one word each,
and a predicate such as
p(T0, T) :-
T0 = f1(A, B, C, _, E, F, G),
D = 42,
T = f1(A, B, C, D, E, F, G).
we generated code such as
MR_Integer D_12 = (MR_Integer) 42;
MR_Unsigned packed_args_0 =
(MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 0)));
MR_Unsigned packed_args_1 =
(MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 2)));
base = (MR_Word) MR_new_object(MR_Word,
((MR_Integer) 3 * sizeof(MR_Word)), NULL, NULL);
*T_4 = base;
MR_hl_field(MR_mktag(0), base, 0) = (MR_Box) (packed_args_0);
MR_hl_field(MR_mktag(0), base, 1) = ((MR_Box) (D_12));
MR_hl_field(MR_mktag(0), base, 2) = (MR_Box) (packed_args_1);
which does NOT pick up the values A, B, C, E, F and G individually.
However, until now, we could reuse packed-together words only in their
unchanged form.
This diff lifts that limitation, which means that now, we can *also*
optimize code such as
p(T0, T) :-
T0 = f1(A, B, _, D, E, _, G),
C = 42i8,
F = 43i8,
T = f1(A, B, C, D, E, F, G).
by generating code like this:
base = (MR_Word) MR_new_object(MR_Word,
(3 * sizeof(MR_Word)), NULL, NULL);
*T_4 = base;
MR_hl_field(MR_mktag(0), base, 0) = (MR_Box)
((((packed_word_0 & (~((MR_Unsigned) 255U)))) |
(MR_Unsigned) ((uint8_t) (C_12))));
MR_hl_field(MR_mktag(0), base, 1) = ((MR_Box) (D_8));
MR_hl_field(MR_mktag(0), base, 2) = (MR_Box)
((((packed_word_1 & (~((MR_Unsigned) 510U)))) |
(((MR_Unsigned) ((uint8_t) (F_13)) << 1))));
The general scheme when reusing *part* of a word is: first set the bits
not being reused to zero, and then OR in new values of those bits.
Make this optimization as general as possible by making it work
not just for
- words in memory cells containing only arguments,
but also for
- words in memory cells containing a remote sectag as well as arguments, and
- words in registers cells containing a ptag, a local sectag as well as
arguments.
compiler/ml_gen_info.m:
Generalize the data structure we use to represent information about
packed words to make possible approximate as well as exact lookups.
The key in the old map was "these bitfields with the values of these
variables in them", while the key in the new map is just "these bitfields",
with the associated value being a list, each element of which says
"the word with these values in those bitfields is available in this rval".
This makes it possible to look for matches words that have some, but not
all, of the right values in the bitfields.
Since the packed words may now contain tags as well as arguments,
rename "packed args" to "packed word".
compiler/ml_unify_gen_deconstruct.m:
When deconstructing a term containing packed words, add them to the
packed word map even when one of the bitfields inside the packed word
contains tag information.
Move the code that adds a packed word to the map into a separate predicate,
now that it is needed from more than one place.
compiler/ml_unify_gen_construct.m:
Change the code that handles packed words to work in terms of filled
bitfields. Use this not only to implement the optimization described
at the top, but also to make the handling of bitfields more systematic.
At least one previous bug was caused by doing sign extension differently
for the bitfield containing the first packed argument in a word than for
the later packed arguments in that word; with the new design, such
inconsistencies should not happen.
compiler/ml_unify_gen_util.m:
Add utility predicates now needed for both construct and deconstruct
unifications.
compiler/mlds.m:
Document the new use of lvnc_packed_word (renamed from lvnc_packed_args).
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
Conform to the changes above (mostly the packed_word rename).
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_stmt.m:
Omit unneeded casts from the output. Specifically, don't put (MR_Integer)
casts in front of integer constants being used either as shift amounts,
or as the number of words that a new_object MLDS operation should allocate.
The casts only cluttered the output, making it harder to read, and
therefore to judge its correctness.
|
||
|
|
bbe0f28f3b |
Copy packed arguments all at once.
Copy words containing packed-together sub-word-sized arguments all
in one piece if possible, for hlc grades.
Given a type such as
:- type t
---> f1(int8, bool, int8, int, bool, int8, bool).
whose first three and last three arguments are packed into one word each,
and a predicate such as
p(T0, T) :-
T0 = f1(A, B, C, _, E, F, G),
D = 42,
T = f1(A, B, C, D, E, F, G).
we used to generate code that picked up each of the six named arguments
from T0, and used them to construct T. With this diff, we now translate
the above to
MR_Integer D_12 = (MR_Integer) 42;
MR_Unsigned packed_args_0 =
(MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 0)));
MR_Unsigned packed_args_1 =
(MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 2)));
base = (MR_Word) MR_new_object(MR_Word,
((MR_Integer) 3 * sizeof(MR_Word)), NULL, NULL);
*T_4 = base;
MR_hl_field(MR_mktag(0), base, 0) = (MR_Box) (packed_args_0);
MR_hl_field(MR_mktag(0), base, 1) = ((MR_Box) (D_12));
MR_hl_field(MR_mktag(0), base, 2) = (MR_Box) (packed_args_1);
compiler/ml_unify_gen.m:
Implement the two main parts of this optimization.
Part one is the change to deconstruction unifications. When we generate
assignments from all the fields packed together into a word to their
corresponding argument variables (such as A/B/C or E/F/G above),
create a fresh variable (such as packed_args_0 above), assign to it
the value of the whole word, and record in a new data structure (the
packed_args_map) that these argument variables, in these positions
within the word, are now available in the newly created variable.
(We still define the argument variables as well, since they may be needed;
deleting them if they are *not* needed is the job of ml_unused_assign.m.)
Part two is the change to construction unifications. When we generate code
to OR together the shifted and/or masked values of two or more variables
to fill in one word in a new heap cell, we search the packed_args_map
to see whether those variables, in the positions we need, are available
in one of the variables created in part one. If yes, we discard
the whole OR-ing together operation and we use that variable instead.
Since part one can now create local variable definitions, return these
upwards as needed.
compiler/ml_gen_info.m:
Add two fields to the ml_gen_info structure (actually, to one of its
substructures). One is the packed_args_map described above, the other
is a counter we use to give a unique name to all the fresh variables.
When creating ml_gen_infos, put the code defining each field of a
substructure next to the creation of that substructure.
compiler/mlds.m:
Add a kind of compiler-generated variable holding packed argument words.
It is used in part one above.
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
Save, reset and restore the packed_args_map as necessary to ensure that
a construction unification sees an entry in that map only if the
deconstruction unification that created that entry *had* to be executed
before execution reaches the construction unification.
This means that when we process a branched control structure, we have to
make sure that (a) entries created by one branch are not seen when
we generate code for the other branches, and (b) that code *after* the
branched control structure sees only the entries created *before* the
branched control structure, since such code following cannot use an entry
that was created by a branch that may or may NOT have been executed
on the way there.
We also reset the packed_args_map to empty when generating code
that will end up inside a nested function, for two reasons. First,
I am not sure whether the code in ml_elim_nested.m that flattens out
nested functions is general enough to handle the new kind of compiler
generated variable correctly. And second, even if it is, the additional
memory traffic for putting those variables into environments, and later
pulling them out again, would definitely reduce and maybe completely
eliminate the speedup from optimizing constructions.
compiler/ml_closure_gen.m:
Conform to the change in ml_unify_gen.m.
compiler/ml_proc_gen.m:
Invoke ml_unused_assign.m in both branches of an if-then-else.
Previously, it was invoked in only the rarely executed branch,
which is what hid its bugs.
Fix one bug: for model_semi procedures, include the succeeded variable
in the set of variables whose values is needed after the generated
function body.
Work around another bug: the ml_unused_assign.m cannot yet handle
nested functions properly, so throw away its output in their presence.
compiler/ml_unused_assign.m:
As part of the same workaround, if a block contains nested functions,
tell ml_proc_gen.m to use the original code.
Fix several other bugs.
Don't delete variables from the seen_set when the backwards traversal
finds an assignment to them, because the variable's absence from
the seen_set would lead to the declaration of the variable being deleted.
Delete a sanity check that made sense only the presence of such deletions.
Never delete assignments to compiler-generated variables; we generate
such assignments only when their results *will* be needed.
When exiting the traversal of a block, *do* delete the variables
declared locally in that block from the seen_set; being undeclared there,
they cannot possibly be seen before that block. leaving them in
does not compromise correctness, but does reduce performance
by making operations on the seen_set slower than necessary.
If deleting unused assignments makes the else part of an if-then-else
empty, then delete the whole else part.
compiler/mlds_to_c_stmt.m:
Generate a valid C statement even for an MLDS comment. When an buggy
version of ml_unused_assign.m (incorrectly) deleted assignments to
succeeded, it sometimes left an else part containing only a comment,
which lead gcc to report syntax errors.
|
||
|
|
955a69efff |
Give better names to some functions.
compiler/type_util.m:
Rename the "check_dummy_type" function to "is_type_a_dummy", since this
expresses its job more clearly.
Make the implementation of "is_type_a_dummy" slightly more efficient,
by avoiding some redundant actions.
Provide a new function "is_either_type_a_dummy" that does
what its name says, and which is somewhat more efficient than
two separate calls to "is_type_a_dummy".
compiler/prog_type.m:
Rename the "check_builtin_dummy_type_ctor" function to
"is_type_ctor_a_builtin_dummy", since this expresses its job
more clearly.
compiler/ml_unify_gen.m:
Conform to the name changes.
Use the new function where relevant to simplify some code.
Fix some comments.
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/continuation_info.m:
compiler/erl_call_gen.m:
compiler/erl_code_gen.m:
compiler/erl_code_util.m:
compiler/erl_unify_gen.m:
compiler/export.m:
compiler/higher_order.m:
compiler/hlds_pred.m:
compiler/live_vars.m:
compiler/llds_out_instr.m:
compiler/mark_tail_calls.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/pragma_c_gen.m:
compiler/stack_layout.m:
compiler/term_constr_util.m:
compiler/trace_gen.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/var_locn.m:
compiler/write_module_interface_files.m:
Use the new function where relevant.
|
||
|
|
234501be75 |
Remove ml_tailcall.m and associated code.
Now that we can optimize tail recursion for all MLDS targets better via
the MLDS code generator than via ml_tailcall.m, we don't need it anymore.
compiler/ml_tailcall.m:
Delete this module.
compiler/ml_backend.m:
compiler/notes/compiler_design.html:
Delete the inclusion and the documentation of the deleted module.
compiler/mark_tail_calls.m:
Update old references to the deleted module, as well as some comments.
compiler/mercury_compile_mlds_back_end.m:
Don't invoke the deleted module.
compiler/options.m:
Delete the (developer-only) options that used to control whether
we did tail call optimization (TCO) via ml_tailcall.m or not.
compiler/ml_optimize.m:
Delete the parts of this module that worked in concert with ml_tailcall.m
to implement TCO.
compiler/mlds.m:
Delete the field from ml_call_stmts that was needed only by ml_tailcall.m.
compiler/ml_call_gen.m:
Don't fill in the deleted field.
Shift here the only part of the old contents of ml_tailcall.m that is
still needed, the check for whether rvals would become dangling references
if we discarded the current call's stack frame.
compiler/ml_elim_nested.m:
Conform to the change to mlds.m, and eliminate an unused field
in elim_info.
compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_proc_gen.m:
compiler/ml_rename_classes.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
Conform to the changes above.
|
||
|
|
5c43340b11 |
Implement TRO for model_non procedures.
The one thing that tail recursion optimization (TRO) via ml_tailcalls.m
could do that TRO via the MLDS code generator couldn't was TRO for model_non
procedures. This diff eliminates that difference.
compiler/mark_tail_calls.m:
Don't blow off marking tail calls in model_non procedures.
Add a new reason why TRO does not apply to a tail call. If the tail
call is in a nondet continuation, then the code we generate for it
will be in a nested function, which will end up in a *separate* function.
Implementing the tail call as a continue that jumps to the start of a
while loop that wraps the entire function body won't work, since continues
won't work from functions other than the one that contains the while loop.
compiler/ml_gen_info.m:
Add a field to the code generator state that gives the number of nested
functions the about-to-be-generated code will end up inside.
compiler/ml_call_gen.m:
Don't apply TRO to a call if this nesting level isn't zero, since
in that case the generated code would end up in a different function.
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
Increment the function nesting level before starting to generate code
that will end up in nested function, and decrement it afterwards.
compiler/ml_proc_gen.m:
Allow model_non procedures to be subject to TRO.
When generating the comment identifying a function that results from TRO
for a single procedure, make it specify its code_model.
|
||
|
|
996d689219 |
Support tail recursion between funcs and preds.
Generalize the mechanism we use to implement mutual tail recursion optimization
in the MLDS backend to handle TSCCs that contain both predicates and functions.
This generalization also simplifies the split of responsibilities between
the MLDS functions that implement each TSCC procedure for external callers
(which we now call the container function) on the one hand, and their main
components, the bodies of the procedures themselves (which we now call the
wrapped procedures, since each container function wraps up the bodies
of *all* the procedures in the TSCC).
In the new scheme, wrapped functions always give output arguments
to container functions by value. It is the job of the container functions
to return these output arguments to the caller according to the requirements
imposed by the container function's calling convention. This allows
different container functions to return output arguments differently
(some may return an output by value, while some may do so by reference)
while still allowing the wrapped procedure bodies to be generated just once
and then duplicated for each container function.
compiler/notes/mlds_tail_recursion.html:
A new file explaining both the scheme we use to generate code for
TSCCs, and the reasons why we use that scheme.
compiler/notes/Mmakefile:
Include the new file in the list of compiler notes files.
compiler/ml_args_util.m:
Update the code that generated code fragments handling arguments
for TSCCs to follow the updated scheme. Use the terminology in the
new notes file to clarify variable names where relevant. Group
related arguments together.
compiler/ml_proc_gen.m:
Update the code that created wrapped procedures and container functions
to follow the updated scheme. Use the terminology in the new notes file
to clarify both function and variable names where relevant. Delete the
documentation which is now in notes/mlds_tail_recursion.html (in greatly
enhanced form).
Split the predicate for adding local variable definitions to MLDS
functions, since when generating code for TSCCs using the new scheme,
we only need one of its two halves.
compiler/mlds.m:
Add the new forms of compiler generated variables needed by the new
translation scheme.
compiler/ml_gen_info.m:
Change the type of the field containing the byref output vars
from a list to a set. All its users want to treat it as a set,
so it is simpler and faster to convert it just once, when it is set,
instead of on every use.
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
Conform to the change in ml_gen_info.m.
|
||
|
|
b0edecbc7e |
Return information about output args in an assoc list.
compiler/ml_args_util.m:
Change the interface of the ml_gen_args predicate, which is used
to generate argument passing code at call sites. Instead of returning
information about output arguments in two lists, return a single list
of pairs, since this encodes the relevant invariant (the two lists
have to be of equal length) in the type.
compiler/ml_gen_info.m:
Make the same change in the representation of information about
output variables in success continuations. These continuations
are often constructed from the data returned by ml_gen_args.
compiler/ml_call_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_proc_gen.m:
Conform to the change above.
compiler/ml_closure_gen.m:
Conform to the change above.
Use the new list of pairs representation to greatly simplify
a piece of code that used higher order constructs to excess.
|
||
|
|
f4e0059a49 |
Eliminate hlc_nest and hl_nest grades ...
... by eliminating the grade component that calls for the use of gcc nested
functions.
runtime/mercury_grade.h:
compiler/compute_grade.m:
Delete the gcc_nested_functions grade component, and the C macro
that specifies its presence, MR_USE_GCC_NESTED_FUNCTIONS.
scripts/canonical_grade.sh-subr:
scripts/init_grade_options.sh-subr:
scripts/mgnuc.in:
scripts/parse_grade_options.sh-subr:
Delete the code that parses the deleted grade component,
and delete the code that signals its absence in other grades.
compiler/options.m:
Delete the gcc_nested_functions grade option.
Delete also the gcc_local_labels option, since it was useful
only if gcc_nested_functions was set.
configure.ac:
Delete the code that sometimes added hl*_nest grades to the list of grades
to be installed.
Fix a bunch of comments.
compiler/compile_target_code.m:
compiler/handle_options.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_gen_info.m:
compiler/mlds_to_c.m:
library/backjump.m:
library/exception.m:
runtime/mercury_hlc_types.h:
runtime/mercury_tabling.c:
runtime/mercury_tabling.h:
Delete code that was active only in grades with the deleted grade
component.
compiler/ml_accurate_gc.m:
compiler/notes/grade_library.html:
runtime/mercury_conf_param.h:
Delete mentions of the deleted grade component.
compiler/ml_code_gen.m:
Delete mentions of the deleted grade component, and a bunch of other
obsolete comments.
doc/user_guide.texi:
Fix a line break.
|
||
|
|
a4b6ca3b83 |
Eliminate repeated lookups of two options.
compiler/ml_gen_info.m:
Store the values of the det_copy_out and nondet_copy_out options
in the ml_gen_info.
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_proc_gen.m:
Get the values of those options from the ml_gen_info.
compiler/ml_args_util.m:
Get the values of those options from the ml_gen_info when it is available.
Keep private a predicate that (after the changes to the modules above)
isn't used outside this module anymore.
|
||
|
|
3ee7f79f9c |
Document the var_lvals field of ml_gen_info.
compiler/ml_gen_info.m:
As above.
compiler/ml_commit_gen.m:
Don't hide taking the snapshot of the var_lvals field in a subroutine.
Take it explicitly in each predicate that later restores that snapshot,
since having each save visibly paired with its restore simplifies
the implicit correctness argument.
|
||
|
|
034cb97988 |
Don't module- or type-qualify MLDS local variables.
Some global variables generated by the MLDS backend need to be visible
across module boundaries, and therefore mlds_data definitions, which
contained global as well as other variables, used to have their names
qualified; usually module-qualified, though sometimes type-qualified.
However, since the diff that partitioned mlds_data_defns into the
definitions of local variables, global variables and field variables,
the qualification of local variables has *not* been necessary, so this diff
removes such qualifications. This makes the MLDS code generating references
to local variables simpler, more readable, and slightly faster.
The generated code is also shorter and easier to read.
There are two exceptional cases in which local variables *did* need
qualification, both of which stretch the meaning of "local".
One such case is the "local" variable dummy_var, which (by definition)
is only ever assigned to, and never used. It is also never defined
in MLDS-generated code; instead, it is defined defined in private_builtin.m
(for the Java and C# backends) or the runtime (for C). All three backends
currently require references to this variable in the runtime to be module
qualified. There are three possible fixes to this problem, which is caused
by the fact that this "local" variable is in fact global.
- Fix 1a would be to make dummy_vars global, not local.
- Fix 1b is to special-case dummy_vars in mlds_to_{c,cs,java}.m, and put
the fixed "private_builtin" qualifier in front of it.
- Fix 1c would be to modify the compiler to never generate any references
to dummy vars at all.
This diff uses fix 1b, because it is simple. I (zs) will explore fix 1c
in the future, and see if it is viable.
The second such case occurs when generating code for unifications
involving function symbols represented by the addresses of reserved objects.
These addresses used to be represented as the addresses of mlds_data
definitions, then as addresses of field variables cast as qualified
local variables. Since diff this makes all local variables unqualified,
this can't continue. Two possible fixes are
- Fix 2a: introduce an mlds const rval representing the address of a field
variable, which solves the problem because unlike local variables,
field variables can still be either module- or type-qualified.
- Fix 2b: prohibit the use of the addresses of reserved objects as tags.
After a (short) discussion on m-dev, this diff uses fix 2b.
compiler/mlds.m:
Delete the qual_local_var_name type, and replace all its uses
with the mlds_local_var_name type. Delete the module qualifier field
in mlds_data_addr_local_var consts.
compiler/ml_code_util.m:
Simplify the predicates and functions whose task is to build references
to local variables. Delete the arguments that they don't need anymore.
Delete one function entirely, since calling it now takes both more
characters and more code than its shortened body does.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_rename_classes.m:
compiler/ml_string_switch.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_target_util.m:
compiler/rtti_to_mlds.m:
Conform to the changes above. Stop qualifying local variable names,
and stop passing the parameters that used to be used *only* for
qualifying local variable names.
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Conform to the changes above, and implement fix 1b.
NEWS:
compiler/options.m:
compiler/make_tags.m:
Implement fix 2b by disabling the --num-reserved-objects option.
This ensures that we don't use the addresses of reserved objects as tags.
library/private_builtin.m:
Move the C# definition of dummy_var next to the Java definition,
and fix the comments on them.
|
||
|
|
bd3fd38c0d |
Delete the field for the "this" rval in MLDS calls.
This field of type maybe(mlds_rval) was *always* set to "no".
compiler/mlds.m:
As above.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_rename_classes.m:
compiler/ml_tailcall.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
Conform to the above.
|
||
|
|
1c01ed85eb | Fix lines. | ||
|
|
91790794f1 |
Define the MLDS "succeeded" variable only if needed.
This makes the generated MLDS code less cluttered and easier to work on.
compiler/ml_gen_info.m:
Add a field for recording whether the succeeded variable has been used.
compiler/ml_code_util.m:
Change the predicates that return references to the succeeded variable
to record that it has been used.
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_lookup_switch.m:
compiler/ml_string_switch.m:
compiler/ml_unify_gen.m:
Use the updated forms of the predicates in ml_code_util.m.
compiler/ml_proc_gen.m:
Define the succeeded variable only if the new slot says it has been used.
compiler/ml_optimize.m:
Fix a bug triggered by the above change: when a tail recursive call
was the *entire body* of a MLDS function, ml_optimize.m did not find it,
and thus did not do the setup needed to prepare for the tail recursion.
Previously, the always-present declaration of "succeeded" made it
impossible for the tail call to be the only thing in the body.
|
||
|
|
11c232f060 |
Store different kinds of definitions in blocks separately.
An ml_stmt_block contains some definitions and some statements.
The definitions were traditionally stored in a single list of mlds_defns,
but lots of code knew that some kinds of mlds_defns just couldn't occur
in blocks. This diff, by storing the definitions of (a) local variables
and (b) continuation functions in separate field in ml_stmt_blocks,
gets the type system to enforce the invariant that other kinds of definitions
can't occur in blocks.
This also allows the compiler to do less work, since definitions
don't have to wrapped and then later unwrapped, and code that wants to look
at only e.g. the function definitions in a block don't have to traverse
the definitions of local variables (of which there are many more).
compiler/mlds.m:
Make the change described above.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_simplify_switch.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
Conform to the change above. This allows us to avoid lots of wrapping
up definitions.
In some cases, after this change, we don't need to process mlds_defns
*in general*, which leaves the predicates that used to do that,
and some of the predicates that they used to call, unused. Delete these.
In code that generated MLDS code, consistently use names containing
the word "Defn", instead of "Decl", for variables that contain
mlds_local_var_defns or mlds_function_defns. Some such predicates
generate lists of both local var definition and function definitions,
but most generate only one, and some generate neither.
|
||
|
|
47f1df4a0a |
Split mlds_data_defn into three separate types.
We used to use mlds_data_defns to represent three related but nevertheless
distinct kinds of entities: global variables, local variables, and fields
in classes. This diff replaces the mlds_data_defn type with three separate
types: mlds_global_var_defn, mlds_local_var_defn and mlds_field_var_defn
respectively, with corresponding changes to related types, such as
mlds_data_name.
The global variables are completely separate from the other two kinds.
Local and field variables are *mostly* separate from each other, but they
are related in one way. When we flatten out nested functions, the child
nested function can no longer access its parent function's local variables,
so we pass those variables to it as fields of an environment structure.
This requires turning local variables to fields of that structure,
and the code in the flattened previously-nested function that accesses
those fields naturally wants to treat them as if they were local variables
(as indeed they sort-of were before the flattening). There are therefore
ways to convert each of local and fields vars into the other.
This restructuring makes clear several invariants of the MLDS we generate
that were previously hidden. For example, variables with certain kinds of
names (in the before-this-diff, general version of the mlds_var_name type)
could appear only as function arguments or as locals in ml_stmt_blocks,
not in ml_global_data, while for some other names the opposite was the case.
And in several cases, functions used to take a general mlds_data_defn
as argument but aborted if given the "wrong kind" of mlds_data_defn.
This diff also makes possible further simplifications. For example,
local vars should not need some flags (since e.g. they are never per-instance),
and should never need either module or type qualification, while global
variables (which are also never per-instance) should never need type
qualification (since they are not fields of a type). The definitions
in blocks should consist of local variables and (before flattening) functions,
not global variables, field variables or classes, while the members in classes
should be only field variables and functions (and maybe classes), not
global or local variables. Those changes will be in future diffs;
this is already large enough.
compiler/mlds.m:
Make the changes described above.
Use tighter types where possible.
Use (a generalized version) of the mlconst_named_const functor
to represent values of enum types defined in the runtimes
of the target platforms.
compiler/ml_global_data.m:
Store *only* global variables in fields that previously stored general
mlds_datas (that by design were always global).
Store *only* closure wrapper functions in the previous non-flat-defns
field. Before this diff, the code generator only put closure wrapper
functions in this field, but then ml_elim_nested.m put everything
resulting from the expansion of those functions back into those fields
as well, some of which were not functions. It now puts those non-function
things into the MLDS data structure directly.
compiler/ml_code_util.m:
compiler/ml_util.m:
Conform to the changes above.
Use tighter types where possible. If appropriate, change the name
of the function or predicate accordingly.
Represent references to enum constants defined in the runtime of the
target language as named constants (since they is what they are),
instead of representing them as MLDS "variables", which required
the code of mlds_to_cs.m had to special-case the treatment
of those "variables".
compiler/ml_elim_nested.m:
Conform to the changes above.
Use tighter types where possible.
Don't put the environment types resulting from flattening nested scopes
back into the non-flat-defns slot of the ml_elim_info; instead, return
them separately to code that puts them directly in the MLDS.
compiler/rtti.m:
When returning the names of enum constants in the C runtime, return also
the prefixes that you need to place in front of these to obtain their names
in the Java and C# runtimes.
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
Conform to the changes above.
Move a utility function from ml_util.m to mlds_to_target_util.m,
since it is used only in mlds_to_*.m.
|
||
|
|
083f990dbb |
Simplify the use of contexts in the MLDS.
compiler/mlds.m:
This diff fixes two minor annoyances imposed by the old use of the
mlds_context type in the MLDS.
The first annoyance was that the mlds_context type used to be an
abstract type that was privately defined to be a trivial wrapper
around a prog_context. It had the exact same information content
as a prog_context, but you had to go through translation functions
to translate prog_contexts to mlds_contexts and vice versa.
I think Fergus's idea was that we may want to add other information
to the mlds_context type. However, since we haven't felt the need
to anything like that in the 18 years (almost to the day) that the
mlds_context type existed, I think this turned out to be a classic
case of YAGNI (you ain't gonna need it).
This diff deletes the mlds_context type, and replaces its uses
with prog_context.
The second annoyance was that actual MLDS code, i.e. values of the
mlds_stmt type, always had to wrapped up inside a term of the statement
type, a term which paired a context with the mlds_stmt.
This diff moves the context information (now prog_context, not
mlds_context) into each function symbol of the mlds_stmt type,
deletes the statement type, and replaces its uses with the now-expanded
mlds_stmt type. This simplifies most code that deals with MLDS code.
compiler/ml_util.m:
Add a function, get_mlds_stmt_context, for the (very rare) occasions
where we want to know the context of an mlds_stmt *before* testing
to see what function symbol it is bound to.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_simplify_switch.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/rtti_to_mlds.m:
Conform to the changes above.
In some cases, a function was given two separate contexts, sometimes from
two separate sources; a prog_context and an mlds_context. In such cases,
keep only one source.
Standardize on Stmt as the variable name for "statement".
Delete redundant $module references from unexpected and other abort
predicates.
In one case, delete a function that was a duplicate of another function.
Give some predicates and functions more meaningful names.
|
||
|
|
869605956c |
Make MLDS definitions self-contained.
Until now, we used a single type, mlds_defn, to contain both
- generic information that we need for all MLDS definitions, such as
name and context, and
- information that is specific to each different kind of MLDS definition,
such as a variable's initializer or a function's list of parameter types.
The former were contained in three fields in the mlds_defns directly,
while the latter were contained in a fourth field that was a discriminated
union of mlds_data_defn, mlds_function_defn and mlds_class_defn.
While seemingly parsimonious, this design meant that if we had e.g. a list
of variable definitions, we would have to wrap the mlds_defn/4 wrapper around
them to give them their names, and thereafter, any code that processed
that list would have to be prepared to process not just variables but also
functions and classes.
This diff moves the three generic fields into each of the mlds_data_defn,
mlds_function_defn and mlds_class_defn types, making each those types
self-contained, and leaving mlds_defn as nothing more than a discriminated
union of those types.
In the few places that want to look at the generic fields *without*
caring about what kind of entity is being defined, this design requires
a bit of extra work compared to the old design, but in many other places,
the new design allows us to return mlds_data_defns, mlds_function_defns
or mlds_class_defns instead of just mlds_defns.
compiler/mlds.m:
Make the change described above.
Store type definions (for high level data) and table structures definitions
separately from other definitions in the MLDS type, since we can now
give them tighter types.
compiler/ml_global_data.m:
Change the fields that store flat cells from storing mlds_defns to
storing mlds_data_defns, since we can now do so.
Add an XXX about an obsolete comment.
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/rtti_to_mlds.m:
Conform to the changes above. Where possible with only local changes,
return mlds_data_defns mlds_function_defns or mlds_class_defns instead
of just mlds_defns. Put the mlds_data(_), mlds_function(_) or mlds_class(_)
wrapper around those definitions as late as possible (typically, when
our current code wants to put it into the same list as some other kind
of definition), in the hope that in the future, that wrapping can be
delayed even later, or even avoided altogether. Make the places where
such improvements may be possible with "XXX MLDS_DEFN".
In some places, the tighter data representation allows us to *delete*
"XXX MLDS_DEFN" markers.
Move some common code from mlds_to_{cs,java}.m to ml_util.m.
In mlds_to_{cs,java}.m, add prefixes to the function symbols in a type
to reduce ambiguity.
|
||
|
|
8dbea9f096 |
Use a structured representation for MLDS variables.
compiler/mlds.m:
Replace the old definition of mlds_var_name, which was a string
with an optional integer. The integer was intended to be the number
of a HLDS variable, while auxiliary variables created by the compiler,
which do not correspond to a HLDS variable, would not have the optional
integer.
This design has a couple of minor problems. The first is that there is
no place in the compiler where all the variable names are visible at once,
and without such a place, we cannot be sure that two names constructed
for different purposes don't accidentally end up with the same name.
The probability of such a clash used to be astronomically small
(which is why this hasn't been a problem), but it was not zero.
The second problem is that several kinds of compiler-created MLDS variables
want to have numerical suffixes too, usually with the suffix being a
unique sequence number used as a means of disambiguation. Most of the
places where these were created put the numerical suffix into the name
string itself, while some put the sequence number as the optional integer.
As it happens, neither of those actions is good when one wants to take
the independently generated MLDS code of several procedures in an SCC
and merge them into a single piece of MLDS code. For this, we want to
rename apart both the HLDS variable numbers and the sequence numbers.
Having the sequence number baked into the strings themselves obviously
makes such renumbering unnecessarily hard, while having sequence numbers
in the slots intended for HLDS variable numbers makes the job impossible
to do safely.
This diff switches to a new representation of mlds_var_names that
has a separate function symbol for each different "origin story"
that is possible for MLDS variables. This addresses both problems.
The single predicate that converts this structured representation
to a string is the place where we can ensure that two semantically
different MLDS variables never get translated to the same string.
The current version of this predicate does *not* offer this guarantee,
but later versions could.
And having all the integers used in mlds_var_names for different purposes
stored as arguments of different function symbols (that clearly indicate
their meaning) makes it possible to rename apart different sets
of MLDS variables easily and reliably.
Move the code for converting mlds_var_names from ml_code_util.m to here,
to make it easier to maintain it together with the mlds_var_name type.
compiler/ml_code_util.m:
Conform to the above change by generating structured MLDS var names.
Delete a predicate that is not needed with structured var names.
Delete the code moved to mlds.m.
Delete a predicate that has been unused since we deleted the IL backend.
Add ml_make_boxed_type as a version of ml_make_boxed_types that returns
exactly one type. This simplifies some code elsewhere.
Add "hld" to some predicate names to make clear that they are intended
for use only with --high-level-data.
compiler/ml_type_gen.m:
Conform to the above change by generating structured MLDS var names.
Add "hld" to the names of the (many) predicates here that are used
only with --high-level-data to make clear that fact.
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Conform to the above change by generating structured MLDS var names.
Add a "for_csharp" or "for_java" suffix to some predicate names
to avoid ambiguities.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_string_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
Conform to the above change by generating structured MLDS var names.
compiler/prog_type.m:
Add var_to_type, as a version of var_list_to_type_list that returns
exactly one type. This simplifies some code elsewhere.
compiler/java_names.m:
Give some predicates and functions better names.
compiler/ml_code_gen.m:
Fix typo.
|
||
|
|
e5daa207fa |
Fix disabling warnings for non-tail recursive calls with MLDS.
compiler/mlds.m:
Add a field to call statements in MLDS that contains a (probably empty)
set of markers. At the moment, the only marker possible is one that says
"don't generate a non-tail recursive call warning for this call".
compiler/ml_gen_info.m:
Add a field to the ml_gen_info type, which contains the state of the
MLDS code generator, that records the set of warnings that are disabled
for the HLDS goal currently being translated.
compiler/ml_code_gen.m:
When processing the subgoal inside a disable_warnings scope,
add the warnings disabled by the scope to the new field
in the ml_gen_info.
compiler/ml_call_gen.m:
When creating MLDS call statements, put the new marker in the call's new
field if goal_warning_non_tail_recursive_calls is among the currently
disabled warnings.
compiler/ml_tailcall.m:
Don't generate warnings about a recursive call not being *tail* recursive
if the call has the new marker.
compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Conform to the changes above.
|
||
|
|
cc9912faa8 |
Don't import anything in packages.
Packages are modules whose only job is to serve as a container for submodules. Modules like top_level.m, hlds.m, parse_tree.m and ll_backend.m are packages in this (informal) sense. Besides the include_module declarations for their submodules, most of the packages in the compiler used to import some modules, mostly other packages whose component modules their submodules may need. For example, ll_backend.m used to import parse_tree.m. This meant that modules in the ll_backend package did not have to import parse_tree.m before importing modules in the parse_tree package. However, this had a price. When we add a new module to the parse_tree package, parse_tree.int would change, and this would require the recompilation of ALL the modules in the ll_backend package, even the ones that did NOT import ANY of the modules in the parse_tree package. This happened even at one remove. Pretty much all modules in every one of the backend have to import one or more modules in the hlds package, and they therefore have import hlds.m. Since hlds.m imported transform_hlds.m, any addition of a new middle pass to the transform_hlds package required the recompilation of all backend modules, even in the usual case of the two having nothing to do with each other. This diff removes all import_module declarations from the packages, and replaces them with import_module declarations in the modules that need them. This includes only a SUBSET of their child modules and of the non-child modules that import them. |
||
|
|
7654ec847e | Convert (C->T;E) to (if C then T else E). | ||
|
|
62ec97d443 |
Report imports shadowed by other imports.
If a module has two or more import_module or use_module declarations
for the same module, (typically, but not always, one being in its interface
and one in its implementation), generate an informational message about
each redundant declaration if --warn-unused-imports is enabled.
compiler/hlds_module.m:
We used to record the set of imported/used modules, and the set of
modules imported/used in the interface of the current module. However,
these sets
- did not record the distinction between imports and uses;
- did not allow distinction between single and multiple imports/uses;
- did not record the locations of the imports/uses.
The first distinction was needed only by module_qual.m, which *did*
pay attention to it; the other two were not needed at all.
To generate messages for imports/uses shadowing other imports/uses,
we need all three, so change the data structure storing such information
for *direct* imports to one that records all three of the above kinds
of information. (For imports made by read-in interface and optimization
files, the old set of modules approach is fine, and this diff leaves
the set of thus *indirectly* imported module names alone.)
compiler/unused_imports.m:
Use the extra information now available to generate a
severity_informational message about any import or use that is made
redundant by an earlier, more general import or use.
Fix two bugs in the code that generated warnings for just plain unused
modules.
(1) It did not consider that a use of the builtin type char justified
an import of char.m, but without that import, the type is not visible.
(2) It scanned cons_ids in goals in procedure bodies, but did not scan
cons_ids that have been put into the const_struct_db. (I did not update
the code here when I added the const_struct_db.)
Also, add a (hopefully temporary) workaround for a bug in
make_hlds_passes.m, which is noted below.
However, there are at least three problems that prevent us from enabling
--warn-unused-imports by default.
(1) In some places, the import of a module is used only by clauses for
a predicate that also has foreign procs. When compiled in a grade that
selects one of those foreign_procs as the implementation of the predicate,
the clauses are discarded *without* being added to the HLDS at all.
This leads unused_imports.m to generate an uncalled-for warning in such
cases. To fix this, we would need to preserve the Mercury clauses for
*all* predicates, even those with foreign procs, and do all the semantic
checks on them before throwing them away. (I tried to do this once, and
failed, but the task should be easier after the item list change.)
(2) We have two pieces of code to generate import warnings. The one in
unused_imports.m operates on the HLDS after type and mode checking,
while module_qual.m operates on the parse tree before the creation of
the HLDS. The former is more powerful, since it knows e.g. what types and
modes are used in the bodies of predicates, and hence can generate warnings
about an import being unused *anywhere* in a module, as opposed to just
unused in its interface.
If --warn-unused-imports is enabled, we will get two separate set of
reports about an interface import being unused in the interface,
*unless* we get a type or mode error, in which case unused_imports.m
won't be invoked. But in case we do get such errors, we don't want to
throw away the warnings from module_qual.m. We could store them and
throw them away only after we know we won't need them, or just get
the two modules to generate identical error_specs for each warning,
so that the sort_and_remove_dups of the error specs will do the
throwing away for us for free, if we get that far.
(3) The valid/bug100.m test case was added as a regression test for a bug
that was fixed in module_qual.m. However the bug is still present in
unused_imports.m.
compiler/make_hlds_passes.m:
Give hlds_module.m the extra information it now needs for each item_avail.
Add an XXX for a bug that cannot be fixed right now: the setting of
the status of abstract instances to abstract_imported. (The "abstract"
part is correct; the "imported" part may not be.)
compiler/intermod.m:
compiler/try_expand.m:
compiler/xml_documentation.m:
Conform to the change in hlds_module.m.
compiler/module_qual.m:
Update the documentation of the relationship of this module
with unused_imports.m.
compiler/hlds_data.m:
Document a problem with the status of instance definitions.
compiler/hlds_out_module.m:
Update the code that prints out the module_info to conform to the change
to hlds_module.m.
Print status information about instances, which was needed to diagnose
one of the bugs in unused_imports.m. Format the output for instances
nicer.
compiler/prog_item.m:
Add a convenience predicate.
compiler/prog_data.m:
Remove a type synonym that makes things harder to understand, not easier.
compiler/modules.m:
Delete an XXX that asks for the feature this diff implements.
Add another XXX about how that feature could be improved.
compiler/Mercury.options.m:
Add some more modules to the list of modules on which the compiler
should be invoked with --no-warn-unused-imports.
compiler/*.m:
library/*.m:
mdbcomp/*.m:
browser/*.m:
deep_profiler/*.m:
mfilterjavac/*.m:
Delete unneeded imports. Many of these shadow other imports, and some
are just plain unneeded, as shown by --warn-unused-imports. In a few
modules, there were a *lot* of unneeded imports, but most had just
one or two.
In a few cases, removing an import from a module, because it *itself*
does not need it, required adding that same import to those of its
submodules which *do* need it.
In a few cases, conform to other changes above.
tests/invalid/Mercury.options:
Test the generation of messages about import shadowing on the existing
import_in_parent.m test case (although it was also tested very thoroughly
when giving me the information needed for the deletion of all the
unneeded imports above).
tests/*/*.{m,*exp}:
Delete unneeded imports, and update any expected error messages
to expect the now-smaller line numbers.
|
||
|
|
d00ea69529 |
Switch from using set(prog_var), which is represented using set_ordlist,
Estimated hours taken: 12 Branches: main Switch from using set(prog_var), which is represented using set_ordlist, to set_of_progvar, which is represented using tree_bitset, for most sets of variables in the compiler, including the nonlocals sets in goal_infos. This diff yields about a 5% speedup when compiling the training_cars_full.m stress test, but also about a 1% slowdown on tools/speedtest. Both of these are with the current default state in which tree_bitset is compiled with a whole bunch of sanity checks. If these are disabled, we get roughly a 1% speedup on tools/speedtest. I intend to disable those sanity checks after a shakedown period of a week or two in which the updated version of the compiler is installed on our platforms. compiler/hlds_goal.m: Replace almost all occurrences of set(prog_var) with set_of_progvar. The main exceptions are the types supporting rbmm. compiler/set_of_var.m: Add some more predicates and functions that previous existed on sets but not yet on set_of_vars. compiler/*.m: Conform to the change in hlds_goal.m, and make similar changes in set representations. library/bag.m: Add a predicate and function for creating a bag from a sorted list. We already had them for creating a bag from a set, but a set_of_progvar shouldn't have to be converted to a set. library/robdd.m: Fix deviations from our programming style. |
||
|
|
295415090e |
Convert almost all remaining modules in the compiler to use
Estimated hours taken: 6 Branches: main compiler/*.m: Convert almost all remaining modules in the compiler to use "$module, $pred" instead of "this_file" in error messages. In a few cases, the old error message was misleading, since it contained an incorrect, out-of-date or cut-and-pasted predicate name. tests/invalid/unresolved_overloading.err_exp: Update an expected output containing an updated error message. |
||
|
|
d73decfa45 |
Eliminate some now-redundant code.
Estimated hours taken: 0.5 Branches: main Eliminate some now-redundant code. compiler/ml_commit_gen.m: compiler/ml_elim_nested.m: compiler/ml_code_util.m: Remove all the calls to ml_decl_is_static_const, since static constant definitions are no longer included in the list of definitions explicitly returned by the predicates of the code generator. compiler/ml_code_util.m: Remove the now obsolete predicate. compiler/rtti_to_mlds.m: Remove a reference to the deleted predicate. |
||
|
|
439e9d474d |
Divide the old 4100, 2900 and 4600 line modules ml_code_gen.m, ml_code_util.m
Estimated hours taken: 4 Branches: main Divide the old 4100, 2900 and 4600 line modules ml_code_gen.m, ml_code_util.m and modes.m into smaller, more cohesive modules. In the process, put related predicates next to each other. There are no algorithmic changes. compiler/ml_proc_gen.m: New module that looks after code generation tasks that affect a procedure as a whole. Its code is taken from the old ml_code_gen.m. Analogous to proc_gen.m, which does the same job for the LLDS backend. compiler/ml_foreign_proc_gen.m: New module that generates code for foreign_proc goals. Its code is taken from the old ml_code_gen.m. Analogous to pragma_c_gen.m in the LLDS backend. compiler/ml_commit_gen.m: New module that generates code for commit goals. Its code is taken from the old ml_code_gen.m. Analogous to commit_gen.m in the LLDS backend. compiler/ml_gen_info.m: New module that encapsulates the ml_gen_info structure. Its code is taken from the old ml_code_util.m. Analogous to code_info.m in the LLDS backend. compiler/ml_accurate_gc.m: New module that generates the data and goals needed for accurate gc. Its code is taken from the old ml_code_util.m. compiler/ml_call_gen.m: compiler/ml_closure_gen.m: Move some predicates that are used by other modules of the MLDS backend to ml_code_util, in order to avoid otherwise unneeded dependencies. compiler/mode_util.m: Move a predicate here from ml_code_util.m, since it is needed by several MLDS backend modules but is not MLDS specific. compiler/ml_code_gen.m: Remove the code moved to other modules. Delete an old note about a problem fixed long ago. compiler/ml_code_util.m: Remove the code moved to other modules. Add the code moved here from other modules. compiler/modecheck_conj.m: New module that handles mode analysis of conjunctions. Its code is taken from the old modes.m. compiler/modecheck_goal.m: New module that handles mode analysis of most types of goals, except conjunctions, unifications and calls. Its code is taken from the old modes.m. compiler/modecheck_util.m: New module containing utility predicates used more one of the modules do mode analysis. Its code is taken from the old modes.m. compiler/mode_util.m: Move a predicate here from modes.m, since this is where a related predicate already is. Give a predicate a more meaningful name. compiler/goal_util.m: Move a predicate here from modes.m, since this is where a related predicate already is. compiler/modes.m: Remove the code moved to other modules. compiler/ml_backend.m: compiler/check_hlds.m: Add the new modules. compiler/notes/compiler_design.html: Document the new modules. compiler/prog_data.m: Give some function symbols disambiguating prefixes. compiler/add_solver.m: compiler/deforest.m: compiler/make_hlds_passes.m: compiler/mercury_compile.m: compiler/ml_lookup_switch.m: compiler/ml_simplify_switch.m: compiler/ml_string.m: compiler/ml_switch_gen.m: compiler/ml_tag_switch.m: compiler/ml_unify_gen.m: compiler/modecheck_call.m: compiler/modecheck_unify.m: compiler/prog_io_type_defn.m: compiler/rtti_to_mlds.m: compiler/type_ctor_info.m: compiler/unify_proc.m: Conform to the changes above. |