Commit Graph

29 Commits

Author SHA1 Message Date
Zoltan Somogyi
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.
2022-04-18 02:00:38 +10:00
Zoltan Somogyi
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.
2022-03-28 10:20:49 +11:00
Zoltan Somogyi
6a915eef05 Optimize field updates inside packed arg words.
Since june, we have been copying words containing packed-together
sub-word-sized arguments all in one piece if possible, for hlc grades.
This means that given a type such as

:- type t
    --->    f1(int8, bool, int8, int, bool, int8, bool).

whose first three and last three arguments are packed into one word each,
and a predicate such as

    p(T0, T) :-
        T0 = f1(A, B, C, _, E, F, G),
        D = 42,
        T  = f1(A, B, C, D, E, F, G).

we generated code such as

    MR_Integer D_12 = (MR_Integer) 42;
    MR_Unsigned packed_args_0 =
        (MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 0)));
    MR_Unsigned packed_args_1 =
        (MR_Unsigned) ((MR_hl_field(MR_mktag(0), T0_3, (MR_Integer) 2)));

    base = (MR_Word) MR_new_object(MR_Word,
        ((MR_Integer) 3 * sizeof(MR_Word)), NULL, NULL);
    *T_4 = base;
    MR_hl_field(MR_mktag(0), base, 0) = (MR_Box) (packed_args_0);
    MR_hl_field(MR_mktag(0), base, 1) = ((MR_Box) (D_12));
    MR_hl_field(MR_mktag(0), base, 2) = (MR_Box) (packed_args_1);

which does NOT pick up the values A, B, C, E, F and G individually.
However, until now, we could reuse packed-together words only in their
unchanged form.

This diff lifts that limitation, which means that now, we can *also*
optimize code such as

    p(T0, T) :-
        T0 = f1(A, B, _, D, E, _, G),
        C = 42i8,
        F = 43i8,
        T  = f1(A, B, C, D, E, F, G).

by generating code like this:

    base = (MR_Word) MR_new_object(MR_Word,
        (3 * sizeof(MR_Word)), NULL, NULL);
    *T_4 = base;
    MR_hl_field(MR_mktag(0), base, 0) = (MR_Box)
        ((((packed_word_0 & (~((MR_Unsigned) 255U)))) |
        (MR_Unsigned) ((uint8_t) (C_12))));
    MR_hl_field(MR_mktag(0), base, 1) = ((MR_Box) (D_8));
    MR_hl_field(MR_mktag(0), base, 2) = (MR_Box)
        ((((packed_word_1 & (~((MR_Unsigned) 510U)))) |
        (((MR_Unsigned) ((uint8_t) (F_13)) << 1))));

The general scheme when reusing *part* of a word is: first set the bits
not being reused to zero, and then OR in new values of those bits.

Make this optimization as general as possible by making it work
not just for

- words in memory cells containing only arguments,

but also for

- words in memory cells containing a remote sectag as well as arguments, and
- words in registers cells containing a ptag, a local sectag as well as
  arguments.

compiler/ml_gen_info.m:
    Generalize the data structure we use to represent information about
    packed words to make possible approximate as well as exact lookups.
    The key in the old map was "these bitfields with the values of these
    variables in them", while the key in the new map is just "these bitfields",
    with the associated value being a list, each element of which says
    "the word with these values in those bitfields is available in this rval".
    This makes it possible to look for matches words that have some, but not
    all, of the right values in the bitfields.

    Since the packed words may now contain tags as well as arguments,
    rename "packed args" to "packed word".

compiler/ml_unify_gen_deconstruct.m:
    When deconstructing a term containing packed words, add them to the
    packed word map even when one of the bitfields inside the packed word
    contains tag information.

    Move the code that adds a packed word to the map into a separate predicate,
    now that it is needed from more than one place.

compiler/ml_unify_gen_construct.m:
    Change the code that handles packed words to work in terms of filled
    bitfields. Use this not only to implement the optimization described
    at the top, but also to make the handling of bitfields more systematic.
    At least one previous bug was caused by doing sign extension differently
    for the bitfield containing the first packed argument in a word than for
    the later packed arguments in that word; with the new design, such
    inconsistencies should not happen.

compiler/ml_unify_gen_util.m:
    Add utility predicates now needed for both construct and deconstruct
    unifications.

compiler/mlds.m:
    Document the new use of lvnc_packed_word (renamed from lvnc_packed_args).

compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
    Conform to the changes above (mostly the packed_word rename).

compiler/mlds_to_c_data.m:
compiler/mlds_to_c_stmt.m:
    Omit unneeded casts from the output. Specifically, don't put (MR_Integer)
    casts in front of integer constants being used either as shift amounts,
    or as the number of words that a new_object MLDS operation should allocate.
    The casts only cluttered the output, making it harder to read, and
    therefore to judge its correctness.
2018-09-10 16:17:17 +10:00
Zoltan Somogyi
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.
2018-06-02 18:56:40 +02:00
Zoltan Somogyi
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.
2018-02-28 13:48:44 +11:00
Zoltan Somogyi
234501be75 Remove ml_tailcall.m and associated code.
Now that we can optimize tail recursion for all MLDS targets better via
the MLDS code generator than via ml_tailcall.m, we don't need it anymore.

compiler/ml_tailcall.m:
    Delete this module.

compiler/ml_backend.m:
compiler/notes/compiler_design.html:
    Delete the inclusion and the documentation of the deleted module.

compiler/mark_tail_calls.m:
    Update old references to the deleted module, as well as some comments.

compiler/mercury_compile_mlds_back_end.m:
    Don't invoke the deleted module.

compiler/options.m:
    Delete the (developer-only) options that used to control whether
    we did tail call optimization (TCO) via ml_tailcall.m or not.

compiler/ml_optimize.m:
    Delete the parts of this module that worked in concert with ml_tailcall.m
    to implement TCO.

compiler/mlds.m:
    Delete the field from ml_call_stmts that was needed only by ml_tailcall.m.

compiler/ml_call_gen.m:
    Don't fill in the deleted field.

    Shift here the only part of the old contents of ml_tailcall.m that is
    still needed, the check for whether rvals would become dangling references
    if we discarded the current call's stack frame.

compiler/ml_elim_nested.m:
    Conform to the change to mlds.m, and eliminate an unused field
    in elim_info.

compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_proc_gen.m:
compiler/ml_rename_classes.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
    Conform to the changes above.
2017-11-10 14:26:32 +11:00
Zoltan Somogyi
5c43340b11 Implement TRO for model_non procedures.
The one thing that tail recursion optimization (TRO) via ml_tailcalls.m
could do that TRO via the MLDS code generator couldn't was TRO for model_non
procedures. This diff eliminates that difference.

compiler/mark_tail_calls.m:
    Don't blow off marking tail calls in model_non procedures.

    Add a new reason why TRO does not apply to a tail call. If the tail
    call is in a nondet continuation, then the code we generate for it
    will be in a nested function, which will end up in a *separate* function.
    Implementing the tail call as a continue that jumps to the start of a
    while loop that wraps the entire function body won't work, since continues
    won't work from functions other than the one that contains the while loop.

compiler/ml_gen_info.m:
    Add a field to the code generator state that gives the number of nested
    functions the about-to-be-generated code will end up inside.

compiler/ml_call_gen.m:
    Don't apply TRO to a call if this nesting level isn't zero, since
    in that case the generated code would end up in a different function.

compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
    Increment the function nesting level before starting to generate code
    that will end up in nested function, and decrement it afterwards.

compiler/ml_proc_gen.m:
    Allow model_non procedures to be subject to TRO.

    When generating the comment identifying a function that results from TRO
    for a single procedure, make it specify its code_model.
2017-10-12 23:04:06 +11:00
Zoltan Somogyi
996d689219 Support tail recursion between funcs and preds.
Generalize the mechanism we use to implement mutual tail recursion optimization
in the MLDS backend to handle TSCCs that contain both predicates and functions.
This generalization also simplifies the split of responsibilities between
the MLDS functions that implement each TSCC procedure for external callers
(which we now call the container function) on the one hand, and their main
components, the bodies of the procedures themselves (which we now call the
wrapped procedures, since each container function wraps up the bodies
of *all* the procedures in the TSCC).

In the new scheme, wrapped functions always give output arguments
to container functions by value. It is the job of the container functions
to return these output arguments to the caller according to the requirements
imposed by the container function's calling convention. This allows
different container functions to return output arguments differently
(some may return an output by value, while some may do so by reference)
while still allowing the wrapped procedure bodies to be generated just once
and then duplicated for each container function.

compiler/notes/mlds_tail_recursion.html:
    A new file explaining both the scheme we use to generate code for
    TSCCs, and the reasons why we use that scheme.

compiler/notes/Mmakefile:
    Include the new file in the list of compiler notes files.

compiler/ml_args_util.m:
    Update the code that generated code fragments handling arguments
    for TSCCs to follow the updated scheme. Use the terminology in the
    new notes file to clarify variable names where relevant. Group
    related arguments together.

compiler/ml_proc_gen.m:
    Update the code that created wrapped procedures and container functions
    to follow the updated scheme. Use the terminology in the new notes file
    to clarify both function and variable names where relevant. Delete the
    documentation which is now in notes/mlds_tail_recursion.html (in greatly
    enhanced form).

    Split the predicate for adding local variable definitions to MLDS
    functions, since when generating code for TSCCs using the new scheme,
    we only need one of its two halves.

compiler/mlds.m:
    Add the new forms of compiler generated variables needed by the new
    translation scheme.

compiler/ml_gen_info.m:
    Change the type of the field containing the byref output vars
    from a list to a set. All its users want to treat it as a set,
    so it is simpler and faster to convert it just once, when it is set,
    instead of on every use.

compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
    Conform to the change in ml_gen_info.m.
2017-10-10 02:40:16 +11:00
Zoltan Somogyi
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.
2017-09-12 00:52:39 +10:00
Zoltan Somogyi
f4e0059a49 Eliminate hlc_nest and hl_nest grades ...
... by eliminating the grade component that calls for the use of gcc nested
functions.

runtime/mercury_grade.h:
compiler/compute_grade.m:
    Delete the gcc_nested_functions grade component, and the C macro
    that specifies its presence, MR_USE_GCC_NESTED_FUNCTIONS.

scripts/canonical_grade.sh-subr:
scripts/init_grade_options.sh-subr:
scripts/mgnuc.in:
scripts/parse_grade_options.sh-subr:
    Delete the code that parses the deleted grade component,
    and delete the code that signals its absence in other grades.

compiler/options.m:
    Delete the gcc_nested_functions grade option.

    Delete also the gcc_local_labels option, since it was useful
    only if gcc_nested_functions was set.

configure.ac:
    Delete the code that sometimes added hl*_nest grades to the list of grades
    to be installed.

    Fix a bunch of comments.

compiler/compile_target_code.m:
compiler/handle_options.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_gen_info.m:
compiler/mlds_to_c.m:
library/backjump.m:
library/exception.m:
runtime/mercury_hlc_types.h:
runtime/mercury_tabling.c:
runtime/mercury_tabling.h:
    Delete code that was active only in grades with the deleted grade
    component.

compiler/ml_accurate_gc.m:
compiler/notes/grade_library.html:
runtime/mercury_conf_param.h:
    Delete mentions of the deleted grade component.

compiler/ml_code_gen.m:
    Delete mentions of the deleted grade component, and a bunch of other
    obsolete comments.

doc/user_guide.texi:
    Fix a line break.
2017-09-07 03:01:55 +10:00
Zoltan Somogyi
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.
2017-09-06 13:43:29 +10:00
Zoltan Somogyi
3ee7f79f9c Document the var_lvals field of ml_gen_info.
compiler/ml_gen_info.m:
    As above.

compiler/ml_commit_gen.m:
    Don't hide taking the snapshot of the var_lvals field in a subroutine.
    Take it explicitly in each predicate that later restores that snapshot,
    since having each save visibly paired with its restore simplifies
    the implicit correctness argument.
2017-08-17 13:16:15 +10:00
Zoltan Somogyi
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.
2017-08-09 18:23:53 +02:00
Zoltan Somogyi
bd3fd38c0d Delete the field for the "this" rval in MLDS calls.
This field of type maybe(mlds_rval) was *always* set to "no".

compiler/mlds.m:
    As above.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_rename_classes.m:
compiler/ml_tailcall.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mlds_to_target_util.m:
    Conform to the above.
2017-07-31 21:26:04 +02:00
Zoltan Somogyi
1c01ed85eb Fix lines. 2017-07-29 14:15:15 +02:00
Zoltan Somogyi
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.
2017-07-29 01:40:56 +02:00
Zoltan Somogyi
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.
2017-07-26 00:57:13 +02:00
Zoltan Somogyi
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.
2017-07-22 00:20:40 +02:00
Zoltan Somogyi
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.
2017-07-09 18:44:05 +02:00
Zoltan Somogyi
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.
2017-05-24 09:45:21 +02:00
Zoltan Somogyi
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.
2017-04-24 15:16:36 +10:00
Zoltan Somogyi
e5daa207fa Fix disabling warnings for non-tail recursive calls with MLDS.
compiler/mlds.m:
    Add a field to call statements in MLDS that contains a (probably empty)
    set of markers. At the moment, the only marker possible is one that says
    "don't generate a non-tail recursive call warning for this call".

compiler/ml_gen_info.m:
    Add a field to the ml_gen_info type, which contains the state of the
    MLDS code generator, that records the set of warnings that are disabled
    for the HLDS goal currently being translated.

compiler/ml_code_gen.m:
    When processing the subgoal inside a disable_warnings scope,
    add the warnings disabled by the scope to the new field
    in the ml_gen_info.

compiler/ml_call_gen.m:
    When creating MLDS call statements, put the new marker in the call's new
    field if goal_warning_non_tail_recursive_calls is among the currently
    disabled warnings.

compiler/ml_tailcall.m:
    Don't generate warnings about a recursive call not being *tail* recursive
    if the call has the new marker.

compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Conform to the changes above.
2017-01-19 20:47:26 +11:00
Zoltan Somogyi
cc9912faa8 Don't import anything in packages.
Packages are modules whose only job is to serve as a container for submodules.
Modules like top_level.m, hlds.m, parse_tree.m and ll_backend.m are packages
in this (informal) sense.

Besides the include_module declarations for their submodules, most of the
packages in the compiler used to import some modules, mostly other packages
whose component modules their submodules may need. For example, ll_backend.m
used to import parse_tree.m. This meant that modules in the ll_backend package
did not have to import parse_tree.m before importing modules in the parse_tree
package.

However, this had a price. When we add a new module to the parse_tree package,
parse_tree.int would change, and this would require the recompilation of ALL
the modules in the ll_backend package, even the ones that did NOT import ANY
of the modules in the parse_tree package.

This happened even at one remove. Pretty much all modules in every one
of the backend have to import one or more modules in the hlds package,
and they therefore have import hlds.m. Since hlds.m imported transform_hlds.m,
any addition of a new middle pass to the transform_hlds package required
the recompilation of all backend modules, even in the usual case of the two
having nothing to do with each other.

This diff removes all import_module declarations from the packages,
and replaces them with import_module declarations in the modules that need
them. This includes only a SUBSET of their child modules and of the non-child
modules that import them.
2015-11-13 15:03:20 +11:00
Zoltan Somogyi
7654ec847e Convert (C->T;E) to (if C then T else E). 2015-09-18 09:37:29 +10:00
Zoltan Somogyi
62ec97d443 Report imports shadowed by other imports.
If a module has two or more import_module or use_module declarations
for the same module, (typically, but not always, one being in its interface
and one in its implementation), generate an informational message about
each redundant declaration if --warn-unused-imports is enabled.

compiler/hlds_module.m:
    We used to record the set of imported/used modules, and the set of
    modules imported/used in the interface of the current module. However,
    these sets

    - did not record the distinction between imports and uses;
    - did not allow distinction between single and multiple imports/uses;
    - did not record the locations of the imports/uses.

    The first distinction was needed only by module_qual.m, which *did*
    pay attention to it; the other two were not needed at all.

    To generate messages for imports/uses shadowing other imports/uses,
    we need all three, so change the data structure storing such information
    for *direct* imports to one that records all three of the above kinds
    of information. (For imports made by read-in interface and optimization
    files, the old set of modules approach is fine, and this diff leaves
    the set of thus *indirectly* imported module names alone.)

compiler/unused_imports.m:
    Use the extra information now available to generate a
    severity_informational message about any import or use that is made
    redundant by an earlier, more general import or use.

    Fix two bugs in the code that generated warnings for just plain unused
    modules.

    (1) It did not consider that a use of the builtin type char justified
    an import of char.m, but without that import, the type is not visible.

    (2) It scanned cons_ids in goals in procedure bodies, but did not scan
    cons_ids that have been put into the const_struct_db. (I did not update
    the code here when I added the const_struct_db.)

    Also, add a (hopefully temporary) workaround for a bug in
    make_hlds_passes.m, which is noted below.

    However, there are at least three problems that prevent us from enabling
    --warn-unused-imports by default.

    (1) In some places, the import of a module is used only by clauses for
    a predicate that also has foreign procs. When compiled in a grade that
    selects one of those foreign_procs as the implementation of the predicate,
    the clauses are discarded *without* being added to the HLDS at all.
    This leads unused_imports.m to generate an uncalled-for warning in such
    cases. To fix this, we would need to preserve the Mercury clauses for
    *all* predicates, even those with foreign procs, and do all the semantic
    checks on them before throwing them away. (I tried to do this once, and
    failed, but the task should be easier after the item list change.)

    (2) We have two pieces of code to generate import warnings. The one in
    unused_imports.m operates on the HLDS after type and mode checking,
    while module_qual.m operates on the parse tree before the creation of
    the HLDS. The former is more powerful, since it knows e.g. what types and
    modes are used in the bodies of predicates, and hence can generate warnings
    about an import being unused *anywhere* in a module, as opposed to just
    unused in its interface.

    If --warn-unused-imports is enabled, we will get two separate set of
    reports about an interface import being unused in the interface,
    *unless* we get a type or mode error, in which case unused_imports.m
    won't be invoked. But in case we do get such errors, we don't want to
    throw away the warnings from module_qual.m. We could store them and
    throw them away only after we know we won't need them, or just get
    the two modules to generate identical error_specs for each warning,
    so that the sort_and_remove_dups of the error specs will do the
    throwing away for us for free, if we get that far.

    (3) The valid/bug100.m test case was added as a regression test for a bug
    that was fixed in module_qual.m. However the bug is still present in
    unused_imports.m.

compiler/make_hlds_passes.m:
    Give hlds_module.m the extra information it now needs for each item_avail.

    Add an XXX for a bug that cannot be fixed right now: the setting of
    the status of abstract instances to abstract_imported. (The "abstract"
    part is correct; the "imported" part may not be.)

compiler/intermod.m:
compiler/try_expand.m:
compiler/xml_documentation.m:
    Conform to the change in hlds_module.m.

compiler/module_qual.m:
    Update the documentation of the relationship of this module
    with unused_imports.m.

compiler/hlds_data.m:
    Document a problem with the status of instance definitions.

compiler/hlds_out_module.m:
    Update the code that prints out the module_info to conform to the change
    to hlds_module.m.

    Print status information about instances, which was needed to diagnose
    one of the bugs in unused_imports.m. Format the output for instances
    nicer.

compiler/prog_item.m:
    Add a convenience predicate.

compiler/prog_data.m:
    Remove a type synonym that makes things harder to understand, not easier.

compiler/modules.m:
    Delete an XXX that asks for the feature this diff implements.
    Add another XXX about how that feature could be improved.

compiler/Mercury.options.m:
    Add some more modules to the list of modules on which the compiler
    should be invoked with --no-warn-unused-imports.

compiler/*.m:
library/*.m:
mdbcomp/*.m:
browser/*.m:
deep_profiler/*.m:
mfilterjavac/*.m:
    Delete unneeded imports. Many of these shadow other imports, and some
    are just plain unneeded, as shown by --warn-unused-imports. In a few
    modules, there were a *lot* of unneeded imports, but most had just
    one or two.

    In a few cases, removing an import from a module, because it *itself*
    does not need it, required adding that same import to those of its
    submodules which *do* need it.

    In a few cases, conform to other changes above.

tests/invalid/Mercury.options:
    Test the generation of messages about import shadowing on the existing
    import_in_parent.m test case (although it was also tested very thoroughly
    when giving me the information needed for the deletion of all the
    unneeded imports above).

tests/*/*.{m,*exp}:
    Delete unneeded imports, and update any expected error messages
    to expect the now-smaller line numbers.
2015-08-25 00:38:49 +10:00
Zoltan Somogyi
d00ea69529 Switch from using set(prog_var), which is represented using set_ordlist,
Estimated hours taken: 12
Branches: main

Switch from using set(prog_var), which is represented using set_ordlist,
to set_of_progvar, which is represented using tree_bitset, for most sets
of variables in the compiler, including the nonlocals sets in goal_infos.

This diff yields about a 5% speedup when compiling the training_cars_full.m
stress test, but also about a 1% slowdown on tools/speedtest. Both of these
are with the current default state in which tree_bitset is compiled with
a whole bunch of sanity checks. If these are disabled, we get roughly a 1%
speedup on tools/speedtest. I intend to disable those sanity checks after
a shakedown period of a week or two in which the updated version of the
compiler is installed on our platforms.

compiler/hlds_goal.m:
	Replace almost all occurrences of set(prog_var) with set_of_progvar.
	The main exceptions are the types supporting rbmm.

compiler/set_of_var.m:
	Add some more predicates and functions that previous existed on sets
	but not yet on set_of_vars.

compiler/*.m:
	Conform to the change in hlds_goal.m, and make similar changes
	in set representations.

library/bag.m:
	Add a predicate and function for creating a bag from a sorted list.
	We already had them for creating a bag from a set, but a set_of_progvar
	shouldn't have to be converted to a set.

library/robdd.m:
	Fix deviations from our programming style.
2011-08-16 03:26:40 +00:00
Zoltan Somogyi
295415090e Convert almost all remaining modules in the compiler to use
Estimated hours taken: 6
Branches: main

compiler/*.m:
	Convert almost all remaining modules in the compiler to use
	"$module, $pred" instead of "this_file" in error messages.

	In a few cases, the old error message was misleading, since it
	contained an incorrect, out-of-date or cut-and-pasted predicate name.

tests/invalid/unresolved_overloading.err_exp:
	Update an expected output containing an updated error message.
2011-05-23 05:08:24 +00:00
Zoltan Somogyi
d73decfa45 Eliminate some now-redundant code.
Estimated hours taken: 0.5
Branches: main

Eliminate some now-redundant code.

compiler/ml_commit_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_code_util.m:
	Remove all the calls to ml_decl_is_static_const, since static constant
	definitions are no longer included in the list of definitions
	explicitly returned by the predicates of the code generator.

compiler/ml_code_util.m:
	Remove the now obsolete predicate.

compiler/rtti_to_mlds.m:
	Remove a reference to the deleted predicate.
2009-10-02 06:54:30 +00:00
Zoltan Somogyi
439e9d474d Divide the old 4100, 2900 and 4600 line modules ml_code_gen.m, ml_code_util.m
Estimated hours taken: 4
Branches: main

Divide the old 4100, 2900 and 4600 line modules ml_code_gen.m, ml_code_util.m
and modes.m into smaller, more cohesive modules. In the process, put
related predicates next to each other. There are no algorithmic changes.

compiler/ml_proc_gen.m:
	New module that looks after code generation tasks that affect a
	procedure as a whole. Its code is taken from the old ml_code_gen.m.
	Analogous to proc_gen.m, which does the same job for the LLDS backend.

compiler/ml_foreign_proc_gen.m:
	New module that generates code for foreign_proc goals.
	Its code is taken from the old ml_code_gen.m.
	Analogous to pragma_c_gen.m in the LLDS backend.

compiler/ml_commit_gen.m:
	New module that generates code for commit goals.
	Its code is taken from the old ml_code_gen.m.
	Analogous to commit_gen.m in the LLDS backend.

compiler/ml_gen_info.m:
	New module that encapsulates the ml_gen_info structure.
	Its code is taken from the old ml_code_util.m.
	Analogous to code_info.m in the LLDS backend.

compiler/ml_accurate_gc.m:
	New module that generates the data and goals needed for accurate gc.
	Its code is taken from the old ml_code_util.m.

compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
	Move some predicates that are used by other modules of the MLDS backend
	to ml_code_util, in order to avoid otherwise unneeded dependencies.

compiler/mode_util.m:
	Move a predicate here from ml_code_util.m, since it is needed by
	several MLDS backend modules but is not MLDS specific.

compiler/ml_code_gen.m:
	Remove the code moved to other modules.

	Delete an old note about a problem fixed long ago.

compiler/ml_code_util.m:
	Remove the code moved to other modules.

	Add the code moved here from other modules.

compiler/modecheck_conj.m:
	New module that handles mode analysis of conjunctions.
	Its code is taken from the old modes.m.

compiler/modecheck_goal.m:
	New module that handles mode analysis of most types of goals,
	except conjunctions, unifications and calls.
	Its code is taken from the old modes.m.

compiler/modecheck_util.m:
	New module containing utility predicates used more one of the modules
	do mode analysis. Its code is taken from the old modes.m.

compiler/mode_util.m:
	Move a predicate here from modes.m, since this is where a related
	predicate already is.

	Give a predicate a more meaningful name.

compiler/goal_util.m:
	Move a predicate here from modes.m, since this is where a related
	predicate already is.

compiler/modes.m:
	Remove the code moved to other modules.

compiler/ml_backend.m:
compiler/check_hlds.m:
	Add the new modules.

compiler/notes/compiler_design.html:
	Document the new modules.

compiler/prog_data.m:
	Give some function symbols disambiguating prefixes.

compiler/add_solver.m:
compiler/deforest.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/ml_lookup_switch.m:
compiler/ml_simplify_switch.m:
compiler/ml_string.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/modecheck_call.m:
compiler/modecheck_unify.m:
compiler/prog_io_type_defn.m:
compiler/rtti_to_mlds.m:
compiler/type_ctor_info.m:
compiler/unify_proc.m:
	Conform to the changes above.
2009-09-25 05:13:23 +00:00