Commit Graph

241 Commits

Author SHA1 Message Date
Zoltan Somogyi
a19a5f0267 Delete the Erlang backend from the compiler.
compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_backend.m:
compiler/erl_call_gen.m:
compiler/erl_code_gen.m:
compiler/erl_code_util.m:
compiler/erl_rtti.m:
compiler/erl_unify_gen.m:
compiler/erlang_rtti.m:
compiler/mercury_compile_erl_back_end.m:
    Delete these modules, which together constitute the Erlang backend.

compiler/notes/compiler_design.html:
    Delete references to the deleted modules.

compiler/parse_tree_out_type_repn.m:
    Update the format we use to represent the sets of foreign_type and
    foreign_enum declarations for a type as part of its item_type_repn_info,
    now that Erlang is no longer a target language.

compiler/parse_type_repn.m:
    Accept both the updated version of the item_type_repn_info and the
    immediately previous version, since the installed compiler will
    initially generate that previous version. However, stop accepting
    an even older version that we stopped generating several months ago.

compiler/parse_pragma_foreign.m:
    When the compiler finds a reference to Erlang as a foreign language,
    add a message about support for Erlang being discontinued to the error
    message.

    Make the code parsing foreign_decls handle the term containing
    the foreign language the same way as the codes parsing foreign
    codes, procs, types and enums.

    Add a mechanism to help parse_mutable.m to do the same.

compiler/parse_mutable.m:
    When the compiler finds a reference to Erlang as a foreign language,
    print an error message about support for Erlang being discontinued.

compiler/compute_grade.m:
    When the compiler finds a reference to Erlang as a grade component,
    print an informational message about support for Erlang being discontinued.

compiler/pickle.m:
compiler/make.build.m:
    Delete Erlang foreign procs and types.

compiler/add_foreign_enum.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_type.m:
compiler/check_libgrades.m:
compiler/check_parse_tree_type_defns.m:
compiler/code_gen.m:
compiler/compile_target_code.m:
compiler/compute_grade.m:
compiler/const_struct.m:
compiler/convert_parse_tree.m:
compiler/dead_proc_elim.m:
compiler/decide_type_repn.m:
compiler/deps_map.m:
compiler/du_type_layout.m:
compiler/export.m:
compiler/foreign.m:
compiler/globals.m:
compiler/granularity.m:
compiler/handle_options.m:
compiler/hlds_code_util.m:
compiler/hlds_data.m:
compiler/hlds_module.m:
compiler/inlining.m:
compiler/int_emu.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/lco.m:
compiler/llds_out_file.m:
compiler/make.dependencies.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_warn.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_code_util.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_target_util.m:
compiler/ml_top_gen.m:
compiler/mlds.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_export.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_export.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_type.m:
compiler/module_imports.m:
compiler/parse_pragma_foreign.m:
compiler/parse_tree_out.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/prog_data.m:
compiler/prog_data_foreign.m:
compiler/prog_foreign.m:
compiler/prog_item.m:
compiler/simplify_goal_scope.m:
compiler/special_pred.m:
compiler/string_encoding.m:
compiler/top_level.m:
compiler/uint_emu.m:
compiler/write_deps_file.m:
    Remove references to Erlang as a backend or as a target language.

tests/invalid/bad_foreign_code.{m,err_exp}:
tests/invalid/bad_foreign_decl.{m,err_exp}:
tests/invalid/bad_foreign_enum.{m,err_exp}:
tests/invalid/bad_foreign_export.{m,err_exp}:
tests/invalid/bad_foreign_export_enum.{m,err_exp}:
tests/invalid/bad_foreign_import_module.{m,err_exp}:
tests/invalid/bad_foreign_proc.{m,err_exp}:
tests/invalid/bad_foreign_type.{m,err_exp}:
    Add a test for Erlang as an invalid foreign language. Expect both the
    new error message for this new error, and the updated list of now-valid
    foreign languages on all errors.
2020-10-29 13:24:49 +11:00
Zoltan Somogyi
1afe0df4e9 Fix an abort when constructing MLDS lookup tables.
This fixes Mantis bug #481.

compiler/ml_code_util.m:
    We used to approach the construction of tables for lookup switches
    by testing whether the shape of the HLDS code fit our requirements,
    and then building those tables using code that assumed that all the
    variables involved represented constants. This approach had a bug:
    when a switch arm constructed an output using *only* the switched-on
    variable, this passed the shape test even when that variable wasn't
    a constant.

    We could fix the shape test, instead this diff changes the approach
    to avoid making the incorrect assumption. This seems more robust,
    and in any case it is the approach used by the LLDS backend.

compiler/ml_disj_gen.m:
    Make the same switch in approach when generating lookup tables
    for disjunctions.

tests/valid/bug481.m:
    The Mantis test case.

tests/valid/Mmakefile:
    Enable the new test case.
2019-08-19 17:27:13 +10:00
Zoltan Somogyi
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.
2018-09-28 23:07:23 +10: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
5f7629e1db Harmonize unify_gen_test.m with its MLDS counterpart.
compiler/unify_gen_test.m:
compiler/ml_unify_gen_test.m:
    Harmonise the code of the predicates that test whether the top functor
    of the term referred to by a given variable is bound
    (a) to a given cons_id, for unifications, or
    (b) to one of a list of given cons_ids, for switch arms,
    between the backends, as much as possible.

    Give the predicates involved more meaningful names.

    Factor out some common code.

compiler/ml_switch_gen.m:
    The code for handling the "list of cons_ids" part was previously here.
    Delete it after moving it to ml_unify_gen_test.m.

compiler/ml_code_util.m:
    Factor out some common code, and note a relationship to
    ml_unify_gen_test.m.

compiler/unify_gen_deconstruct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/middle_rec.m:
compiler/switch_gen.m:
    Conform to the changes above.
2018-07-12 00:18:55 +02:00
Zoltan Somogyi
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.
2018-06-06 03:35:20 +02:00
Zoltan Somogyi
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.
2018-06-04 23:28:19 +02: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
94740ed865 Delete func_local.
compiler/mlds.m:
    We haven't supported the hl*_nest grades for more than half a year,
    so delete the func_local function symbol (representing the accessibility
    of nested functions) in the function_access type.

compiler/ml_code_util.m:
    Create nested functions as func_private, not func_local. (ml_elim_nested.m
    will ignore the function's accessibility anyway when it lifts the nested
    function out of its block.)

compiler/mlds_to_c_stmt.m:
    Throw an exception if the MLDS block being output has a nested function
    left in it.

compiler/mlds_to_c_func.m:
compiler/mlds_to_c_util.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Conform to the change above.
2018-05-15 11:49:50 +02:00
Zoltan Somogyi
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.
2018-05-13 12:23:38 +02:00
Zoltan Somogyi
fc903a0911 Eliminate the double storage of types in the MLDS.
compiler/mlds.m:
    When we record a Mercury type in the MLDS, we used to record with it
    not just its type category (which some aux predicates need), but also
    the name by which it is known to the target language compiler, if the
    type is defined in that foreign language. Unfortunaly, the data structure
    we used to represent the name of the foreign type (and any assertions
    on it) also stored a duplicate copy of the Mercury type in the usual
    case where the Mercury type was *not* defined in the foreign language.
    Having two copies of the same information was dangerous, due to the
    possibility of inconsistency between them. It was also unnecessary work
    for the compiler passes that had to create the duplicate copies.

    Eliminate these problems by always storing *one* copy of the Mercury type.

    Store the Mercury and foreign type information next to each other.

compiler/foreign.m:
    Make the above possible by deleting up the old exported_type type,
    which contained the duplicate copy of the Mercury type in usual case
    of a type that is not defined by foreign code, and replacing it
    with a type that contains information about just a foreign type.

    In the argument lists of the predicates and functions of this module,
    replace arguments that used to be type exported_type with a pair
    of the Mercury type and a maybe of the new type, which is yes(...)
    iff the Mercury type *is* defined in foreign code.

    Give some predicates and functions more meaningful names.

    Make specialized versions of these functions available (specialized
    e.g. to a target language) where these would be useful.

    Delete the auxiliary predicates that aren't needed with the
    new data structure design.

compiler/export.m:
compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_simplify_switch.m:
compiler/ml_switch_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.
2018-05-08 00:17:34 +02:00
Zoltan Somogyi
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.
2018-05-05 13:22:19 +02:00
Zoltan Somogyi
28a80ce155 Simplify some code.
compiler/ml_code_util.m:
    Make ml_gen_box_const_rval take an arg_width argument instead of
    a bool derived from that arg_width. This simplifies the code of
    the call sites, concentrates the (simple) derivation process in one place,
    and allows us to avoid doing the derivation if it its result is not needed.

compiler/ml_unify_gen.m:
    Conform to the change to ml_code_util.m.

    Simplify some of the call sites further by putting the processing required
    for one argument into place.
2018-03-05 19:37:21 +11:00
Zoltan Somogyi
5ec743ac97 Move some code to where it is needed. 2018-03-01 18:23:16 +11:00
Zoltan Somogyi
16e3331604 Fix white space. 2018-03-01 13:16:48 +11: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
Julien Fischer
a9b26c923c Support 64-bit integers in static ground terms with the MLDS backend.
compiler/ml_code_util.m:
    As above

compiler/mlds.m:
    Extend the type describing the different kinds of global variable
    holding constant immutable data to convert 64-bit integers.
2018-01-26 07:21:09 -05:00
Julien Fischer
f519e26173 Add builtin 64-bit integer types -- Part 1.
Add the new builtin types: int64 and uint64.

Support for these new types will need to be bootstrapped over several changes.
This is the first such change and does the following:

- Extends the compiler to recognise 'int64' and 'uint64' as builtin types.
- Extends the set of builtin arithmetic, bitwise and relational operators
  to cover the new types.
- Adds the new internal option '--unboxed-int64s' to the compiler; this will be
  used to control whether 64-bit integer types are boxed or not.
- Extends all of the code generators to handle the new types.
- Extends the runtimes to support the new types.
- Adds new modules to the standard library intend to contain basic operations
  on the new types.  (These are currently empty and not documented.)

There are bunch of limitations marks with "XXX INT64"; these will be lifted in
part 2 of this change.  Also, 64-bit integer types are currently always boxed,
again this limitation will be lifted in later changes.

compiler/options.m:
    Add the new option --unboxed-int64s.

compiler/prog_type.m:
compiler/prog_data.m:
compiler/builtin_lib_types.m:
     Recognise int64 and uint64 as builtin types.

compiler/builtin_ops.m:
     Add builtin operations for the new types.

compiler/hlds_data.m:
     Add new tag types for the new types.

compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/export.m:
compiler/foreign.m:
compiler/goal_util.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_dependency_graph.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/implementation_defined_literals.m:
compiler/inst_check.m:
compiler/mercury_to_mercury.m:
compiler/mode_util.m:
compiler/module_qual.qualify_items.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/parse_tree_to_term.m:
compiler/parse_type_name.m:
compiler/polymorphism.m:
compiler/prog_out.m:
compiler/prog_util.m:
compiler/rbmm.execution_path.m:
compiler/rtti.m:
compiler/table_gen.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
    Conform to the above changes to the parse tree and HLDS.

compiler/c_util.m:
    Support writing out constants of the new types.

compiler/llds.m:
    Add a representation for constants of the new types to the LLDS.

compiler/stack_layout.m:
    Add a new field to the stack layout params that records whether
    64-bit integers are boxed or not.

compiler/call_gen.:m
compiler/code_info.m:
compiler/disj_gen.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/llds_out_data.m:
compiler/llds_out_instr.m:
compiler/lookup_switch.m:
compiler/mercury_compile_llds_back_end.m:
compiler/prog_rep.m:
compiler/prog_rep_tables.m:
compiler/var_locn.m b/compiler/var_locn.m:
    Support the new types in the LLDS code generator.

compiler/mlds.m:
    Support constants of the new types in the MLDS.

compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_global_data.m:
compiler/ml_rename_classes.m:
compiler/ml_top_gen.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 above changes to the MLDS.

compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Generate the appropriate target code for constants of the new types
    and operations involving them.

compiler/bytecode.m:
compiler/bytecode_gen.m:
    Handle the new types in the bytecode generator; we just abort if we
    encounter them for now.

compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_call_gen.m:
compiler/erl_code_util.m:
compiler/erl_unify_gen.m:
    Handle the new types in the Erlang code generator.

library/private_builtin.m:
    Add placeholders for the builtin unify and compare operations for
    the new types.  Since the bootstrapping compiler will not recognise
    the new types we give them polymorphic arguments.  These can be
    replaced after this change has bootstrapped.

    Update the Java list of TypeCtorRep constants here.

library/int64.m:
library/uint64.m:
    New modules that will eventually contain builtin operations on the new
    types.

library/library.m:
library/MODULES_UNDOC:
    Do not include the above modules in the library documentation for now.

library/construct.m:
library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
library/table_statistics.m:
deep_profiler/program_representation_utils.m:
mdbcomp/program_representation.m:
    Handle the new types.

configure.ac:
runtime/mercury_conf.h.in:
    Define the macro MR_BOXED_INT64S.  For now it is always defined, support for
    unboxed 64-bit integers will be enabled in a later change.

runtime/mercury_dotnet.cs.in:
java/runtime/TypeCtorRep.java:
runtime/mercury_type_info.h:
    Update the list of type_ctor reps.

runtime/mercury.h:
runtime/mercury_int.[ch]:
    Add macros for int64 / uint64 -> MR_Word conversion, boxing and
    unboxing.

    Add functions for hashing 64-bit integer types suitable for use
    with the tabling mechanism.

runtime/mercury_tabling.[ch]:
    Add additional HashTableSlot structs for 64-bit integer types.

    Omit the '%' character from the conversion specifiers we pass via
    the 'key_format' argument to the macros that generate the table lookup
    function.  This is so we can use the C99 exact size integer conversion
    specifiers (e.g. PRIu64 etc.) directly here.

runtime/mercury_hash_lookup_or_add_body.h:
    Add the '%' character that was omitted above to the call to debug_key_msg.

runtime/mercury_memory.h:
     Add new builtin allocation sites for boxed 64-bit integer types.

runtime/mercury_builtin_types.[ch]:
runtime/mercury_builitn_types_proc_layouts.h:
runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
runtime/mercury_deep_copy_body.h:
runtime/mercury_ml_expand_body.h:
runtime/mercury_table_type_body.h:
runtime/mercury_tabling_macros.h:
runtime/mercury_tabling_preds.h:
runtime/mercury_term_size.c:
runtime/mercury_unify_compare_body.h:
    Add the new builtin types and handle them throughout the runtime.

runtime/Mmakefile:
    Add mercury_int.c to the list of .c files.

doc/reference_manual.texi:
     Add the new types to the list of reserved type names.

     Add the mapping from the new types to their target language types.
     These are commented out for now.
2018-01-12 09:29:24 -05: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
7b0ca6345f Encode invariants about class inheritance in types.
compiler/mlds.m:
    Make mlds_interface_id its own type, instead of identifying all
    interfaces by an MLDS type using the mlds_class_type/3 data constructors.

    Make mlds_class_id its own type, instead of identifying (almost all)
    classes by an MLDS type using the mlds_class_type/3 data constructors.

    Change the field of mlds_class_defns that says what base classes the
    class inherits from to reflect the facts that

    - the "classes" representing environments that we put on the heap
      when targeting C# or Java have a base *type*, not a base *class*, and

    - no current MLDS target language supports multiple inheritance,
      so an MLDS class cannot inherit from more than one base class.

    Change the mlds_class_type data constructor of the mlds_type type
    to take a complete mlds_class_id as an argument, instead of its pieces.

compiler/ml_accurate_gc.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_rename_classes.m:
compiler/ml_simplify_switch.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:
    Conform to the changes above.
2017-10-19 19:13:28 +11:00
Zoltan Somogyi
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.
2017-10-15 01:39:28 +11:00
Zoltan Somogyi
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.
2017-10-14 19:39:21 +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
7b5823caaa Improve some variable names. 2017-09-11 05:13:53 +10:00
Zoltan Somogyi
ad522f23e6 Improve formatting. 2017-09-11 05:01:15 +10:00
Zoltan Somogyi
d7d30e5ef1 Fix typo. 2017-09-09 03: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
eccd0bfab4 Implement mutual tail call optimization for the MLDS.
It does not (yet) optimize all the calls that the LLDS backend optimizes,
with the most significant limitation being that it handles only calls to
procedures that return all their arguments by reference. This rules out
det functions (thought it includes *semidet* functions), as well as the
backends that use copy-out. Lifting those limitations is future work.

compiler/ml_proc_gen.m:
    Make the change described above.

compiler/mlds.m:
    Add two new kinds of compiler-generated local variables to represent
    the input and output arguments of procedures in TSCCs respectively.
    They are key to allowing the code generation scheme used by ml_proc_gen.m
    to work *without* having to rename apart either sets of HLDS variables
    or set of MLDS variables. (Both those renames would be a lot of work.)

    Add a new kind of compiler-generated local variable to represent
    the identity of the tail-called procedure if the code generator is asked
    not to use labels and gotos.

compiler/ml_args_util.m:
    Provide a predicate that ml_proc_gen.m uses to generate argument handling
    code for mutually recursive procedures.

compiler/ml_gen_info.m:
    Generalize the existing support for self-tail-recursive calls
    to also handle mutually-tail-recursive calls.

compiler/ml_call_gen.m:
    Use the new generalized support to generate code for
    mutually-tail-recursive calls as well as for self-tail-recursive calls.
    For each call to a procedure that the ml_gen_info records as a potential
    target for a tail recursive call (i.e. for each procedure in the TSCC
    we are generating code for), record what kinds of calls we *do* generate
    to it, for use by ml_proc_gen.m.

compiler/ml_code_util.m:
    Add a slightly different form of an existing utility function,
    to allow new code in ml_proc_gen.m to use it without doing redundant work.

    Expand out a function's definition to allow mdb breakpoints on its
    components.

compiler/options.m:
    Provide developer-only options to control aspects of how ml_proc_gen.m
    handles tail call optimization.

compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Provide a way for the MLDS to specify the printing of a blank line:
    a comment containing an empty string. Some code in ml_proc_gen.m uses this
    to make the comments it generates look nicer.

compiler/hlds_desc.m:
    Add two utility functions that we now use to include descriptions
    of TSCCs in the generated MLDS code, to help debug that code.

compiler/proc_gen.m:
    Delete code that can now be replaced by calling one of the new utility
    functions in hlds_desc.m. (The deleted code was used as the original
    template for the code of that function.)

    Delete an unused type.

compiler/rtti_to_mlds.m:
    Conform to the changes in ml_gen_info.m.
2017-08-31 14:38:45 +10:00
Zoltan Somogyi
57d58da6ff Factor out some common code.
compiler/ml_proc_gen.m:
    Prepare for translating all HLDS procedures in a TSCC all at once to MLDS,
    by taking some chunks of code that will be useful in this process
    out of the predicate that translates a single HLDS procedure to MLDS
    and making them predicates in their own right. The new mechanism for
    translating a whole TSCC at once will take these pieces and put them,
    or modified/generalized versions of them, together in different ways.

compiler/ml_args_util.m:
    Factor out some code that is common to all exported predicates
    that generate argument lists.

    Add a "_no_gc_stmts" suffix to the names of the predicates that generate
    argument lists that do not fill in the gc stmt field in the generated
    mlds_arguments.

compiler/ml_gen_info.m:
    Instead of storing the pred_id and proc_id of the procedure being
    translated separately, store them together as a pred_proc_id, because
    most users of ml_gen_info need both at the same time.

compiler/ml_code_util.m:
    Make several predicates take pred_proc_ids instead of separate pred_ids
    and proc_ids.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_top_gen.m:
compiler/ml_unify_gen.m:
compiler/rtti_to_mlds.m:
    Conform to the changes above.
2017-08-13 13:48:44 +02:00
Zoltan Somogyi
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.
2017-08-13 02:06:26 +02:00
Zoltan Somogyi
3d83bff49f Represent MLDS dummy vars as global vars, not local vars.
Guaranteeing that we never generate any references to dummy vars (fix 1c
in the log message of the previous diff) would require too many places
in the compiler to be made more complicated. This diff implements fix 1a
for the problem that dummy vars, unlike other local vars, need module
qualification.

compiler/mlds.m:
    Move the representation of dummy vars from local to global vars.

compiler/ml_code_util.m:
    Generate dummy vars as global, not dummy vars.

compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Conform to the change above.
2017-08-09 20:26:30 +02: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
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.
2017-08-07 19:33:33 +02:00
Zoltan Somogyi
7aa70516ae Refactor code to eliminate some redundant test. 2017-08-02 18:36:24 +02:00
Zoltan Somogyi
0929c9ae7e Encode an invariant in the modes. 2017-08-02 16:53:07 +02:00
Zoltan Somogyi
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.
2017-08-02 16:17:55 +02:00
Zoltan Somogyi
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.
2017-08-01 22:11:01 +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
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.
2017-07-27 03:33:20 +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
595014b978 Simplify the flags field in field var definitions.
compiler/mlds.m:
    The field variables we generate are always "public" within the classes
    that define them, so delete the access field from their flags. Field vars
    were the only type left that used the mlds_data_decl_flags type, so rename
    this type to reflect this fact. Make the type concrete, since abstraction
    buys us nothing useful in this case.

compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_global_data.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/mlds_to_target_util.m:
    Conform to the change above.
2017-07-23 04:40:40 +02:00
Julien Fischer
7c42aa1aa2 Use a separate type to describe integer tags.
compiler/hlds_data.m
     Use a separate type to describe integer tags and parameterise
     the int_tag functor of the cons_tag/0 type by that new type.

compiler/bytecode_gen.m:
compiler/dense_switch.m:
compiler/du_type_layout.m:
compiler/export.m:
compiler/hlds_code_util.m:
compiler/make_tags.m:
compiler/ml_type_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_unify_gen.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/type_ctor_info.m:
compiler/unify_gen.m:
     Conform to the above change.

compiler/ml_code_util.m:
    Add a utility function for use by the above.
2017-07-23 12:05:57 +10:00
Zoltan Somogyi
59b2a7c110 Delete the flags field from local var definitions.
compiler/mlds.m:
    The flags field of the mlds_local_var_defn type was always set
    to the same value, so it contained no information. Delete it.
    (The field contained information in its original home in the
    mlds_data_defn type; it distinguished local variables from
    global and field variables.)

compiler/ml_code_util.m:
    Delete the function that returned the value we always used to put
    into the now-deleted field.

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-07-23 00:34:44 +02:00
Zoltan Somogyi
fa5eee77c5 Specialize qual/3 for each type it was applied to.
The MLDS either module- or type-qualifies several kinds of entities.
It used to use the same qual/3 wrapper for all these entities. However,
many kinds of entities are never (and can never be) type-qualified,
because they are not defined inside a type.

This diff replaces the mlds_fully_qualified_name type, and its qual/3 wrapper,
with a separate type and a separate wrapper for each kind of entity.
For those entities that can be both module- and type-qualified, have this
wrapper continue to include a mlds_qual_kind (module_qual or type_qual) field;
for the entities that are only ever module qualified, omit this field.

compiler/mlds.m:
    Make the change described above.

    There are some related changes.

    The first is that the argument of the ml_field_named rval specifying
    the field used to be a string. Change this to be a field_var_name,
    because if a field's name is given by a field_var_name in its definition,
    it should be given by that same field_var_name in its uses as well.
    Without this, it is unnecessarily hard to ensure that the code that
    generates the target language versions of the field's name match
    in definitions and uses; specification, it would be unnecessarily hard
    to ensure that they do module- or type-qualification the same way.

    The second is required by the first. We used to use "ptr_num"
    as the name of only a compiler-generated local variable, but it is
    actually the name of a field in a compiler-generated class, and the
    local variable use actually refers to the field. Therefore this diff
    moves the reference to this from the mlds_local_var_name type
    to the mlds_field_var_name type.

    The third is switching to a more consistent naming scheme:
    having the unqualified name of entities of kind xxx be mlds_xxx_name
    and the qualified version of those names being qual_xxx_name.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_optimize.m:
compiler/ml_proc_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/rtti_to_mlds.m:
    Conform to the changes above.

compiler/java_names.m:
    Clarify a variable name.
2017-07-22 22:48:30 +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
Julien Fischer
8a240ba3f0 Add builtin 8, 16 and 32 bit integer types -- Part 1.
Add the new builtin types: int8, uint8, int16, uint16, int32 and uint32.
Support for these new types will need to be bootstrapped over several changes.
This is the first such change and does the following:

- Extends the compiler to recognise 'int8', 'uint8', 'int16', 'uint16', 'int32'
  and 'uint32' as builtin types.
- Extends the set of builtin arithmetic, bitwise and relational operators to
  cover the new types.
- Extends all of the code generators to handle new types.  There currently lots
  of limitations and placeholders marked by 'XXX FIXED SIZE INT'.  These will
  be lifted in later changes.
- Extends the runtimes to support the new types.
- Adds new modules to the standard library intended to hold the basic
  operations on the new types.  (These are currently empty and not documented.)

This change does not introduce the two 64-bit types, 'int64' and 'uint64'.
Their implementation is more complicated and is best left to a separate change.

compiler/prog_type.m:
compiler/prog_data.m:
compiler/builtin_lib_types.m:
    Recognise int8, uint8, int16, uint16, int32 and uint32 as builtin types.

    Add new type, int_type/0,that enumerates all the possible integer types.

    Extend the cons_id/0 type to cover the new types.

compiler/builtin_ops.m:
    Parameterize the integer operations in the unary_op/0 and binary_op/0
    types by the new int_type/0 type.

    Add builtin operations for all the new types.

compiler/hlds_data.m:
    Add new tag types for the new types.

compiler/hlds_pred.m:
    Parameterize integers in the table_trie_step/0 type.

compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/export.m:
compiler/foreign.m:
compiler/goal_util.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_dependency_graph.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/implementation_defined_literals.m:
compiler/inst_check.m:
compiler/mercury_to_mercury.m:
compiler/mode_util.m:
compiler/module_qual.qualify_items.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_to_term.m:
compiler/parse_type_name.m:
compiler/polymorphism.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_rep_tables.m:
compiler/prog_util.m:
compiler/rbmm.exection_path.m:
compiler/rtti.m:
compiler/rtti_to_mlds.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/type_constraints.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
    Conform to the above changes to the parse tree and HLDS.

compiler/c_util.m:
    Support generating the builtin operations for the new types.

doc/reference_manual.texi:
    Add the new types to the list of reserved type names.

    Add the mapping from the new types to their target language types.
    These are commented out for now.

compiler/llds.m:
    Replace the lt_integer/0 and lt_unsigned functors of the llds_type/0,
    with a single lt_int/1 functor that is parameterized by the int_type/0
    type.

    Add a representations for constants of the new types to the LLDS.

compiler/call_gen.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/llds_out_data.m:
compiler/llds_out_global.m:
compiler/llds_out_instr.m:
compiler/lookup_switch.m:
compiler/middle_rec.m:
compiler/peephole.m:
compiler/pragma_c_gen.m:
compiler/stack_layout.m:
compiler/string_switch.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
compiler/trace_gen.m:
compiler/transform_llds.m:
    Support the new types in the LLDS code generator.

compiler/mlds.m:
    Support constants of the new types in the MLDS.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.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_target_util.m:
    Conform to the above changes to the MLDS.

compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
    Generate the appropriate target code for constants of the new
    types and operations involving them.

compiler/bytecode.m:
compiler/bytecode_gen.m:
    Handle the new types in the bytecode generator; we just abort if we
    encounter them for now.

compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_call_gen.m:
compiler/erl_code_util.m:
compiler/erl_rtti.m:
compiler/erl_unify_gen.m:
    Handle the new types in the Erlang code generator.

library/private_builtin.m:
    Add placeholders for the builtin unify and compare operations for
    the new types.  Since the bootstrapping compiler will not recognise
    the new types we give the polymorphic arguments.  These can be
    replaced after this change has bootstrapped.

    Update the Java list of TypeCtorRep constants.

library/int8.m:
library/int16.m:
library/int32.m:
library/uint8.m:
library/uint16.m:
library/uint32.m:
    New modules that will eventually contain builtin operations
    on the new types.

library/library.m:
library/MODULES_UNDOC:
    Do not include the above modules in the library documentation
    for now.

library/construct.m:
library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
deep_profiler/program_representation_utils.m:
mdbcomp/program_representation.m:
    Handle the new types.

runtime/mercury_dotnet.cs.in:
java/runtime/TypeCtorRep.java:
runtime/mercury_type_info.h:
    Update the list of TypeCtorReps.

configure.ac:
runtime/mercury_conf.h.in:
    Check for the header stdint.h.

runtime/mercury_std.h:
    Include stdint.h; abort if that header is no present.

runtime/mercury_builtin_types.[ch]:
runtime/mercury_builtin_types_proc_layouts.h:
runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
runtime/mercury_deep_copy_body.h:
runtime/mercury_ml_expand_body.h
runtime/mercury_table_type_body.h:
runtime/mercury_tabling_macros.h:
runtime/mercury_tabling_preds.h:
runtime/mercury_term_size.c:
runtime/mercury_unify_compare_body.h:
    Add the new builtin types and handle them throughout the runtime.
2017-07-18 01:31:01 +10:00