mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 13:23:47 +00:00
083d376e6598628362ee91c2da170febd83590f4
124 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d787ee9355 |
Store var_tables in proc_infos.
This fixes the performance problem reported in Mantis bug #562. compiler/hlds_pred.m: Instead of storing a varset and a vartypes in each proc_info, store just a var_table. Update the predicates that create or clone procedures accordingly. Where we had operations on proc_infos that had two versions, one operating on a varset/vartypes pair and one operating on var_table, keep only the latter, with the (shorter) name of the former. Delete the arity argument of proc_info_init, because the only valid value of that argument is the length of the list of the argument types. (In other words, this arg has been redundant all along.) Change the operations that create new variables in a procedure to get the caller to specify the (base) name of the new variable up front. Delete the unused predicate proc_info_ensure_unique_names. compiler/type_util.m: Due to the change above, we now construct var_tables during the construction of the HLDS. The code that does that needs to fill in the field that says whether the type of each variable in the table is a dummy type or not. However, at this time, the pass that decides type representations has not been run yet. The code of is_type_a_dummy used to throw an exception in such situations. Change this so that in such situations, is_type_a_dummy returns a placeholder, not-guaranteed-to-be-correct value. Document why this is ok. compiler/post_typecheck.m: Replace the placeholder values in vte_is_dummy fields in all the entries in the var_tables in all (valid) predicates with valid data. (If there are any invalid predicates, the compilation will fail anyway.) The clause_to_proc pass will copy these updated var_tables to be the initial var_tables in procedures. compiler/make_goal.m: Change the operations that create new variables in a procedure to get the caller to specify the (base) name of the new variable up front. This is simpler than the old method, which created new variables without a name, and had the caller give them a name as a separate operation. And since var_tables need this info, get the caller to also specify whether the type is a dummy, if the type is not a builtin type which is known not to be a dummy. compiler/var_table.m: Document the times when the types and is_dummy fields in var_table entries become meaningful. Fix a potential bug: when performing type substitutions in var_table entries, updating a variable's type may change whether that variable is a dummy or not, so recompute that info. It is quite possible that we *never* replace a nondummy type with a dummy type or vice versa, but in the absence of a convincing correctness argument for that proposition, better safe than sorry. Export the previously-private predicate transform_var_table to post_typecheck. Add code to implement the unused predicate deleted from hlds_pred.m: at the time I wrote it, I haven't yet realised that it was unused. The code I wrote here is therefore unused as well, so it is commented out. I did not delete it, because it may be useful later on. compiler/direct_arg_in_out.m: Don't make and split var_tables, since it is no longer needed. compiler/accumulator.m: compiler/add_class.m: compiler/add_clause.m: compiler/add_heap_ops.m: compiler/add_pred.m: compiler/add_special_pred.m: compiler/add_trail_ops.m: compiler/arg_info.m: compiler/build_mode_constraints.m: compiler/bytecode_gen.m: compiler/check_typeclass.m: compiler/clause_to_proc.m: compiler/closure_analysis.m: compiler/code_gen.m: compiler/code_loc_dep.m: compiler/complexity.m: compiler/continuation_info.m: compiler/cse_detection.m: compiler/ctgc.livedata.m: compiler/deep_profiling.m: compiler/default_func_mode.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/distance_granularity.m: compiler/equiv_type_hlds.m: compiler/exception_analysis.m: compiler/float_regs.m: compiler/follow_code.m: compiler/goal_mode.m: compiler/goal_path.m: compiler/higher_order.m: compiler/hlds_out_pred.m: compiler/hlds_rtti.m: compiler/hlds_statistics.m: compiler/inlining.m: compiler/intermod.m: compiler/intermod_analysis.m: compiler/introduce_exists_casts.m: compiler/introduce_parallelism.m: compiler/lambda.m: compiler/lco.m: compiler/live_vars.m: compiler/liveness.m: compiler/loop_inv.m: compiler/mark_tail_calls.m: compiler/ml_accurate_gc.m: compiler/ml_args_util.m: compiler/ml_closure_gen.m: compiler/ml_gen_info.m: compiler/ml_proc_gen.m: compiler/mode_errors.m: compiler/mode_info.m: compiler/modecheck_goal.m: compiler/par_loop_control.m: compiler/pd_debug.m: compiler/pd_info.m: compiler/pd_util.m: compiler/polymorphism_info.m: compiler/post_typecheck.m: compiler/proc_gen.m: compiler/proc_requests.m: compiler/purity.m: compiler/push_goals_together.m: compiler/quantification.m: compiler/rbmm.add_rbmm_goal_infos.m: compiler/rbmm.live_variable_analysis.m: compiler/rbmm.points_to_analysis.m: compiler/rbmm.points_to_graph.m: compiler/rbmm.points_to_info.m: compiler/rbmm.region_liveness_info.m: compiler/rbmm.region_transformation.m: compiler/recompute_instmap_deltas.m: compiler/saved_vars.m: compiler/simplify_goal_unify.m: compiler/simplify_info.m: compiler/simplify_proc.m: compiler/size_prof.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_reuse.versions.m: compiler/structure_sharing.analysis.m: compiler/structure_sharing.domain.m: compiler/switch_detection.m: compiler/table_gen.m: compiler/tabling_analysis.m: compiler/term_constr_build.m: compiler/term_constr_initial.m: compiler/term_errors.m: compiler/term_pass1.m: compiler/term_pass2.m: compiler/trace_gen.m: compiler/trailing_analysis.m: compiler/try_expand.m: compiler/tupling.m: compiler/unneeded_code.m: compiler/untupling.m: compiler/unused_args.m: compiler/unused_imports.m: Conform to the changes above. Mostly this means - not passing a module_info to get a var_table out of a proc_info, but - having to pass a module_info to code that either constructs a var_table, or adds entries to a var_table (since we now need the type table to figure out whether variables' types are dummies). |
||
|
|
03c9135991 |
Stop using varsets/vartypes in the MLDS backend.
compiler/ml_args_util.m:
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_proc_gen.m:
As above.
compiler/hlds_pred.m:
The code in the MLDS code generator that handles calls reuses
some code in ml_args_util.m that it uses for the clause head,
and thus derived the names of some MLDS variables from the
varset of the callee. In the case where the callee is a unify
or compare predicate for an imported type, the varset contained
the names of the argument variables, but not their type. This means
that looking up their names in the var_table instead of the varset
requires the var_table to contain every variable that the varset contains,
so change the code that constructs the var_table to ensure this.
Add a var_table version of another predicate to prepare for a future
change.
tests/invalid/try_detism.err_exp:
Update the variable number of an unnamed variable after the changes
in hlds_pred.m.
|
||
|
|
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.
|
||
|
|
3f3045c9e2 |
Get and set varsets/vartypes in proc_infos together.
compiler/hlds_pred.m:
We eventually want to replace the varset and vartypes fields in
each proc_info with a var_table, but it is not practical to do so
at once; it will have to be done gradually, a few modules at most
at a time. During this process, we will need a way either
- to let already converted modules get a var_table out of the proc_info,
and put an updated var_table back into a proc_info, even though
proc_infos still contain varset and vartypes fields, or
- to let not-yet-converted modules get varsets and vartypes out of the
proc_info, and put updated varsets and vartypes back into a proc_info,
even though proc_infos already store a var_table.
The latter cannot be done in two halves (i.e. set the varset half
of the var_table, and then set its vartypes half), and while the former
*can* be done that way, it is more efficient to do them at the same time.
Therefore as a first step, this diff replaces the indiviual getter
and setter predicates of the varset and vartypes fields of proc_info
with a getter that gets both and a setter that sets both.
Put the varset and vartypes next to each other in a structure.
compiler/code_info.m:
Delete a function that duplicates a function in var_table.m.
Conform to the change above.
compiler/det_report.m:
Factor out some common code.
Conform to the change above.
compiler/det_util.m:
Delete a no-longer-needed predicate.
Conform to the change above.
compiler/higher_order.m:
Fix an old oversight: when deleting variables from the vartypes,
delete them from the varset as well.
Conform to the change above.
compiler/liveness.m:
Avoid constructing and traversing a list unnecessarily.
Conform to the change above.
compiler/accumulator.m:
compiler/add_heap_ops.m:
compiler/add_trail_ops.m:
compiler/arg_info.m:
compiler/build_mode_constraints.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/clause_to_proc.m:
compiler/closure_analysis.m:
compiler/code_gen.m:
compiler/code_loc_dep.m:
compiler/complexity.m:
compiler/continuation_info.m:
compiler/cse_detection.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.util.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/direct_arg_in_out.m:
compiler/disj_gen.m:
compiler/equiv_type_hlds.m:
compiler/exception_analysis.m:
compiler/float_regs.m:
compiler/follow_code.m:
compiler/goal_mode.m:
compiler/goal_path.m:
compiler/hlds_out_pred.m:
compiler/hlds_rtti.m:
compiler/hlds_statistics.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/intermod_analysis.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/lambda.m:
compiler/lco.m:
compiler/live_vars.m:
compiler/loop_inv.m:
compiler/mark_tail_calls.m:
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_closure_gen.m:
compiler/ml_gen_info.m:
compiler/ml_proc_gen.m:
compiler/mode_info.m:
compiler/modecheck_goal.m:
compiler/modes.m:
compiler/par_loop_control.m:
compiler/pd_debug.m:
compiler/pd_info.m:
compiler/pd_util.m:
compiler/polymorphism_info.m:
compiler/proc_gen.m:
compiler/purity.m:
compiler/push_goals_together.m:
compiler/quantification.m:
compiler/rbmm.add_rbmm_goal_infos.m:
compiler/rbmm.live_variable_analysis.m:
compiler/rbmm.points_to_graph.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_liveness_info.m:
compiler/rbmm.region_transformation.m:
compiler/recompute_instmap_deltas.m:
compiler/saved_vars.m:
compiler/simplify_goal_unify.m:
compiler/simplify_info.m:
compiler/simplify_proc.m:
compiler/size_prof.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.indirect.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/switch_detection.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_initial.m:
compiler/term_errors.m:
compiler/term_pass1.m:
compiler/term_pass2.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/unneeded_code.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/unused_imports.m:
Conform to the change 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.
|
||
|
|
28589be990 | Minor updates of comments. | ||
|
|
9cbe5d2caf |
Put type_repn items for complex types into .int files.
compiler/decide_type_repn.m:
Previously, this module computed type_repn items to put into .int3 files
for a subset of the type constructors defined in the current module:
the direct_dummy, enum and notag types (the *simple* types),
and the du types whose representation is guaranteed to be
a word-aligned pointer when targeting C. (We care about pointers
being word-aligned only when applying the direct arg optimization.
This optimization is applicable only with the low level data
representation, which we use only when targeting C.)
This diff adds code to decide the representations of *all* the
type constructors defined in the current module.
This code is based on the existing code in du_type_layout.m,
which it is intended to eventually replace, but its job is more general,
because it decides the representation of each type not just for
one platform (the one we want to generate code), but for all possible
platforms. This is because we want to put the descriptions of type
representations into the module's .int file to serve as a single source
of truth for all modules that use the types defined in this module,
and the contents of .int files should be platform-independent.
For our purposes, there are six kinds of platforms, which are
distinguished along three axes: 64 vs 32 bit machines, spf vs non-spf
grades, and direct arg optimization enabled vs disabled. That is eight
combinations, but on 64 bit machines, a float takes up one word whether
that float is single or double precision, so two combinations aren't valid.
Some of the change to this module consists of generalizing the existing
code so that it can decide simple types not just when targeting .int3 files
but .int files as well. However, the bulk of it is code for deciding
the representations of non-simple types. The code is not lifted straight
from du_type_layout.m. There are two main kinds of changes.
First, I took the opportunity to simplify the algorithms used.
For example, while du_type_layout.m passes over each function symbol
in the most general kind of type twice: once to assign it a cons_tag,
and once to decide how to pack its arguments, the code here does both jobs
in one pass. Another example is that for historical reasons,
du_type_layout.m computed the amount of space needed for an argument
in one place for sub-word-sized arguments, and in another place
for more-than-word-sized arguments; decide_type_repn.m does it all
in one place.
Second, since we compute a representation for each type six times,
I tried to avoid obvious inefficiencies, but only if the code
remained simple. In the future, we may want to use an approach
based on the idea that in the process of computing the first
representation, we look out for any indication that the representation
may be different on any of the other five platforms, and if not,
we just reuse the first representation on the other five platforms as well.
However, that would be appropriate only *after* we have a simpler
system that has proven to work in practice.
There is a third, smaller change: when deciding whether an argument
is packable, we take into account not just equivalence type
definitions, but the definitions of notag types as well.
This takes advantage of the fact that if a notag type is abstract
exported, its representation is put into the relevant .int3 file
even though its definition isn't. (This is why du_type_layout.m
couldn't "see through" notag types: it couldn't depend on knowing
which types were notags.)
compiler/prog_item.m:
Change the types we use for type representation information.
Their previous definitions baked in the assumption that the only
distinction between platforms that mattered was the 64 vs 32 bit
distinction, which is not the case.
Use a more consistent naming scheme for the types we use
to represent type representation information.
Include the "dereferenced" types of the arguments in functors'
representations. (I use "dereferencing" here to mean expanding
equivalence types and throwing away any notag wrappers.).
We don't need it when generating C code using the low level
data representation, but we do need it to create constructors
when generating e.g. Java code that uses the high level data
representation.
compiler/parse_type_repn.m:
Rewrite most of this module due to the changes in prog_item.m.
compiler/parse_tree_out_type_repn.m:
A new module containing the code for writing out type representations.
The original code used to be in parse_tree_out.m, but it has been
mostly rewritten. Partly this is due the changes in prog_item.m,
but partly it is to provide much more structured output for humans,
since this makes debugging so much easier.
compiler/parse_tree.m:
Add the new module to the parse_tree package.
compiler/parse_tree_out.m:
Delete the code moved to parse_tree_out_type_repn.m.
compiler/parse_tree_out_info.m:
Provide a mechanism for selecting between output for machines
(the default) and output for humans.
compiler/hlds_data.m:
compiler/prog_data.m:
Move the ptag type from hlds_data.m to prog_data.m, to make it
accessible in prog_item.m.
Add some documentation in prog_data.m.
compiler/comp_unit_interface.m:
If the experiment1 option is enabled, invoke decide_type_repn.m
to decide what type_repn items to put into the .int file we are
generating. Otherwise, maintain the status quo.
compiler/write_module_interface_files.m:
Pass the globals to comp_unit_interface.m so it can look up experiment1.
compiler/equiv_type.m:
Add a predicate for expanding equivalence types for use by
decide_type_repn.m. This predicate expands just one type,
but reports any use of circular equivalence types in that type.
Improve the error message for circular equivalence types by *naming*
the type constructors involved. To make this possible, pass around
sets of such type constructors instead of just a boolean saying
*whether* we have found *some* circular equivalence type.
Replace bools used as changed/unchanged flag with a bespoke type.
Standardize some variable names.
compiler/options.m:
Add the developer-only option --pack-everything, which, if set,
tells decide_type_repn.m to turn on all the packing options
that currently work. This is to allow the testing of decide_type_repn.m
in the eventual intended mode of operation, even if the various
allow-packing-... options used by du_type_layout.m are set to "no".
compiler/disj_gen.m:
compiler/equiv_type_hlds.m:
compiler/llds_out_data.m:
compiler/lookup_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/mlds_to_c_data.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/tag_switch.m:
Conform to the changes above (mostly the move of ptag to prog_data.m.)
compiler/parse_pragma.m:
Improve indentation.
tests/valid_make_int/test_repn.m:
tests/valid_make_int/test_repn_sub.m:
A fairly comprehensive test case of the new functionality.
test_repn_sub.m defines one ore more simple type constructors
of each possible kind, and test_repn.m uses them to define types
that use each possible kind of complex type representation.
tests/valid_make_int/Mmakefile:
tests/valid_make_int/Mercury.options:
Enable the new test case.
|
||
|
|
b66f45e4db |
Tighten the mlds_type type.
compiler/mlds.m:
Make two changes to mlds_type.
The simpler change is the deletion of the maybe(foreign_type_assertions)
field from the MLDS representations of Mercury types. It was never used,
because Mercury types that are defined in a foreign language that is
acceptable for the current MLDS target platform are represented
as mlds_foreign_type, not as mercury_type.
The more involved change is to change the representation of builtin types.
Until now, we had separate function symbols in mlds_type to represent
ints, uints, floats and chars, but not strings or values of the sized
types {int,uint}{8,16,32,64}; those had to be represented as Mercury types.
This is an unnecessary inconsistency. It also had two allowed
representations for ints, uints, floats and chars, which meant that
some of the code handling those conceptual types had to be duplicated
to handle both representations.
This diff provides mlds_builtin_type_{int(_),float,string,char} function
symbols to represent every builtin type, and changes mercury_type
to mercury_nb_type to make clear that it is NOT to be used for builtins
(the nb is short for "not builtin").
compiler/ml_code_util.m:
compiler/ml_util.m:
Delete functions that used to construct MLDS representations of builtin
types. The new representation of those types is so simple that using
such functions is no less cumbersome than writing down the representations
directly.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_rename_classes.m:
compiler/ml_simplify_switch.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_c_stmt.m:
compiler/mlds_to_c_type.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_stmt.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mlds_to_java_wrap.m:
compiler/rtti_to_mlds.m:
Conform to the changes above.
|
||
|
|
86f563a94d |
Pack subword-sized arguments next to a remote sectag.
compiler/du_type_layout.m:
If the --allow-packing-remote-sectag option is set, then try to pack
an initial subsequence of subword-sized arguments next to remote sectags.
To allow the polymorphism transformation to put the type_infos and/or
typeclass_infos it adds to a function symbol's argument list at the
*front* of that argument list, pack arguments next to remote sectags
only in function symbols that won't have any such extra arguments
added to them.
Do not write all new code for the new optimization; instead, generalize
the code that already does a very similar job for packing args next to
local sectags.
Delete the code we used to have that picked the packed representation
over the base unpacked representation only if it reduced the
"rounded-to-even" number of words. A case could be made for its usefulness,
but in the presence of the new optimization the extra code complexity
it requires is not worth it (in my opinion).
Extend the code that informs users about possible argument order
rearrangements that yield better packing to take packing next to sectags
into account.
compiler/hlds_data.m:
Provide a representation for cons_tags that use the new optimization.
Instead of adding a new cons_tag, we do this by replacing several old
cons_tags that all represent pointers to memory cells with a single
cons_tag named remote_args_tag with an argument that selects among
the old cons_tags being replaced, and adding a new alternative inside
this new type. The new alternative is remote_args_shared with a
remote_sectag whose size is rsectag_subword(...).
Instead of representing the value of the "data" field in classes
on the Java and C# backends as a strange kind of secondary tag
that is added to a memory cell by a class constructor instead of
having to be explicitly added to the front of the argument vector
by the code of a unification, represent it more directly as separate
kind of remote_args_tag. Continuing to treat it as a sectag would have
been very confusing to readers of the code of ml_unify_gen_*.m in the
presence of the new optimization.
Replacing several cons_tags that were usually treated similarly with
one cons_tag simplifies many switches. Instead of an switch with that
branches to the same switch arm for single_functor_tag, unshared_tag
and shared_remote_tag, and then switches on these three tags again
to get e.g. the primary tag of each, the new code of the switch arm
is executed for just cons_tag value (remote_args_tag), and switches
on the various kinds of remote args tags only when it needs to.
In is also more natural to pass around the argument of remote_args_tag
than to pass around a variable of type cons_tag that can be bound to only
single_functor_tag, unshared_tag or shared_remote_tag.
Add an XXX about possible further steps along these lines, such as
making a new cons_tag named something like "user_const_tag" represent
all user-visible constants.
compiler/unify_gen_construct.m:
compiler/unify_gen_deconstruct.m:
compiler/unify_gen_test.m:
compiler/unify_gen_util.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:
Implement X = f(Yi) unifications where f uses the new representation,
i.e. some of its arguments are stored next to a remote sectag.
Some of the Yi are stored in a tagword (a word that also contains a tag,
in this case the remote secondary tag), while some are stored in other
words in a memory cell. This means that such unifications have similarities
both to unifications involving arguments being packed next to local
sectags, and to unifications involving ordinary arguments in memory cells.
Therefore wherever possible, their implemenation uses suitably generalized
versions of existing code that did those two jobs for two separate kinds of
cons_tags.
Making such generalizations possible in some cases required shifting the
boundary between predicates, moving work from a caller to a callee
or vice versa.
In unify_gen_deconstruct.m, stop using uni_vals to represent *either* a var
*or* a word in a memory cell. While this enabled us to factor out some
common code, the predicate boundaries it lead to are unsuitable for the
generalizations we now need.
Consistently use unsigned ints to represent both the whole and the parts
of words containing packed arguments (and maybe sectags), except when
comparing ptag constants with the result of applying the "tag" unop
to a word, (since that unop returns an int, at least for now).
In a few cases, avoid the recomputation of some information that we
already know. The motivation is not efficiency, since the recomputation
we avoid is usually cheap, but the simplification of the code's correctness
argument.
Use more consistent terminology in things such as variable names.
Note the possibility of further future improvements in several places.
compiler/ml_foreign_proc_gen.m:
Delete a long unused predicate.
compiler/mlds.m:
Add an XXX documenting a possible improvement.
compiler/rtti.m:
Update the compiler's internal representation of RTTI data structures
to make them able to describe secondary tags that are smaller than
a full word.
compiler/rtti_out.m:
Conform to the changes above, and delete a long-unused predicate.
compiler/type_ctor_info.m:
Use the RTTI's du_hl_rep to represent cons_tags that distinguish
between function symbols using a field in a class.
compiler/ml_type_gen.m:
Provide a specialized form of a function for code in ml_unify_gen_*.m.
Conform to the changes above.
compiler/add_special_pred.m:
compiler/bytecode_gen.m:
compiler/export.m:
compiler/hlds_code_util.m:
compiler/lco.m:
compiler/ml_closure_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/rtti_to_mlds.m:
compiler/switch_util.m:
compiler/tag_switch.m:
Conform to the changes above.
runtime/mercury_type_info.h:
Update the runtime's representation of RTTI data structures to make them
able to describe remote secondary tags that are smaller than a full word.
runtime/mercury_deconstruct.[ch]:
runtime/mercury_deconstruct.h:
runtime/mercury_deconstruct_macros.h:
runtime/mercury_ml_expand_body.h:
runtime/mercury_ml_arg_body.h:
runtime/mercury_ml_deconstruct_body.h:
runtime/mercury_ml_functor_body.h:
These modules collectively implement the predicates in deconstruct.m
in the library, and provide access to its functionality to other C code,
e.g. in the debugger. Update these to be able to handle terms with the
new data representation optimization.
This update requires a significant change in the distribution of work
between these files for the predicates deconstruct.deconstruct and
deconstruct.limited_deconstruct. We used to have mercury_ml_expand_body.h
fill in the fields of their expand_info structures (whose types are
defined in mercury_deconstruct.h) with pointers to three vectors:
(a) a vector of arg_locns with one element per argument, with a NULL
pointer being equivalent to a vector with a given element in every slot;
(b) a vector of type_infos with one element per argument, constructed
dynamically (and later freed) if necessary; and (c) a vector of argument
words. Once upon a time, before double-word and sub-word arguments,
vector (c) also had one word per argument, but that hasn't been true
for a while; we added vector (a) help the consumers of the expand_info
decode the difference. The consumers of this info always used these
vectors to build up a Mercury term containing a list of univs,
with one univ for each argument.
This structure could be stretched to handle function symbols that store
*all* their arguments in a tagword next to a local sectag, but I found
that stretching it to cover function symbols that have *some* of their
arguments packed next to a remote sectag and *some other* of their
arguments in a memory cell as usual would have required a well-nigh
incomprehensibly complex, and therefore almost undebuggable, interface
between mercury_ml_expand_body.h and the other files above. This diff
therefore changes the interface to have mercury_ml_expand_body.h
build the list of univs directly. This make its code relatively simple
and self-contained, and it should be somewhat faster then the old code
as well, since it never needs to allocate, fill in and then free
vectors of type_infos (each such typeinfo now gets put into a univ
as soon as it is constructed). The downside is that if we ever wanted
to get all the arguments at once for a purpose other than constructing
a list of univs from them, it would nevertheless require constructing
that list of univs anyway as an intermediate data structure. I don't see
this downside is significant, because (a) I don't think such a use case
is very likely, and (b) even if one arises, debuggable but a bit slow
is probably preferable to faster but very hard to debug.
Reduce the level of indentation of some of these files to make the code
easier to edit. Do this by
- not adding an indent level from switch statements to their cases; and
- not adding an indent level when a case in a switch has a local block.
Move the break or return ending a case inside that case's block,
if it has one.
runtime/mercury_deep_copy_body.h:
runtime/mercury_table_type_body.h:
Update these to enable the copying or tabling of terms whose
representations uses the new optimization.
Use the techniques listed above to reduce the level of indentation
make the code easier to edit.
runtime/mercury_tabling.c:
runtime/mercury_term_size.c:
Conform to the changes above.
runtime/mercury_unify_compare_body.h:
Make this code compile after the changes above. It does need to work
correctly, since we only ever used this code to compare the speed
of unify-by-rtti with the speed of unify-by-compiler-generated-code,
and in real life, we always use the latter. (It hasn't been updated
to work right with previous arg packing changes either.)
library/construct.m:
Update to enable the code to construct terms whose representations
uses the new optimization.
Add some sanity checks.
library/private_builtin.m:
runtime/mercury_dotnet.cs.in:
java/runtime/Sectag_Locn.java:
Update the list of possible sectag kinds.
library/store.m:
Conform to the changes above.
trace/mercury_trace_vars.c:
Conform to the changes above.
tests/hard_coded/deconstruct_arg.{m,exp,exp2}:
Extend this test to test the deconstruction of terms whose
representations uses the new optimization.
Modify some of the existing terms being tested to make them more diverse,
in order to make the output easier to navigate.
tests/hard_coded/construct_packed.{m,exp}:
A new test case to test the construction of terms whose
representations uses the new optimization.
tests/debugger/browse_packed.{m,exp}:
A new test case to test access to the fields of terms whose
representations uses the new optimization.
tests/tabling/test_packed.{m,exp}:
A new test case to test the tabling of terms whose
representations uses the new optimization.
tests/debugger/Mmakefile:
tests/hard_coded/Mmakefile:
tests/tabling/Mmakefile:
Enable the new test cases.
|
||
|
|
cebda224a6 |
Simplify some code.
And user standard variable names in more places. |
||
|
|
582ba08c80 |
Harmonize unify_gen{,_util}.m with their MLDS counterparts.
This diff begins a process to make the code in the LLDS and MLDS backends
use similar code, using similar predicate names and predicate code structures,
similar type structures, and even similar variable names, for their similar
tasks in generating code for unifications. Where possible, this process
should make the predicates handling different kinds of unifications
even within the *same* backend use similar data- and code structures
and variable names.
The convention for names is that when two predicates do the same job
in the two backends, then if the predicate name in the LLDS backend is X,
then the predicate name in the MLDS backend is ml_X. This preserves the
usefulness of the tags file.
compiler/unify_gen.m:
compiler/ml_unify_gen.m:
Mold the predicates that dispatch on the kind of unification being done
(assign, test, construct or deconstruct) into similar structures.
Make both these modules handle assignment and simple test unifications
using similar code.
compiler/unify_gen_util.m:
compiler/ml_unify_gen_util.m:
Give predicates and functions that do similar jobs in these two modules
similar names. Document some of the reasons for differences between
the backends that are not immediately obvious.
Delete an output argument from a predicate that was always given the
same value.
compiler/unify_gen_construct.m:
compiler/ml_unify_gen_construct.m:
Make a start on harmonizing the contents of these two modules
by making them process the various kinds of constants
in the same order for dynamic unifications.
compiler/unify_gen_deconstruct.m:
compiler/ml_unify_gen_deconstruct.m:
Make these modules handle *every* aspect of generating code for
deconstruction unifications, not just *some*, to simplify the boundary
between then and unify_gen.m/ml_unify_gen.m.
compiler/unify_gen_test.m:
Delete the predicate handling simple test unifications, since it has now
been moved to unify_gen.m. (The MLDS backend never had a separate
predicate for this task in the first place.)
compiler/ml_unify_gen_test.m:
Improve some comments.
compiler/closure_gen.m:
compiler/ml_closure_gen.m:
Use similar names for predicates that generate code for construct
unifications that create closures.
compiler/ml_code_gen.m:
Conform to a predicate name change in ml_unify_gen.m.
|
||
|
|
1fb59caa47 |
Split up 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:
Carve these four modules out of ml_unify_gen.m. The first two handle
the construction and deconstruction of terms, the third tests whether
a variable is bound to a given cons_id, and the fourth contains utility
types and predicates needed by more than one of the other modules.
compiler/ml_unify_gen.m:
Remove the code moved to the modules above.
compiler/ml_backend.m:
compiler/notes/compiler_design.html:
Add and document the new modules.
compiler/Mercury.options:
Require the new modules to have consistency between the order of predicate
declarations and the order of predicate definitions.
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_top_gen.m:
Conform to the change above.
|
||
|
|
b06b2621b3 |
Move towards packing args with secondary tags.
compiler/hlds_data.m:
Add bespoke types to record information about local and remote secondary
tags. The one for local secondary tags includes the value of the
primary and secondary tag together, since construct unifications
need to assign this value, and it is better to compute this once,
instead leaving the target language compiler to do it, potentially
many times.
Use a wrapped uint8 to record primary tag values, and wrapped uints
to record secondary tag values. The wrap is to prevent any accidental
confusion with other values. The use of uint8 and uint has two purposes.
First, using the tighest possible representation. Tags are never negative,
and primary tags cannot exceed 7. Second, using these types in the compiler
help us eat our own dogfood; if a change causes a problem affecting
these types, its bootcheck should fail, alerting us to the problem.
Add commented-out types and fields that will be needed for packing
sub-word-sized arguments together with both local and remote secondary
tags.
compiler/du_type_layout.m:
Generate references to tags in the new format.
compiler/ml_unify_gen.m:
compiler/unify_gen.m:
compiler/modecheck_goal.m:
Conform to the changes above.
Fix an old bug: the inst corresponding to a constant with a primary
and a local secondary tag is not the secondary tag alone, but both tags
together.
compiler/bytecode.m:
compiler/bytecode_gen.m:
compiler/closure_gen.m:
compiler/disj_gen.m:
compiler/export.m:
compiler/hlds_code_util.m:
compiler/jumpopt.m:
compiler/lco.m:
compiler/llds_out_data.m:
compiler/llds_out_instr.m:
compiler/lookup_switch.m:
compiler/lookup_util.m:
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_type_gen.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_stmt.m:
compiler/opt_debug.m:
compiler/peephole.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/string_switch.m:
compiler/switch_util.m:
compiler/tag_switch.m:
compiler/type_ctor_info.m:
Conform to the change to hlds_data.m.
In two places, in rtti_out.m and rtti_to_mlds.m, delete old code
that was needed only to implement reserved tags, which we have
stopped supporting a few months ago.
library/uint8.m:
library/uint16.m:
library/uint32.m:
library/uint64.m:
Add predicates to cast from each of these types to uint.
|
||
|
|
ec6a40ed85 |
Put related args of ml_field next to each other.
compiler/mlds.m:
Put the *type* of the pointer next to the *value* of the pointer.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_rename_classes.m:
compiler/ml_string_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/ml_unused_assign.m:
compiler/ml_util.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
compiler/rtti_to_mlds.m:
Conform to the change above.
|
||
|
|
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.
|
||
|
|
b9afc8b78e |
Delete the mlds_unary_op type.
compiler/mlds.m:
We used to have a function symbol ml_unop in the mlds_rval type
that applied one of four kinds of operations to an argument mlds_rval:
boxing, unboxing, casting or a standard unary operation, with a value
of type mlds_unary_op selecting between the four. Replace this system
with four separate function symbols in the mlds_rval type directly,
and delete the mlds_unary_op type.
The new arrangement requires fewer memory cells to be allocated,
and less indirection; it also leads to shorter and somewhat
more readable code.
compiler/ml_optimize.m:
Conform to the change above.
Recognize that a cast has negligible cost.
compiler/ml_code_util.m:
Conform to the change above.
Keep private a predicate that is not used by any other module,
after merging it with another previously-exported predicate
that only *it* uses.
Delete some other predicates that are not used anywhere.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_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_rename_classes.m:
compiler/ml_string_switch.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unused_assign.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:
compiler/rtti_to_mlds.m:
Conform to the change above.
|
||
|
|
24b98fdafe |
Pack sub-word-sized ints and dummies in terms.
Previously, the only situation in which we could pack two or more arguments
of a term into a single word was when all those arguments are enums. This diff
changes that, so that the arguments can also be sub-word-sized integers
(signed or unsigned), or values of dummy types (which occupy zero bits).
This diff also records, for each argument of a function symbol, not just
whether, and if yes, how it is packed into a word, but also at *what offset*
that word is in the term's heap cell. It is more economical to compute this
once, when the representation of the type is being decided, than to compute
it over and over again when terms with that function symbol are being
constructed or deconstructed. However, for a transition period, we compute
these offsets at *both* times, to check the consistency of the new algorithm
for computing offsets that is run at "decide representation time" with
the old algorithms run at "generate code for a unification time".
compiler/du_type_layout.m:
Make the changes described above: pack sub-word-sized integers and
dummy values into argument words, if possible, and if the relevant
new option allows it. These options are temporary. If we find no problems
with the new packing algorithm in a few weeks, we should be able to
delete them.
Allow 64 bit ints and uints to be stored in unboxed in two words
on 32 bit platforms, if the relevant new option allows it. Support
for this is not yet complete, but it makes sense to implement the
RTTI changes for both this change and one described in the above
paragraph together.
For each packed argument, record not just its width, its shift and
the mask, but also the number of bits the argument takes. Previously,
we computed this on demand from the mask, but there is no real need
for that when simply storing this info is so cheap.
For all arguments, packed or not, record its offset, relative to both
the start of the arguments, and the start of the memory cell. (The two
are different if the arguments are preceded by either a remote secondary
tag, the typeinfos and/or typeclass_infos describing some existentially
typed arguments, or both.) The reason for this is given at the top.
Centralize the decision of the parameters of packing in one predicate.
If the option --inform-suboptimal-packing is given, print an informational
message whenever the code deciding type representations finds that
reordering the arguments of a function symbol would allow it to pack
the arguments of that function symbol into less space.
compiler/options.m:
Add the option --allow-packing-ints which controls whether
du_type_layout.m will attempt to pack {int,uint}{8,16,32} arguments
alongside enum arguments.
Add the option --allow-packing-dummies which controls whether
du_type_layout.m will optimize away (in other words, represent in 0 bits)
arguments of dummy types.
Add the option --allow-double-word-ints which controls whether
du_type_layout.m will store arguments of the types int64 and uint64
unboxed in two words on 32 bit platforms, the way it currently stores
double precision floats.
All three those options are off by default, which preserves binary
compatibility with existing code. However, the first two are ready
to be switched on (the third is not).
All three options are intended to be present in the compiler
only until these changes are tested. Once we deem them sufficiently
tested, I will modify the compiler to always do the packing they control,
at which point we can delete these options. This is why they are not
documented.
Add the option --inform-suboptimal-packing, whose meaning is described
above.
doc/user_guide.texi:
Document --inform-suboptimal-packing.
compiler/prog_data.m:
For each argument of a function symbol in a type definition, use
a new type called arg_pos_width to record the extra information
mentioned above in (offsets for all arguments, and number of bits
for packed arguments).
For each function symbol that has some existential type constraints,
record the extra information mentioned for parse_type_defn.m below.
compiler/hlds_data.m:
Include the position, as well as the width, in the representation
of the arguments of function symbols.
Previously, we used the integer 0 as a tag for dummies. Add a tag to
represent dummy values, since this gives more information to any code
that sees that tag.
compiler/ml_unify_gen.m:
compiler/unify_gen.m:
Handle the packing of dummy values, and of sub-word-sized ints and uints.
Compare the cell offset of each argument computed using existing
algorithms here with the cell offset recorded in the argument's
representation, and abort if they are different.
In some cases, restructure code a bit to make it possible.
For example, for tuples and closures, this means that instead of
simply recording that each tuple argument or closure element
is a full word, we must record its correct offset as well.
Handle the new dummy_tag.
Add prelim (not yet finished) support for double-word int64s/uint64s
on 32 bit platforms.
When packing the values of two or more variables (or constants) into a
single word in a memory cell, optimize away operations that are no-ops,
such as shifting anything by zero bits, shifting the constant zero
by any number of bits, and ORing anything with zero. This makes the
generated code easier to read. It is probably also faster for us
to do it here than to write out a bigger expression, have the C compiler
read in the bigger expression, and then later make the same optimization.
In ml_unify_gen.m, avoid the unnecessary use of a list of the argument
variables' types separate from the list of the argument variables
themselves; just look up the type of each argument variable when it is
processed.
compiler/add_special_pred.m:
When creating special (unify and compare) predicates for tuples,
include the offsets in the representation of their arguments.
Delete an unused predicate.
compiler/llds.m:
Add a new way to create an rval: a cast. We use it to implement
the extraction of signed sub-word-sized integers from packed argument
words in terms. Masking the right N bits out of the packed word
leaves the other 32-N or 64-N bits as zeroes; a cast to int8_t,
int16_t or int32_t will copy the sign bit to these bits.
Likewise, when we pack signed int{8,16,32} values into words,
we cast them to their unsigned versions to throw away any sign-extension
bits in their original word-sized representations.
No similar change is needed for the MLDS, since that already had
a mechanism for casts.
compiler/mlds.m:
Note a potential simplification in the MLDS.
compiler/builtin_lib_types.m:
Add functions to return the Mercury representation of the int64
and uint64 types.
compiler/foreign.m:
Export a specialized version of an existing predicate, to allow
ml_unify_gen.m to avoid the costs of the more general version.
compiler/hlds_out_module.m:
Always print the representations of all arguments, since the
inclusion of position information in those representation means that
the representations of even all-full-word-argument terms are of potential
interest when debugging term representations.
compiler/lco.m:
Do not try to apply LCO to arguments of dummy types. (We could optimize
them differently, by filling them in before they are "computed", but
that is a separate optimization, which is of *very* low priority.)
compiler/liveness.m:
Do not include variables of dummy types in resume points.
The reason for this is that the code that establishes a resume point
returns, for each such variable, a list of *lvals* where that variable
can be found. The new code in unify_gen.m will optimize away assignments
to values of dummy types, so there is *no* lval where they can be found.
We could allocate one, but doing so would be a pessimization. Instead,
we simply don't save and restore such values. When their value (which is
always 0) is needed, we can create them out of thin air.
compiler/ml_global_data.m:
Include the target language in the ml_global_data structure, to prevent
some of its users having to look it up in the module_info.
Add notes about the specializing the implementation of arrays of
int64s/uint64s on 32 bit platforms.
compiler/check_typeclass.m:
compiler/ml_type_gen.m:
Add sanity checks of the new precomputed fields of exist_constraints.
Conform to the changes above.
compiler/mlds_to_c.m:
Add prelim (not yet finished) support for double-word int64s/uint64s
on 32 bit platforms.
Add notes about possible optimizations.
compiler/parse_type_defn.m:
When a function symbol in a type definition contains existential
arguments, precompute and store the set of constrained and unconstrained
type variables. The code in du_type_layout.m needs this information
to compute the number of slots occupied by typeinfos and typeclass_infos
in memory cells for this function symbol, and several other places
in the compiler do too. It is easier and faster to compute this
information just once, and this is the earliest time what that can be done.
compiler/type_ctor_info.m:
Use the prerecorded information about existential types to simplify
the code here
compiler/polymorphism.m:
Add an XXX about possibly using the extra info we now record in
exist_constraints to simplify the job of polymorphism.m.
compiler/pragma_c_gen.m:
compiler/var_locn.m:
Create the values of dummy variables from scratch, if needed.
compiler/rtti.m:
Replace a bool with a bespoke type.
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
When generating RTTI information for the LLDS and MLDS backends
respectively, record new kinds of arguments as needing special
treatment. These are int64s and uint64s stored unboxed in two words
on 32 bit platforms, {int,uint}{8,16,32} values packed into words,
and dummy arguments. Each of these has a special code: its own negative
negative value in the num_bits field of the argument.
Generate slightly better formatted output.
compiler/type_util.m:
Delete a predicate that isn't needed anymore.
compiler/opt_util.m:
Delete a function that hasn't been needed for a while.
Conform to the changes above.
compiler/arg_pack.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/code_util.m:
compiler/ctgc.selector.m:
compiler/dupelim.m:
compiler/dupproc.m:
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/erl_code_gen.m:
compiler/erl_rtti.m:
compiler/export.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_out_data.m:
compiler/middle_rec.m:
compiler/ml_closure_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_top_gen.m:
compiler/module_qual.qualify_items.m:
compiler/opt_debug.m:
compiler/parse_tree_out.m:
compiler/peephole.m:
compiler/recompilation.usage.m:
compiler/resolve_unify_functor.m:
compiler/stack_layout.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/switch_util.m:
compiler/typecheck.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
Conform to the changes above.
compiler/llds_out_util.m:
Add a comment.
compiler/ml_code_util.m:
Factor out some common code.
runtime/mercury_type_info.h:
Allocate special values of the MR_arg_bits field of the MR_DuArgLocn type
to designate arguments as two word int64/uint64s, as sub-word-sized
arguments of types {int,uint}{8,16,32}, or as arguments of dummy types.
(We already had a special value for two word float arguments.)
Document the list of places that know about this code, so that they
can be updated if and when it changes.
library/construct.m:
Handle the construction of terms with two-word int64/uint64 arguments,
with packed {int,uint}{8,16,32} arguments, and with dummy arguments.
Factor out the code common to the sectag-present and sectag-absent cases,
to make it possible to do the above in just *one* place.
library/store.m:
Add an XXX to a place that I don't think handles two word arguments
correctly. (I think this is an old bug.)
runtime/mercury_deconstruct.c:
Handle the deconstruction of terms with two-word int64/uint64 arguments,
with packed {int,uint}{8,16,32} arguments, and with dummy arguments.
runtime/mercury_deep_copy_body.h:
Handle the copying of terms with two-word int64/uint64 arguments,
with packed {int,uint}{8,16,32} arguments, and with dummy arguments.
Give a macro a more descriptive name.
runtime/mercury_type_info.c:
Handle taking the size of terms with two-word int64/uint64 arguments,
with packed {int,uint}{8,16,32} arguments, and with dummy arguments.
runtime/mercury.h:
Put related definitions next to each other.
runtime/mercury_deconstruct.h:
runtime/mercury_ml_expand_body.h:
Fix indentation.
tests/hard_coded/construct_test.{m,exp}:
Add to this test case a test of the construction, via the library's
construct.m module, of terms containing packed sub-word-sized integers,
and packed dummies.
tests/hard_coded/deconstruct_arg.{m,exp}:
Convert the source code of this test case to state variable notation,
and update the line number references (in the names of predicates created
from lambda expressions) accordingly.
tests/hard_coded/uint64_ground_term.{m,exp}:
A new test case to check that uint64 values too large to be int64 values
can be stored in static structures.
tests/hard_coded/Mmakefile:
Enable the new test case.
|
||
|
|
447ad53ae6 |
Group widths together with arg vars and rvals.
compiler/ml_unify_gen.m:
Add a type that groups a Mercury type and a width together with
a representation of an argument (usually a program variable).
Add a type that groups an MLS type and a width together with
an mlds_rval.
Pair representations of arguments with their types and widths
as soon as possible. Later on, process the resulting list of groups,
instead of two or three lists that had to have the same length
(one element for each argument).
When transforming these triples into rvals, keep the width of the rval
associated with it, instead of returning it in a separate list,
and use this data structure when creating cells on the heap.
(Doing likewise for static cells will come in another diff.)
compiler/vartypes.m:
Add a function version of a predicate for ml_unify_gen.m to make
a closure of.
compiler/ml_closure_gen.m:
Conform to the change in the interface of ml_unify_gen.m.
|
||
|
|
8d0597f97d |
Use typed rvals in the MLDS code generator.
compiler/mlds.m:
Introduce the concept of typed rvals to the MLDS (it is already present
in the LLDS).
To start with, use typed rvals to represent the arguments of the new_object
operation.
compiler/ml_accurate_gc.m:
compiler/ml_closure_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_rename_classes.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 in the new_object operation. In most places,
this means replacing two lists (one of rvals, and one of types)
that had to have the same length, with one list of typed rvals.
The use of typed rvals thus encodes a required invariant in the
type of the data, making its violation impossible. It also means
that many places that used to require iterating on two lists
simultaneously can be replaced by a simple iteration on one list only.
|
||
|
|
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.
|
||
|
|
577cffb940 |
Make the flags on function and class definitions concrete.
compiler/mlds.m:
I made the types of flags on the definitions of variables (global,
local and field) concrete types a while ago. This diff does the same
for the flags on the definitions of functions and classes.
The abstraction barrier may have bought us something when the definitions
of *everything* in the MLDS used the *same* flag type, but it does not buy
us anything useful anymore, and in fact it makes some things harder to see.
Rename the access type the function_access type, since only function
definitions use it now.
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_proc_gen.m:
compiler/ml_type_gen.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 in mlds.m.
In some places, the diff replaces code that updates some components
of a flag with code that totally replaces the flag; the abstract nature
of the old interface hid the fact that the "some components" actually
were *all* the components.
Inline the functions that compute values of flags that are called
from only one place.
|
||
|
|
dad5c99140 |
Delete the attribute field in MLDS function definitions.
compiler/mlds.m:
Delete the attribute field in MLDS function definitions, because
we have never used it.
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Delete the code that ignored the attribute field in function definitions
*without* writing it out.
compiler/ml_proc_gen.m:
compiler/ml_type_gen.m:
Delete code that filled in this field.
compiler/ml_closure_gen.m:
compiler/ml_code_util.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_target_util.m:
Delete code that copied this field around.
|
||
|
|
756ed140d3 |
Improve non-tail recursion warnings from the MLDS code generator.
Consider two mutually recursive procedures p and q, where p tailcalls q
but q does not tailcall p. The LLDS backend can optimize the tailcall
from p to q, but the MLDS backend cannot, because it can optimize only
*mutual* tail recursion. In such cases, and in other cases where the
MLDS cannot implement a recursive call as a tail call even though the
LLDS backend can, add to the warning message we generate a description
of the reason why the MLDS code generator cannot do what the programmer
may expect them to do.
compiler/ml_gen_info.m:
Include in the state of the MLDS code generator tail-call-related
information not just about all the procedures in the current TSCC,
but about all the procedures in the current SCC. And instead of
storing warning messages about non-tail recursive calls in the code
generator state, store a list of the non-tail recursive calls themselves.
These two changes together allow us to gather a description of all
the non-tail recursive calls before we generate even the first warning.
This should allow a later to use this information to generate messages
such as "the recursive call from p to q here cannot be optimized
because the recursive call from q to p at this *other* context
cannot be optimized".
Make the names of some types and function symbols clearer.
compiler/ml_call_gen.m:
Whenever a recursive call cannot be optimized as a tail call,
record the reason behind that fact.
Use pred_proc_ids instead of separate pred_ids and proc_ids,
since this simplifies the code and should speed paramater passing.
compiler/ml_proc_gen.m:
Pass tail-call-related information about the procedures of the SCC along
as we generate code for the SCC's procedures.
Once we have generated code for all of the SCC's procedures,
turn the final list of the non-tail calls in the SCC into a list
of warnings for them.
compiler/options.m:
doc/user_guide.texi:
Add a compiler option that controls whether we report as non-tail
calls recursive calls that *obviously* cannot be tail calls, because
they are followed by other recursive calls. The standard example
is the first recursive call in qsort.
A comment by Paul has long called for such an option, and this diff
touches the same code anyway.
Fix an unrelated old blemish: document both of the old options
--warn-non-tail-recursion-{self,mutual}, but in a commented out form,
since they are internal-use options. Before this diff, only one was
documented, and only user_guide.texi.
compiler/mark_tail_calls.m:
Add parameters to the predicates that generate warnings that specify
why the recursive call cannot be optimized as a tail call (describing
the reason if it is a result of a limitation in the compiler, and
not a problem in the program being compiled), and whether the call
is obviously a non-tail call.
When marking a call as recursive, but the recursive call is obviously
not a tail call, mark it as such using a new goal feature. The MLDS
backend needs this to allow it to filter warnings for obviousness
the same way as mark_tail_calls.m itself.
compiler/hlds_goal.m:
Add the new goal feature mentioned above.
compiler/ml_closure_gen.m:
compiler/ml_tailcall.m:
compiler/rtti_to_mlds.m:
compiler/saved_vars.m:
Conform to the changes above.
tests/invalid/require_tailrec_1.err_exp2:
tests/invalid/require_tailrec_2.err_exp2:
tests/invalid/require_tailrec_3.err_exp2:
Add the expected warnings from the MLDS code generator.
tests/invalid/Mercury.options:
Specify -E for one of the tests above, to test the handling of the
verbose-only part of the warnings.
tests/EXPECT_FAIL_TESTS.hlc.gc:
Do not expect tests/invalid/require_tailrec_[123] to fail
in grade hlc.gc anymore.
|
||
|
|
49e89ef569 |
Extend mutual tail recursion optimization to functions.
Det functions have a copy-out output argument, i.e. the return value,
which is *not* returned by reference. So instead of handling such arguments
like this:
arg_type * tscc_output_var_N;
HeadVarN = tscc_output_var_N;
...
... body of procedure assigns to *HeadVarN
...
return;
we handle them like like this:
arg_type tscc_output_var_N;
...
... body of procedure assigns to HeadVarN
...
tscc_output_var_N = HeadVarN;
return tscc_output_var_N;
For the non-C backends, there may be more than one return value.
This scheme should work for them as well, but until that is tested,
it is not turned on.
compiler/ml_args_util.m:
When computing the information needed for tscc arguments, don't assume
that there are no copy-out output arguments. Instead, compute the
information ml_proc_gen.m needs to handle them. This means returning
a full function signature (including return values), the list of rvals
to return, and the list of pre-return assignment statements.
Simplify the code of ml_append_return_statement. Since ml_proc_gen.m
now computes its own return statements (based on the information mentioned
in the previous paragraph) by making it handle only the situation it was
originally designed for: simple procedure bodies that are *not* parts
of TSCCs. Simplify its code also by requiring its callers to give it
the return values as rvals, not lvals, because the callers can give it
the return values in this form just as easily, and it is more efficient,
since it lets us avoid the construction of a list.
compiler/ml_proc_gen.m:
Let det functions be part of TSCCs. Handle their return values as described
above. Handle the construction of return statements for procedure bodies
in TSCCs separately from return statements in standalone procedures.
compiler/ml_closure_gen.m:
Conform to the changes in ml_args_util.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.
|
||
|
|
d412bd410e |
Use arg tuples to simplify more code.
compiler/ml_args_util.m:
I recently changed most predicates that generate a description
of a procedure's parameter passing interface by first constructing
a tuple for each parameter containing the information that is relevant
to the decision about how that parameter should be passed. This diff
makes those predicates return these tuples, since some callers can
also benefit from having this information in this convenient form.
Use this kind of tuple when generating a description of the input
parameters of mutually-tail-recursive procedures.
Change ml_gen_args and its friends (the predicates that generate code
for actually passing parameters) to take information about the value
being passed as ml_call_args, which have either one of two forms.
One is just the prog_var being passed; the other is a tuple containing
the MLDS var representing the parameter, its lval, and its actual type
(which may differ from the type of the corresponding formal parameter,
by being its instance). The former should be used far more frequently
(the second is used only when constructing closure wrapper functions),
and in this case, our caller will have to construct just one list
(a list of wrapped prog_vars) instead of three (the MLDS var names,
the MLDS var lvals, and the actual types), and will have to do fewer tests.
Export the copy_out_when type, and the function that computes the right
copy_out_when value for a given procedure, for use by ml_closure_gen.m.
In some predicates, put related parameters together.
In some predicates, change the names of variables to state explicitly
whether they contain information about the caller or the callee side
of parameter passing.
Use Head and Tail prefixes in variable names more consistently.
compiler/ml_call_gen.m:
Use ml_call_args to represent the arguments of calls.
In some predicates, put related parameters together.
In some predicates, change the names of variables to state explicitly
whether they contain information about the caller or the callee side
of parameter passing.
compiler/ml_code_gen.m:
When handling calls, simply pass the argument variables to ml_call_gen.m;
let *it* decide how it wants to construct the argument passing code.
compiler/ml_closure_gen.m:
Use ml_call_args (in their more complicated form) to represent
the arguments of the single unusual call inside closure wrapper
function definitions. (It is unusual because some parameters
are not HLDS variables.)
Use the tuple description of the callee's parameters to simplify
the code generating the lvals used as the arguments of that call.
In some predicates, put related parameters together.
compiler/ml_proc_gen.m:
Use the tuples constructed by ml_args_util.m to describe procedures'
arguments to simplify the code that boxes or unboxes arguments as needed.
compiler/ml_top_gen.m:
Conform to the changes in ml_args_util.m.
|
||
|
|
977f5b54be |
Use just one piece of code to make a decision again.
compiler/ml_proc_gen.m:
Use the recently unified code in ml_args_util.m to partition a procedure's
output arguments into the set of arguments passed by reference and the set
of output arguments returned via a return statement, instead of doing
its job yet again in *two* separate predicates (ml_det_copy_out_vars
for model det/semi procedures, and ml_set_up_initial_success_cont
for model non procedures).
Also, avoid the old dance where the ml_gen_info's by_ref_outputs field
was initialized to contain *all* output arguments, using a *third*
algorithm, and then had one of the two predicates mentioned above
overwrite this incorrect-to-specification value with the correct value,
i.e. the *actual* set of arguments passed by reference.
The three algorithms mentioned here differed from each other in whether
they considered top_out arguments to be outputs if their type was
a dummy type. The only reason this inconsistency wasn't a problem was that
the generated code was affected only by the code in ml_args_util.m,
and the versions *there* are consistent (they do NOT consider them
to be outputs).
compiler/ml_gen_info.m:
Do not set the by_ref_outputs field to the set of all outputs,
since ml_proc_gen.m does not need this anymore. Instead, leave
a value explicitly identified as a dummy there.
compiler/ml_args_util.m:
To make the change in ml_proc_gen.m possible, make the predicates
that compute the parameter list of a procedure return the HLDS variables
containing (a) the byref nondummy output args, and (b) the copied
(i.e. returned via return statement) nondummy output args.
Those predicates thus now require, for each argument, its HLDS variable,
as well as its MLDS variable, its type and its top_functor_mode.
Instead of passing four separate lists of equal length, two of which
we have to construct (the ModuleInfo already contains lists of the
arg vars and their types, but we have to compute the MLDS var and the
top_functor_mode for each arg), construct and pass a list of tuples,
one tuple per argument, since this makes the argument classification code
simpler. (The new approach allocates a tuple and a cons cell per arg,
while the old approach allocated two cons cells here, and more in
ml_proc_gen.m and ml_gen_info.m when they did their redundant copies
of this work.)
compiler/ml_closure_gen.m:
Don't generate argument lists for wrapper procedures with incorrect
gc statements, only to delete those statements; generate them with
no gc statements to start with. Besides being the right thing to do,
this allows us to delete a variant of the "generate the parameter list
for this procedure" in ml_args_util.m that was specific to this call site.
compiler/ml_call_gen.m:
Conform to the change in ml_args_util.m.
|
||
|
|
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.
|
||
|
|
c3fb6d4d42 | Replace a bool with a bespoke type. | ||
|
|
217a363181 |
Fix unreachable return statements.
My recent change to ml_args_util.m broke bootchecking in java grades,
because it added an explicit return statement after every procedure body,
even those that end with target language code that throws an exception.
The Java compiler generates an error for throws followed by returns.
compiler/ml_args_util.m:
Append a return statement after procedure bodies that don't return
anything only if an option asks us to do so.
compiler/ml_proc_gen.m:
When generating code for single procedure bodies, let ml_args_util.m
not add return statements.
When generating code for procedure bodies in TSCCs, require ml_args_util.m
to add return statements, since without that, when one procedure succeeds,
you would get a fall-through to the start of the next procedure in the
TSCC. To make sure this return does not cause any problems, don't include
procedures that cannot succeed in TSCCs.
compiler/ml_closure_gen.m:
Conform to the change in ml_args_util.m.
|
||
|
|
bbd6c44a26 |
Create ml_args_util.m.
Both ml_code_util.m and ml_call_gen.m had predicates that used the same logic
to process lists of arguments. This is not a coincidence; they both process
argument lists, one from the point of the callee, the other from the point
of view of the caller. These have to be kept in lockstep. This is easier
if they are next to each other. This diff therefore moves those predicates
to the same module, a new module named ml_args_util.m.
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
Delete the new code now in ml_args_util.m.
compiler/ml_args_util.m:
The new module.
compiler/ml_backend.m:
compiler/notes/compiler_design.html:
Mention the new module.
compiler/ml_closure_gen.m:
compiler/ml_proc_gen.m:
compiler/ml_top_gen.m:
compiler/rtti_to_mlds.m:
Conform to the changes above.
|
||
|
|
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.
|
||
|
|
da9808036c |
Implement self-tail-call optimization in the MLDS code generator.
This is a step towards implementing not just self- but also mutual
tail recursion in the MLDS code generator.
compiler/options.m:
Add an option, --optimize-tailcalls-codegen, that asks for MLDS backend
to optimize self tail calls via the code generator, not ml_tailcall.m.
(We still use ml_tailcall.m if the new option is not set.) The new option
is set by default, but this can be changed if we find a problem
with the new approach.
compiler/mark_tail_calls.m:
Fix a bug. In a disjunction, the nonlast disjuncts cannot contain tail
calls, because (a) if a nonlast disjunct is semidet, then after any
such recursive call fails, we can still backtrack to later disjuncts,
and (b) if the nonlast disjunct involved is det, the later disjuncts
should have been optimized away, and the disjunct wouldn't be nonlast
anymore.
Export predicates that allow the MLDS backend to mark tail calls
as *it* wants them marked.
Reorganize the predicates that generate warnings to make them useable
from the MLDS code generator as well, and export the required predicates.
(The MLDS code generator needs this access because in some cases,
a call that mark_tail_calls.m thinks is a tail call cannot be implemented
as such. Since only the MLDS code generator knows this fact, only *it*
can know when this warning may need to be generated.)
Some of the reorganization of code that generates warnings factors out
common code between mark_tail_calls.m and ml_tailcall.m.
compiler/ml_tailcall.m:
Export some functionality for the code generator to use.
Replace the found_recursive_call type, which used to be defined here,
with the found_any_rec_calls type from mark_tail_calls.m, since they
were isomorphic and had the same job.
Delete the code that was factored out into mark_tail_calls.m.
compiler/mercury_compile_mlds_back_end.m:
If --optimize-tailcalls-codegen is set, run the mark_tail_calls pass
before MLDS codegen.
Prepare for the code generator to generate warnings about calls that should
be tail calls not actually being tail calls.
Delete an unused exported predicate, and the imports it used to need.
compiler/mercury_compile_llds_back_end.m:
Fix style.
compiler/ml_gen_info.m:
Extend the code generator state with information needed for tail call
optimization, and for generating warnings.
compiler/ml_proc_gen.m:
When starting to generate code for a procedure, set up the new part
of the code generator state with the information needed to handle tail
calls, if we both (a) can optimize tail calls in the predicate, and (b)
we have been asked to.
After the code for the procedure body has been generated, *and* if
we have actually turned some tail calls into jumps to the start of
the procedure, create the wrapper around the MLDS code implementing
the body goal that makes such jumps possible.
compiler/ml_call_gen.m:
When generating code for a plain call, test whether it is a tail call,
and if so, try to optimize it. If we fail, generate a warning about
that fact, and fall back to generating code for it as we would do
for any non-tail call.
Provide mechanisms for this new code to compute the actual parameter
lvals for the input arguments of a (tail) call, since only these
have to be assigned from when replacing a tail call.
compiler/ml_code_util.m:
Provide mechanisms for ml_proc_gen to compute the mlds_arguments
of the formal parameters of just the input arguments of a procedure,
since only these have be assigned to when replacing a tail call.
(The predicates that perform these mirror image tasks should be
next to each other, perhaps in a new ml_args_util.m module.)
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_optimize.m:
Export to ml_call_gen.m (a slightly modified form of) a predicate
that is used in the replacement of tail calls.
Peephole optimization a pattern that we now generate.
compiler/rtti_to_mlds.m:
Conform to the changes above.
tests/hard_coded/semi_tail_call_in_nonlast_disjunct.{m,exp}:
Add a test case for the bug fixed in mark_tail_calls.m. Without the fix,
the updated MLDS code generator's output fails this test.
tests/hard_coded/Mmakefile:
Enable the new test case.
|
||
|
|
9517a05242 |
Rename some ambiguous predicates.
compiler/ml_code_util.m:
As above.
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_proc_gen.m:
Conform to the change above.
|
||
|
|
c3d8d7a1a7 |
Fix two problems related to function names.
The first problem is that the MLDS constructs that defined functions and
the MLDS constructs that take the addresses of functions used different
data types to *name* those functions. The translations of these constructs
to each target language had to generate the same target language code,
but they did so via two (or in some cases more) separate pieces of code.
The second problem is that the MLDS functions that implement HLDS procedures,
and the auxiliary functions that are sometimes needed to help implement
those procedures, were not delineated as clearly as is they should be.
compiler/mlds.m:
To (mostly) fix the first problem, define the mlds_func_label type,
and use it to identify MLDS functions in both function definitions
and in the mlds_code_addr type that represents a reference to a function.
A full fix will require function definitions to use *qualified*
mlds_func_labels, as the mlds_code_addrs already do. However,
the problem that MLDS definitions are not qualified applies not just
to functions but to other entities as well, and is therefore better fixed
separately.
To fix the second problem, introduce the mlds_maybe_aux_func_id type.
This also addresses an old XXX by providing explicit ways to represent
gc trace functions for both auxiliary and non-auxiliary MLDS functions.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_gen_info.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_rename_classes.m:
compiler/ml_tailcall.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:
compiler/rtti_to_mlds.m:
Conform to the above.
|
||
|
|
f4ab258e36 | Improve some comments and a predicate name. | ||
|
|
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.
|
||
|
|
b390231f22 |
Use mlds_target_lang in the MLDS backend.
The overall compilation target language (which is recorded in the globals)
can be C, Java, C# or Erlang. The target language of the MLDS backend
can only be the first three. Use the mlds_target_lang type (which has
three functors) instead of the compilation_target type (which has four)
to make target-specific decisions in the MLDS backend.
compiler/mercury_compile_mlds_back_end.m:
Compute the MLDS target (which can be C, Java or C#) from the compilation
target (which can also be Erlang).
compiler/ml_closure_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_proc_gen.m:
compiler/ml_string_switch.m:
compiler/ml_tag_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds.m:
compiler/rtti_to_mlds.m:
Use the mlds_target_lang value computed in mercury_compile_mlds_back_end.m
to make decisions. Code in most modules get this from the ml_gen_info;
in some others, it is passed around, usually instead of the globals.
compiler/ml_code_util.m:
Unify two separate copies of a comment.
|
||
|
|
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.
|
||
|
|
30ec420984 |
Fix an anomaly in how in MLDS treats scalar commons.
compiler/mlds.m:
The MLDS used to have two different ways to refer to scalar common
data structures. It had an rval for the *name* of the scalar common,
and an mlds_name for its *address*. The name could then be wrapped up
inside a mlconst_data_adr function symbol to convert it to rval.
An mlds_name is intended to be used for the names of data definitions
in the MLDS, but scalar commons were never defined in this way.
And the name and address of a scalar common differ in C only by
the addition of an "&" operator in front, so the fact that they
had to be processed by different code (due to them having different types)
*required* double maintenance.
This diff fixes this anomaly by making both the name and the address
of a scalar common its own specific function symbol in the mlds_rval type.
They differ in the presence or absence of an "_addr" suffix.
Since all references to a vector common are to its address, give
the existing mlds_rval function symbol for vector commons the "_addr
suffix as well, for consistency.
Replace the general mlconst_data_addr function symbol in the
mlds_rval_const with its remaining instances. This allows the code
constructing them to be smaller and simpler, and enables them
to be treated differently in the future, if needed.
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Conform to the changes in mlds.m.
Put the code translating the various common structures next to each other,
where they werent' before. Add XXXs about the differences between them
that are probably unnecessary and may possibly be latent problems.
compiler/ml_util.m:
Conform to the changes in mlds.m.
Change the interface to a set of predicates that looks for variables
inside various MLDS constructs to take a variable name, not a data name,
as the thing being looked for.
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_string_switch.m:
compiler/ml_tailcall.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_target_util.m:
compiler/rtti_to_mlds.m:
Conform to the changes in mlds.m, and maybe ml_util.m.
In ml_proc_gen.m, put related arguments of some predicates and functions
next to each other.
|
||
|
|
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.
|
||
|
|
761de42e28 |
Tighten the type of flags in mlds_class_defns.
compiler/mlds.m:
As above.
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_proc_gen.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:
Conform to the change above.
|
||
|
|
91ba5278bc |
Tighten the type of flags in mlds_data_defns.
compiler/mlds.m:
As above.
compiler/ml_util.m:
Delete the predicate that returned the flags of *every* kind of definition
as a value of a single type.
Add a utility predicate used by both mlds_to_{cs,java}.m.
Delete utility predicates all of whose uses in the files below
this diff replaces with other code.
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_proc_gen.m:
compiler/ml_type_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 above.
In mlds_to_c.m, simplify some other related code.
|
||
|
|
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.
|
||
|
|
e2878130d8 |
Tighten the representation of mlds_arguments.
The mlds_argument type describes an argument of an MLDS function: its name,
its type and information about how to trace it for accurate gc. However,
it represented the argument name as an entity name, so the representation
in theory allowed the argument name *itself* to be a type, a function,
the name of a global variable holding rtti information etc. However, the
only kind of entity name that ever made sense is a variable name, and there
were some places in the compiler that threw an exception if they found
the argument name to be any kind of entity name other than a variable name.
compiler/mlds.m:
Change the representation of the name in each mlds_argument
from an entity name to a variable name.
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/mlds_to_c.m:
Conform to the change above. Mostly this is by using VarNames directly,
not wrapping them up as entity_data(mlds_data_var(VarName)).
In several places, it is by not having to remove this wrapping.
And in a few places, it is by adding the wrapping back, to allow
interfacing to code that has good reason to expect entity names.
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
As above, but additionally, rename some predicates involved in handling
entity and variable names.
For predicates that used to have different definitions but identical names
in these two files, give them a "for_csharp" or "for_java" suffix
to avoid the ambiguity, and thus make tags files work better.
Convert some related predicates from clauses to explicit disjunctions.
|
||
|
|
cfcfde1db7 |
Simplify the representation of modes of unifications.
Unifications (x = y) have long had two descriptions of their modes.
One is the unify_mode, which used to look like this:
(initx -> finalx) - (inity -> finaly)
and other is the uni_mode, which used to look like this:
(initx - inity) -> (finalx - finaly)
Each unification had one unify_mode, and each unification that includes
a function symbol had one uni_mode per argument of that function symbol.
The two forms of mode information looked similar enough to be easily
confusable, but were subtly different. As it turns out, there was no
particular reason for the difference, so this diff eliminates the
uni_mode type, and the difference along with it.
What rationale there was for the uni_mode type was that the two modes
it represented (one for each side of the unification) both had their
initial and final insts directly available. This is not true for modes
in general: a value of the mer_mode type could have the form
"InitInst -> FinalInst" (which this diff renames "from_to_mode(InitInst,
FinalInst)", but could also be a "user_defined_inst(...)", which required
a table lookup to turn it into an initial/final pair of insts. This matters,
because almost all code that processes the modes of unifications
works with the initial and final insts.
This diff therefore creates a new type, from_to_insts, which represents
mode information only in the form of terms such as "from_to_insts(InitInst,
FinalInst)", and makes a unify_mode take two values of this type, not mer_mode,
as arguments.
As discussed on m-rev, this diff also renames the old, deceptively named
"arg_mode" type: its new name is "top_functor_mode".
compiler/prog_data.m:
compiler/hlds_goal.m:
As mentioned above, avoid using "->" as a function symbol, and replace
both -> and - with bespoke function symbols.
compiler/mode_util.m:
Add some utility predicates and functions on the new types, and
delete the old utility routines that operated on uni_modes.
Code that uses the new functions and predicates should have a higher level
of abstraction than the code that used to do the same job "manually".
compiler/*.m:
Conform to the changes above, using the new utility predicates and
functions where relevant. In several cases, this required fixing
confusion of the kind described at the top. In all but one case,
the confusion affected only variable names, but in one case,
deconstruct_functor in make_goal.m, it caused a bug. The bug has
had no effect up till now because deconstruct_functor is called
only from three places: try_expand.m, stm_expand.m, and untupling.m.
The incorrect mode (which was the nonsensical ground -> free)
generated by the code of try_expand.m itself was discarded and
overwritten when try_expand.m invoked the modechecker. (I don't
know whether this bugfix makes that invocation redundant or not.)
The other two modules, stm_expand.m and untupling.m, may do something
similar, but in any case, they don't yet work for other reasons.
(A bootcheck with --untupling causes a compiler abort when compiling
deep_profiler/query.m in stage 2 both without and with this fix.)
Delete no-longer-needed imports of the pair module (and of some other
modules).
Put the arguments of some predicates into a more logical order.
In bytecode_gen.m, replace clauses with disjunctions, and delete the
arguments that this step has revealed to be unused.
|
||
|
|
5890311825 |
Fix some unused predicate warnings.
browser/browse.m:
browser/declarative_edt.m:
compiler/continuation_info.m:
compiler/hlds_out_goal.m:
compiler/llds_out_file.m:
compiler/make.dependencies.m:
compiler/ml_closure_gen.m:
compiler/ml_elim_nested.m:
compiler/options_file.m:
compiler/prog_io_pragma.m:
deep_profiler/html_format.m:
Delete some dead predicates that won't be needed anymore.
compiler/hlds_goal.m:
compiler/jumpopt.m:
Comment out some dead predicates that may be needed later.
compiler/matching.m:
compiler/typecheck.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Convert some dead predicates into live predicates by adding calls to them
at their intended call sites. In some cases the missing call was a sort-of
bug (the code worked, but not as well as it should have). In others, the
call was intended only for debugging, and the new call is in a trace scope
that is disabled by default.
compiler/ml_foreign_proc_gen.m:
Add an XXX comment about a dead procedure.
|