These imports were missing from source files, but were included in imported
modules' .int3 files. An upcoming change will delete these from those .int3
files.
The code_info type was originally designed to be a single data structure
that holds all of the state of the LLDS code generator. It HAD to be a single
data structure then, because the DCGs we used to pass state around only
supported passing around ONE piece of state. Nevertheless, it contained
three separate kinds of information:
1 static information, which never changed during the lifetime of a code_info
structure (such as the pred and proc id of the procedure being compiled),
2 persistent information, whose updates were never undone (such as the maximum
number of temporaries that were ever needed at any one time), and
3 location dependent information, such as "which variables are stored where",
whose updates *can* be undone when the code generator jumps back to
a previously visited point in the code, e.g. to start generating code
for the next disjunct in a disjunction.
Originally, these three kinds of fields were all jumbled up together, but
about ten years ago, I grouped all the fields of the same kind together,
into substructures of code_info named code_info_static, code_info_persistent
and code_info_loc_dep respectively. This improved matters, but some problems
remained, the most important of which is that the code_info always contained
the location dependent information, even when it wasn't meaningful, and there
was no way of indicating this fact. (After initialization, the other two parts
are always meaningful.)
This diff separates out the location dependent part of the code_info
into a new type, code_loc_dep, that can be passed around independently
of the code_info, which now contains only the first two kinds of information
above. In places where the location-dependent information is not meaningful,
you don't need to have a current code_loc_dep.
This separation also makes it easier to see what updates to the code generator
state change only the persistent part (the updated code_info type), only
the location-dependent part (the new code_loc_dep type), or both.
In the process of making this change, I found several places where the
location-dependent part of the code_info (now the code_loc_dep) was being
updated, only for those updates to be thrown away, unread, a short time later.
This happened at the ends of branches in e.g. switches, with the updated
code_loc_deps being thrown away when code generation started working on
the next branch.
compiler/code_loc_dep.m:
New module containing the location-dependent part of the LLDS code
generator state. Its contents are derived from those parts of the
old contents of code_info.m that deal with location-dependent state.
Many of the predicates moved here work on only on the code_loc_dep
structure, some others work on both the code_info and code_loc_dep
structure, and a few work only on the code_info. Predicates in the last
category are in code_loc_dep.m only if they are either (a) used only
in this module, or (b) used only with other predicates in this module.
compiler/ll_backend.m:
compiler/notes/compiler_design.html:
Mention the new module.
compiler/code_info.m:
Delete the code now in code_loc_dep.m.
Make the vartypes a field in the static part of the code_info, since it is
used quite often. (We used to look it up in the proc_info every time.)
Put the declarations and definitions of the access predicates in an order
that is consistent with the order of the fields they work on.
Give some fields and predicates more descriptive names.
compiler/call_gen.m:
compiler/code_gen.m:
compiler/commit_gen.m:
compiler/dense_switch.m:
compiler/disj_gen.m:
compiler/ite_gen.m:
compiler/ll_backend.m:
compiler/lookup_switch.m:
compiler/lookup_util.m:
compiler/middle_rec.m:
compiler/par_conj_gen.m:
compiler/pragma_c_gen.m:
compiler/proc_gen.m:
compiler/string_switch.m:
compiler/switch_case.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
compiler/trace_gen.m:
compiler/unify_gen.m:
compiler/var_locn.m:
Conform to and take advantage of the changes above.
Often this required passing an in/out pair of code_loc_deps as well as
an in/out pair of code_infos, but in many cases, one or more of these
would not be needed.
Don't make changes to the code_loc_dep at the end of an arm of a branched
control structure if those updates are about be thrown away when we
start generating code for the next arm.
In several cases, switch to a strategy of taking a snapshot of the
code_loc_dep before entering a branched control structure as a whole,
and restoring that state at the start of each arm. We used to take
a snapshot at the start of each branch, and restore it at its end,
to be ready for the next branch. The former is easier to make
correctness arguments about, since the code_loc_dep in an arm
often has limited scope.
Make some minor unrelated improvements, such as eliminating the
unnecessary use of solutions/2, and reordering tests for slightly
better performance.
Estimated hours taken: 24
Branches: main
Predicates with many variables, such as some of those in zm_enums.m,
tickle pretty bad behavior in the liveness and stack_alloc passes.
This is because those passes manipulate sets of variables, which in
such cases are large sets of variables, and the quadratic behavior
of repeated operations on sets represents as sorted lists hurts us.
This diff changes the representation of the sets of variables involved
in those two passes, which are the prebirth, postbirth, predeath and postdeath
sets in goal_infos, to be values of an abstract type (set_of_progvar).
By default, these are implemented using tree_bitsets, which have much better
worst case behaviour that set_ordlists.
When compiling zm_enums with debugging enabled, this diff speeds up
the liveness pass by about half and the stack alloc pass by about a third,
with the overall speedup being about 6% (due to some other expensive passes).
On tools/speedtest -l, the result is a 3.4% slowdown. Since the slowdown
worsens slightly if I make the abstract representation of sets of prog_vars
be the existing representation (an ordinary set), I think this slowdown is
due to the conversions that are now required in some places between the
abstract representation and an explicit set(prog_var) representation.
As such, as other uses of set(progvar) get converted to set_of_progvar,
this slowdown should disappear.
compiler/set_of_var.m:
The new module that contains the set_of_progvar abstract data type.
This module also contains a copy of the code of the graph_colour
module. Since the set_of_progvar type is private, this is necessary
if we want all the set operations done by graph colouring (which does
the bulk of the work of the stack alloc pass) to use the preferred
set representation.
compiler/graph_colour.m:
Note that this module is no longer used.
compiler/stack_alloc.m:
compiler/liveness.m:
Switch over to using the new module.
compiler/parse_tree.m:
Include set_of_var among the modules of this package. (It is in this
package because the prog_var type is defined in this package.)
compiler/test_bitset.m:
A module that allows new set implementations to be tested. It is
an extended and specialized version of the bitset_tester module
from tests/hard_coded.
compiler/hlds_llds.m:
Use the set_of_progvar type for the prebirth, postbirth, predeath
and postdeath sets in goal_infos, and for other liveness-related
sets of variables.
compiler/code_info.m:
Some of the fields of the code_info structure represent sets of
variables, and some of the predicates defined by this module have
arguments that are sets of variables. If these sets represent entities
that are computed from prebirth, postbirth, predeath and postdeath
sets or from other goal_info fields that have been changed to the
set_of_progvar representation, change them to use the set_of_progvar
representation as well, or, in a few cases, to plain sorted lists.
Conform to the above change.
compiler/proc_type.m:
Add a utility predicate to operate of set_of_progvar.
Replace a lambda expression with a named predicate.
compiler/quantification.m:
Until now, quantification.m used its own private abstract type
(defined as tree_bitset) to represent sets. Make it use set_of_progvar
instead, since it has the same purpose. This eliminates a potential
maintenance problem.
compiler/call_gen.m:
compiler/code_gen.m:
compiler/commit_gen.m:
compiler/delay_construct.m:
compiler/disj_gen.m:
compiler/hlds_out_goal.m:
compiler/hlds_rtti.m:
compiler/interval.m:
compiler/ite_gen.m:
compiler/live_vars.m:
compiler/lookup_switch.m:
compiler/lookup_util.m:
compiler/matching.m:
compiler/pd_util.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/proc_gen.m:
compiler/simplify.m:
compiler/stack_opt.m:
compiler/store_alloc.m:
compiler/string_switch.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.domain.m:
compiler/switch_util.m:
compiler/trace_gen.m:
compiler/tupling.m:
compiler/unify_gen.m:
compiler/unused_args.m:
Conform to the above change.
library/map.m:
Add a utility predicate, map.select_sorted_list, which functions the
same way as map.select, but takes a sorted list as argument instead of
a set.
library/set_ordlist.m:
Bring the interface of this module closer to set.m and tree_bitset.m
to make them more easily interchangeable. This required adding the
predicates is_non_empty and is_singleton, as well as adding predicate
forms of union_list and intersect_list.
I also added missing type_spec pragmas for some predicates frequently
used by the compiler.
library/tree_bitset.m:
Bring the interface of this module closer to set.m and set_ordlist.m
to make them more easily interchangeable. This required adding the
predicates is_non_empty and is_singleton, and both function and
predicate forms of union_list and intersect_list.
Fix an old bug in the difference operation. Given SetA - SetB,
if SetA was the empty set, then this operation would correctly
return the empty set if SetB was small (represented by a leaf list),
but would incorrectly return SetB if it was large (represented by
an interior node list).
Estimated hours taken: 6
Branches: main
compiler/*.m:
Convert almost all remaining modules in the compiler to use
"$module, $pred" instead of "this_file" in error messages.
In a few cases, the old error message was misleading, since it
contained an incorrect, out-of-date or cut-and-pasted predicate name.
tests/invalid/unresolved_overloading.err_exp:
Update an expected output containing an updated error message.
Estimated hours taken: 2
Branches: main, release
Make the system compiler with --warn-unused-imports.
browser/*.m:
library/*.m:
compiler/*.m:
Remove unnecesary imports as flagged by --warn-unused-imports.
In some files, do some minor cleanup along the way.
Estimated hours taken: 2
Branches: main
Add the predicates sorry, unexpected and expect to library/error.m.
compiler/compiler_util.m:
library/error.m:
Move the predicates sorry, unexpected and expect from compiler_util
to error.
Put the predicates in error.m into the same order as their
declarations.
compiler/*.m:
Change imports as needed.
compiler/lp.m:
compiler/lp_rational.m:
Change imports as needed, and some minor cleanups.
deep_profiler/*.m:
Switch to using the new library predicates, instead of calling error
directly. Some other minor cleanups.
NEWS:
Mention the new predicates in the standard library.
Estimated hours taken: 6
Branches: main
Delete the old tree.m module (which did a small subset of what cords now do),
and switch to using cords instead. This is more standard, as well as very
slightly more efficient, because with cords, e.g. concatenating ten code
fragments of which eight are empty doesn't allocate ten cons cells.
My measurements show a 0.1% reduction in executable size and a 0.3% reduction
in compilation time. Both of those are in the noise; the main reason for the
change is more convenient coding.
compiler/tree.m:
Remove this module.
compiler/libs.m:
Remove the inclusion of tree.m.
compiler/notes/compiler_design.html:
Remove the description of tree.m.
compiler/bytecode.m:
Switch to using cords to represent code in the bytecode backend.
compiler/llds.m:
Switch to using cords to represent code in the LLDS backend.
compiler/mlds_to_il.m:
Switch to using cords to represent IL code being built.
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/code_gen.m:
compiler/code_info.m:
compiler/commit_gen.m:
compiler/dense_switch.m:
compiler/disj_gen.m:
compiler/ite_gen.m:
compiler/lookup_switch.m:
compiler/lookup_util.m:
compiler/middle_rec.m:
compiler/par_conj_gen.m:
compiler/pragma_c_gen.m:
compiler/proc_gen.m:
compiler/string_switch.m:
compiler/switch_case.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
compiler/trace_gen.m:
compiler/unify_gen.m:
compiler/var_locn.m:
Conform to the changes above.
library/cord.m:
Add a predicate form of map.
Estimated hours taken: 50 by quan, 8 by zs
Branches: main
Implement the runtime system for region-based memory management. This includes
the implementation of regions, region instructions and support for
backtracking.
Support for backtracking deals with preventing the destruction of backward
live regions and provides instant reclaiming of space in regions when
backtracking reaches a resume point. This support now exploits the data
in rbmm_goal_info structures. The mechanisms are documented in the
papers/rbmm module of the Mercury repository.
compiler/code_info.m:
Change the option to control the addition of region operations from
use_region to region_analysis so that no region operations are
introduced when compiling a compiler in .rbmm grade. This is temporary,
as is the re-adding of --region-analysis option.
Make use of rbmm_goal_info when generating backtrack-supporting code
for commit operations.
compiler/commit_gen.m:
Make use of rbmm_goal_info when generating backtrack-supporting code.
compiler/disj_gen.m:
Make use of rbmm_goal_info when generating semidet disjunction.
Correct one error so that use_region_disj_later is not generated in
the code for the first disjunct.
compiler/ite_gen.m:
Make use of rbmm_goal_info.
compiler/options.m:
Modify the size of disj_protect(ion) to 1 instead of 2.
library/region_builtin.m:
Change the region builtins to call to the correct region operations
in the region runtime system.
Add a predicate to print out profiling information for region-based
memory management.
runtime/mercury_region.h
runtime/mercury_region.c
New files containing the implementation of the region runtime system.
This runtime system supports its own profiling and debugging messages,
which can be turned on and off via the MR_RBMM_PROFILING and
MR_RBMM_DEBUG flags.
Note that these files are still in a state of flux.
runtime/mercury_types.h:
Add typedefs needed by declarations in mercury_region.h.
runtime/mercury_conf_paramh:
Document MR_RBMM_PROFILING and MR_RBMM_DEBUG.
runtime/mercury_imp.h:
#include mercury_region.h in rbmm grades.
runtime/Mmakefile:
Link the region runtime system into the runtime system of Mercury.
tests/tabling/Mmakefile:
Avoid accidental matches on the "mm" in "rbmm".
Estimated hours taken: 0.1
Branches: main
compiler/*.m:
Remove a bunch of unnecessary module qualifications on calls to
predicates in code_info.m, since they tend to cause bad line breaks.
Estimated hours taken: 4
Branches: main
Add new fields to the goal_info structure for region based memory management.
The fields are currently unused, but (a) Quan will add the code to fill them
in, and then (b) I will modify the code generator to use the filled in fields.
compiler/hlds_goal.m:
Make the change described above.
Group all the procedures that access goal_info components together.
Some of the getters were predicates while some were functions, so
this diff changes them all to be functions. (The setters remain
predicates.)
compiler/*.m:
Trivial changes to conform to the change in hlds_goal.m.
In simplify.m, break up a huge (800+ line) predicate into smaller
pieces.
Estimated hours taken: 30
Branches: main
Add a first draft of the code generator support for region based memory
management. It is known to be incomplete; the missing parts are marked by XXXs.
It may also be buggy; it will be tested after Quan adds the runtime support,
i.e. the C macros invoked by the new LLDS instructions. However, the changes
in this diff shouldn't affect non-RBMM operations.
compiler/llds.m:
Add five new LLDS instructions. Four are specific to RBMM operations.
RBMM embeds three new stacks in compiler-reserved temp slots in
procedure's usual Mercury stack frames, and the new LLDS instructions
respectively
(i) push those stack frames onto their respective stacks,
(ii) fill some variable parts of those stack frames,
(iii) fill fixed slots of those stack frames, and
(iv) use the contents of and/or pop those stack frames.
(The pushing and popping affect only the new embedded stacks, not the
usual Mercury stacks.)
The last instruction is a new variant of the old assign instruction.
It has identical semantics, but restricts optimization. An assign
(a) can be deleted if its target lval is not used, and
(b) its target lval can be changed (e.g. to a temp register) as long as
all the later instructions referring to that lval are changed to
use the new lval instead.
Neither is permitted for the new keep_assign instruction. This is
required because in an earlier draft we used it to assign to stack
variables (parts of the embedded stack frames) that aren't explicitly
referred to in later LLDS code, but are nevertheless implicitly
referred to by some instructions (specifically iv above). We now
use a specialized instruction (iii above) for this (since the macro
it invokes can refer to C structure names, this makes it easier to
keep the compiler in sync with the runtime system), but given that
keep_assign is already implemented, may be useful later and shouldn't
cause appreciable slowdown of the compiler, this diff keeps it.
Extend the type that describe the contents of lvals to allow it
to describe the new kinds of things we can now store in them.
Add types to manage and describe the new embedded stack frames,
and some utility functions. Change some existing utility functions
to make all this more conceptually consistent.
compiler/ite_gen.m:
Surround the code we generate for the condition of if-then-elses
with the code required to ensure that regions that are logically
removed in the condition aren't physically destroyed until we know
that the condition succeeds (since the region may still be needed
in the else branch), and to make sure that if the condition fails,
all the memory allocated since the entry into the condition is
reclaimed instantly.
compiler/disj_gen.m:
Surround the code we generate for disjunctions with the code required
to ensure that regions that are logically removed in a disjunct
aren't physically destroyed if a later disjunct needs them, and to
make sure that at entry into a non-first disjunct, all the memory
allocated since the entry into the disjunction is reclaimed instantly.
compiler/commit_gen.m:
compiler/code_info.m:
The protection against destruction offered by a disjunction disappears
when a commit cuts away all later alternatives in that disjunct, so we
must undo that protection. We therefore surround the scope of a commit
goal with goal that achieves that objective.
Add some new utility predicates to code_info. Remove some old utility
functions that are now in llds.m.
compiler/continuation_info.m:
Extend the type that describe the contents of stack slots to allow it
to describe the new kinds of things we can now store in them.
Rename the function symbols of that type to eliminate some ambiguities.
compiler/code_gen.m:
Remember the set of variables live at the start of the goal
(before the pre_goal_update updates it), since the region operations
need to know this.
Leave the lookup of AddTrailOps (and now AddRegionOps) to the specific
kinds of goals that need it (the most frequent goals, unify and call,
do not). Make both AddTrailOps and AddRegionOps use a self-explanatory
type instead of a boolean.
compiler/lookup_switch.m:
Conform to the change to AddTrailOps.
Fix some misleading variable names.
compiler/options.m:
Add some options to control the number of stack slots needed for
various purposes. These have to correspond to the sizes of some C
structures in the runtime system. Eventually these will be constants,
but it is handy to keep them easily changeable while the C data
structures are still being worked on.
Add an option for optimizing away region ops whereever possible.
The intention is that these should be on all the time, but we
will want to turn them off for benchmarking.
compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/frameopt.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_out.m:
compiler/llds_to_x86_64.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/par_conj_gen.m:
compiler/reassign.m:
compiler/stack_layout.m:
compiler/stdlabel.m:
compiler/trace_gen.m:
compiler/use_local_vars.m:
Conform to the changes above, which mostly means handling the new
LLDS instructions.
In some cases, factor out existing common code, turn if-then-elses
into switches, group common cases in switches, rationalize argument
orders or variable names, and/or put code in execution order.
In reassign.m, fix some old oversights that could (in some unlikely
cases) cause bugs in the generated code.
compiler/pragma_c_gen.m:
Exploit the capabilities of code_info.m.
compiler/prog_type.m:
Add a utility predicate.
Estimated hours taken: 10
Branches: main
This diff changes a few types from being defined as equivalent to a pair
to being discriminated union types with their own function symbol. This
was motivated by an error message (one of many, but the one that broke
the camel's back) about "-" being used in an ambiguous manner. It will
reduce the number of such messages in the future, and will make compiler
data structures easier to inspect in the debugger.
The most important type changed by far is hlds_goal, whose function symbol
is now "hlds_goal". Second and third in importance are llds.instruction
(function symbol "llds_instr") and prog_item.m's item_and_context (function
symbol "item_and_context"). There are some others as well.
In several places, I rearranged predicates to factor the deconstruction of
goals into hlds_goal_expr and hlds_goal_into out of each clause into a single
point. In many places, I changed variable names that used "Goal" to refer
to just hlds_goal_exprs to use "GoalExpr" instead. I also changed variable
names that used "Item" to refer to item_and_contexts to use "ItemAndContext"
instead. This should make reading such code less confusing.
I renamed some function symbols and predicates to avoid ambiguities.
I only made one algorithmic change (at least intentionally).
In assertion.m, comparing two goals for equality now ignores goal_infos
for all kinds of goals, whereas previously it ignored them for most kinds
of goals, but for shorthand goals it was insisting on them being equal.
This seemed to me to be a bug. Pete, can you confirm this?
Estimated hours taken: 3
Branches: main
Clean up in unused module imports in the Mercury system detected
by --warn-unused-imports.
analysis/*.m:
browser/*.m:
deep_profiler/*.m:
compiler/*.m:
library/*.m:
mdbcomp/*.m:
profiler/*.m:
slice/*.m:
Remove unused module imports.
Fix some minor departures from our coding standards.
analysis/Mercury.options:
browser/Mercury.options:
deep_profiler/Mercury.options:
compiler/Mercury.options:
library/Mercury.options:
mdbcomp/Mercury.options:
profiler/Mercury.options:
slice/Mercury.options:
Set --no-warn-unused-imports for those modules that are used as
packages or otherwise break --warn-unused-imports, e.g. because they
contain predicates with both foreign and Mercury clauses and some of
the imports only depend on the latter.
Estimated hours taken: 2
Branches: main
Treat trace goals as quantifying the variables that occur in their io() and/or
state() components.
compiler/hlds_goal.m:
Extend trace scopes with a field for recording the set of quantified
variables.
compiler/add_clause.m:
Record the list of quantified variables.
compiler/quantification.m:
Treat the list of quantified variables as for other scopes.
compiler/hlds_out.m:
Write out the new field.
compiler/mercury_to_mercury.m:
Reorder the arguments of some predicates to make them easier to curry,
e.g. for the new code in hlds_out.m.
Rename some predicates to avoid ambiguities.
compiler/*.m:
Conform to the changes in hlds_goal.m and/or mercury_to_mercury.m.
tests/hard_coded/trace_goal_3.{m,exp}:
New test case to test the new functionality.
tests/hard_coded/Mmakefile:
Enable the new test case.
Estimated hours taken: 70
Branches: main
Implement the trace goal construct we discussed, for now for the LLDS backends
only.
Since the syntax of trace goals is non-trivial, useful feedback on syntax
errors inside trace goal attributes is essential. With the previous setup, this
wasn't possible, since the code that turned terms into parse tree goals turned
*all* terms into goals; it couldn't recognize any errors, sweeping them under
the rug as calls. This diff changes that. Now, if this code recognizes a
keyword that indicates a particular construct, it insists on the rest of the
code following the syntax required for that construct, and returns error
messages if it doesn't.
We handle the trace goal attributes that specify state variables to be threaded
through the trace goal (either the I/O state or a mutable variable) in
add_clause.m, at the point at which we transform the list of items to the HLDS.
We handle the compile-time condition on trace goals in the invocation of
simplify at the end of semantics analysis, by eliminating the goal if the
compile-time condition isn't met. We handle run-time conditions on trace goals
partially in the same invocation of simplify: we transform trace goals with
runtime conditions into an if-then-else with the trace goal as the then part
and `true' as the else part, the condition being a foreign_proc that is handled
specially by the code generator, that special handling being to replace
the actual code of the foreign_proc (which is a dummy) with the evaluation of
the runtime condition.
Since these changes require significant changes to some of our key data
structures, I took the liberty of doing some renaming of function symbols
at the same time to avoid using ambiguities with respect to language keywords.
library/ops.m:
Add "trace" as an operator.
compiler/prog_data.m:
Define data types to represent the various attributes of trace goals.
Rename some function symbols to avoid ambiguities.
compiler/prog_item.m:
Extend the parse tree representation of goals with a trace goal.
compiler/mercury_to_mercury.m:
Output the new kind of goal and its components.
compiler/hlds_goal.m:
Extend the HLDS representation of scopes with a scope_reason
representing trace goals.
Add a mechanism (an extra argument in foreign_procs) to allow
the representation of goals that evaluate runtime trace conditions.
Since this requires modifying all code that traverses the HLDS,
do some renames that were long overdue: rename not as negation,
rename call as plain_call, and rename foreign_proc as
call_foreign_proc. These renames all avoid using language keywords
as function symbols.
Change the way we record goals' purities. Instead of optional features
to indicate impure or semipure, which is error-prone, use a plain
field in the goal_info, accessed in the usual way.
Add a way to represent that a goal contains a trace goal, and should
therefore be treated as if it were impure when considering whether to
optimize it away.
Reformat some comments describing function symbols.
compiler/hlds_out.m:
Output the new construct in the HLDS.
compiler/prog_io_util.m:
Generalize the maybe[123] types to allow the representation of more
than one error message. Add functions to extract the error messages.
Add a maybe4 type. Rename the function symbols of these types to
avoid massive ambiguity.
Change the order of some predicates to bring related predicates
next to each other.
compiler/prog_io.m:
compiler/prog_io_dcg.m:
compiler/prog_io_goal.m:
compiler/prog_io_pragma.m:
Rework these modules almost completely to find and accumulate syntax
errors as terms are being parsed. In some cases, this allowed us to
replace "XXX this is a hack" markers with meaningful error-reporting
code.
In prog_io_goal.m, add code for parsing trace goals.
In a bunch of places, update obsolete coding practices, such as using
nested chains of closures instead of simple sequential code, and
using A0 and A to refer to values of different types (terms and goals
respectively). Use more meaningful variable names.
Break up some too-large predicates.
compiler/superhomogeneous.m:
Find and accumulate syntax errors as terms are being parsed.
compiler/add_clause.m:
Add code to transform trace goals from the parse tree to the HLDS.
This is where the IO state and mutable variable attributes of trace
goals are handled.
Eliminate the practice of using the naming scheme Body0 and Body
to refer to values of different types (prog_item.goal and hlds_goal
respectively).
Use error_util for some error messages.
library/private_builtin.m:
Add the predicates referred to by the transformation in add_clause.m.
compiler/goal_util.m:
Rename a predicate to avoid ambiguity.
compiler/typecheck.m:
Do not print error messages about missing clauses if some errors have
been detected previously.
compiler/purity.m:
Instead of just computing purity, compute (and record) also whether
a goal contains a trace goal. However, treat trace goals as pure.
compiler/mode_info.m:
Add trace goals as a reason for locking variables.
Rename some function symbols to avoid ambiguity.
compiler/modes.m:
When analyzing trace goal scopes, lock the scope's nonlocal variables
to prevent them from being further instantiated.
compiler/det_analysis.m:
Insist on the code in trace goal scopes being det or cc_multi.
compiler/det_report.m:
Generate the error message if the code in a trace goal scope isn't det
or cc_multi.
compiler/simplify.m:
At the end of the front end, eliminate trace goal scopes if their
compile-time condition is false. Transform trace goals with runtime
conditions as described at the top.
Treat goals that contain trace goals as if they were impure when
considering whether to optimize them away.
compiler/mercury_compile.m:
Tell simplify when it is being invoked at the end of the front end.
Rename a predicate to avoid ambiguity.
compiler/trace_params.m:
Provide the predicates simplify.m need to be able to evaluate the trace
goal conditions regarding trace levels.
compiler/trace.m:
compiler/trace_gen.m:
Rename the trace module as trace_gen, since "trace" is now an operator.
Rename some predicates exported by the module, now that it is no longer
possible to preface calls with "trace." as a module qualifier.
compiler/notes/compiler_design.html:
Document this name change.
compiler/options.m:
Rename the trace option as trace_level internally, since "trace"
is now an operator. The user-visible name remains the same.
Add the new --trace-flag option.
Delete an obsolete option.
compiler/handle_options.m:
Rename the function symbols of the grade_component type,
since "trace" is now an operator.
compiler/llds.m:
Extend the LLDS with a mechanism to refer to C global variables.
For now, these are used to refer to C globals that will be created
by mkinit to represent the initial values of the environment variables
referred to by trace goals.
compiler/commit_gen.m:
Check that no trace goal with a runtime condition survives to code
generation; they should have been transformed by simplify.m.
compiler/code_gen.m:
Tell commit_gen.m what kind of scope it is generating code for.
compiler/pragma_c_gen.m:
Generate code for runtime conditions when handling the foreign_procs
created by simplify.m.
compiler/code_info.m:
Allow pragma_c_gen.m to record what environment variables it has
generated references to.
compiler/proc_gen.m:
Record the set of environment variables a procedure refers to
in the LLDS procedure header, for efficient access by llds_out.m.
compiler/llds_out.m:
Handle the new LLDS construct, and tell mkinit which environment
variables need C globals created for them.
compiler/pd_util.m:
Rename some predicates to avoid ambiguity.
compiler/*.m:
Conform to the changes above, mainly the renames of function symbols
and predicates, the changed signatures of some predicates, and the new
handling of purity.
util/mkinit.c:
Generate the definitions and the initializations of any C globals
representing the initial status (set or not set) of environment
variables needed by trace goals.
library/assoc_list.m:
Add some predicates that are useful in prog_io*.m.
library/term_io.m:
Minor cleanup.
tests/hard_coded/trace_goal_{1,2}.{m,exp}:
New test cases to test the new construct, identical except for whether
the trace goal is enabled at compile time.
tests/hard_coded/trace_goal_env_{1,2}.{m,exp}:
New test cases to test the new construct, identical except for whether
the trace goal is enabled at run time.
tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
Enable the new test cases.
tests/invalid/*.err_exp:
Update the expected output for the new versions of the error messages
now being generated.
Estimated hours taken: 18
Branches: main
Move the univ, maybe, pair and unit types from std_util into their own
modules. std_util still contains the general purpose higher-order programming
constructs.
library/std_util.m:
Move univ, maybe, pair and unit (plus any other related types
and procedures) into their own modules.
library/maybe.m:
New module. This contains the maybe and maybe_error types and
the associated procedures.
library/pair.m:
New module. This contains the pair type and associated procedures.
library/unit.m:
New module. This contains the types unit/0 and unit/1.
library/univ.m:
New module. This contains the univ type and associated procedures.
library/library.m:
Add the new modules.
library/private_builtin.m:
Update the declaration of the type_ctor_info struct for univ.
runtime/mercury.h:
Update the declaration for the type_ctor_info struct for univ.
runtime/mercury_mcpp.h:
runtime/mercury_hlc_types.h:
Update the definition of MR_Univ.
runtime/mercury_init.h:
Fix a comment: ML_type_name is now exported from type_desc.m.
compiler/mlds_to_il.m:
Update the the name of the module that defines univs (which are
handled specially by the il code generator.)
library/*.m:
compiler/*.m:
browser/*.m:
mdbcomp/*.m:
profiler/*.m:
deep_profiler/*.m:
Conform to the above changes. Import the new modules where they
are needed; don't import std_util where it isn't needed.
Fix formatting in lots of modules. Delete duplicate module
imports.
tests/*:
Update the test suite to confrom to the above changes.
Estimated hours taken: 6
Branches: main
compiler/*.m:
Convert almost all the compiler modules to use . instead of __ as
the module qualifier.
In some cases, change the names of predicates and types to make them
meaningful without the module qualifier. In particular, most of the
types that used to be referred to with an "mlds__" prefix have been
changed to have a "mlds_" prefix instead of changing the prefix to
"mlds.".
There are no algorithmic changes.
Estimated hours taken: 4
Branches: main
Various cleanups for the modules in the compiler directory. The are
no changes to algorithms except the replacement of some if-then-elses
that would naturally be switches with switches and the replacement of
most of the calls to error/1.
compiler/*.m:
Convert calls to error/1 to calls to unexpected/2 or sorry/2 as
appropriate throughout most or the compiler.
Fix inaccurate assertion failure messages, e.g. identifying the
assertion failure as taking place in the wrong module.
Add :- end_module declarations.
Fix formatting problems and bring the positioning of comments
into line with our current coding standards.
Fix some overlong lines.
Convert some more modules to 4-space indentation. Fix some spots
where previous conversions to 4-space indentation have stuffed
the formatting of the code up.
Fix a bunch of typos in comments.
Use state variables in more places; use library predicates
from the sv* modules where appropriate.
Delete unnecessary and duplicate module imports.
Misc. other small cleanups.
Estimated hours taken: 5
Branches: main
Implement trail usage optimization for the lowlevel backend.
compiler/code_gen.m:
As we generate code for each HLDS goal check if it is safe to omit
trailing operations. Do so, if trail usage optimization is enabled.
Reformat some code for the purposes of readability.
compiler/commit_gen.m:
compiler/disj_gen.m:
compiler/ite_gen.m:
compiler/code_info.m:
Thread the above information down to the relevant parts of the code
generator.
Misc. cleanups: reduce unnecessary module qualification and minor
layout fixes.
compiler/code_util.m:
Add a utility predicate the tests if we are allowed to omit trailing
primitives for a given HLDS goal.
compiler/llds.m:
Add the equivalence type: add_trail_ops == bool.
compiler/hlds_goal.m:
compiler/prog_data.m:
Unrelated changes: fix typos in comments.
Add an end_module declaration to the former.
Estimated hours taken: 8
Branches: main
Improve the error messages generated for determinism errors involving committed
choice contexts. Previously, we printed a message to the effect that e.g.
a cc pred is called in context that requires all solutions, but we didn't say
*why* the context requires all solutions. We now keep track of all the goals
to the right that could fail, since it is these goals that may reject the first
solution of a committed choice goal.
The motivation for this diff was the fact that I found that locating the
failing goal can be very difficult if the conjunction to the right is
a couple of hundred lines long. This would have been a nontrivial problem,
since (a) unifications involving values of user-defined types are committed
choice goals, and (b) we can expect uses of user-defined types to increase.
compiler/det_analysis.m:
Keep track of goals to the right of the current goal that could fail,
and include them in the error representation if required.
compiler/det_report.m:
Include the list of failing goals to the right in the representations
of determinism errors involving committed committed choice goals.
Convert the last part of this module that wasn't using error_util
to use error_util. Make most parts of this module just construct
error message specifications; print those specifications (using
error_util) in only a few places.
compiler/hlds_out.m:
Add a function for use by the new code in det_report.m.
compiler/error_util.m:
Add a function for use by the new code in det_report.m.
compiler/error_util.m:
compiler/compiler_util.m:
Error_util is still changing reasonably often, and yet it is
included in lots of modules, most of which need only a few simple
non-parse-tree-related predicates from it (e.g. unexpected).
Move those predicates to a new module, compiler_util.m. This also
eliminates some undesirable dependencies from libs to parse_tree.
compiler/libs.m:
Include compiler_util.m.
compiler/notes/compiler_design.html:
Document compiler_util.m, and fix the documentation of some other
modules.
compiler/*.m:
Import compiler_util instead of or in addition to error_util.
To make this easier, consistently use . instead of __ for module
qualifying module names.
tests/invalid/det_errors_cc.{m,err_exp}:
Add this new test case to test the error messages for cc contexts.
tests/invalid/det_errors_deet.{m,err_exp}:
Add this new test case to test the error messages for unifications
inside function symbols.
tests/invalid/Mmakefile:
Add the new test cases.
tests/invalid/det_errors.err_exp:
tests/invalid/magicbox.err_exp:
Change the expected output to conform to the change in det_report.m,
which is now more consistent.
Estimated hours taken: 4
Branches: main
compiler/*.m:
Convert a bunch of modules to four-space indentation.
In the process, fix departures from our coding standards.
In some cases, do minor other cleanups such as changing argument orders
to be friendly to state variables.
There are no algorithmic changes.
Estimated hours taken: 3
Branches: main
compiler/*.m:
Import only one module per line in the modules of the compiler
where my previous diff did not already do so.
Misc other cleanups.
Where relevant, use the new mechanism in tree.m.
compiler/tree.m:
Fix a performance problem I noticed while update :- import_module
items. Instead of supplying a function to convert lists of trees
to a tree, make the tree data structure able to hold a list of
subtrees directly. This reduces the number of times where we have to
convert list of trees to trees that are sticks just to stay within
the old definition of what a tree is.
Estimated hours taken: 4
Branches: main
Reduce the dependence of earlier parts of the compiler on the later ones.
Unnecessary import_module declarations in top level modules such as hlds.m
cause unnecessary recompilations when adding new types in later modules,
such as submodules of ll_backend.m. This change reduces the number of such
unnecessary imports.
There are no changes in algorithms, only functionality being moved around.
compiler/code_model.m:
Change this module from being a submodule of backend_libs.m to being a
submodule of hlds.m, since nothing in it is dependent on any backend.
compiler/arg_info.m:
compiler/code_util.m:
Change arg_info.m from being a submodule of ll_backend.m to being a
submodule of hlds.m, since most of it is applicable to all current
and foreseeable backends. Move the one exported predicate that is
ll_backend dependent, and its support predicates, to code_util.m.
compiler/backend_libs.m:
compiler/ll_backend.m:
compiler/hlds.m:
Update include_module declarations in accordance with the above.
compiler/prog_data.m:
compiler/term_util.m:
Instead of defining two separate types for holding argument size and
termination information, one including HLDS-specific information (in
term_util.m) and one not (in prog_data.m), use a polymorphic type
defined in prog_data.m and two monomorphic instances.
compiler/termination.m:
compiler/mercury_to_mercury.m:
Change the predicates for writing out argument size and termination
information to handle the polymorphic type (we don't need special
handling of the monomorphic versions), and move them from termination.m
to mercury_to_mercury.m, since this allows us to avoid some
undesirable dependencies.
compiler/base_typeclass_info.m:
compiler/hlds_code_util.m:
Move the predicate make_instance_string from base_typeclass_info.m
to hlds_code_util.m, again because it allows us to remove some
undesirable dependencies.
compiler/top_level.m:
compiler/backend_libs.m:
compiler/check_hlds.m:
compiler/hlds.m:
compiler/ll_backend.m:
compiler/parse_tree.m:
compiler/transform_hlds.m:
Delete some import_module declarations of other top level modules
in these top level modules. Some imports were totally unnecessary.
Some imports were useful in only a small minority of submodules;
those submodules now import the necessary top level modules directly.
Move remaining import_module declarations to the implementation section
where this is feasible.
Where we still need to import modules we ideally shouldn't, note why.
compiler/*.m:
Update imports of code_util and arg_info.
In some cases, import top level modules no longer imported by the
parent module.
In some cases, delete unnecessary imports.
Estimated hours taken: 2
Branches: main
compiler/*.m:
Import only one compiler module per line. Sort the blocks of imports.
This makes it easier to merge in changes.
In a couple of places, remove unnecessary imports.
The main aim of this change is to make the overall, high-level structure
of the compiler clearer, and to encourage better encapsulation of the
major components.
compiler/libs.m:
compiler/backend_libs.m:
compiler/parse_tree.m:
compiler/hlds.m:
compiler/check_hlds.m:
compiler/transform_hlds.m:
compiler/bytecode_backend.m:
compiler/aditi_backend.m:
compiler/ml_backend.m:
compiler/ll_backend.m:
compiler/top_level.m:
New files. One module for each of the major components of the
Mercury compiler. These modules contain (as separate sub-modules)
all the other modules in the Mercury compiler, except gcc.m and
mlds_to_gcc.m.
Mmakefile:
compiler/Mmakefile:
Handle the fact that the top-level module is now `top_level',
not `mercury_compile' (since `mercury_compile' is a sub-module
of `top_level').
compiler/Mmakefile:
Update settings of *FLAGS-<modulename> to use the appropriate
nested module names.
compiler/recompilation_check.m:
compiler/recompilation_version.m:
compiler/recompilation_usage.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/recompilation.version.m:
Convert the `recompilation_*' modules into sub-modules of the
`recompilation' module.
compiler/*.m:
compiler/*.pp:
Module-qualify the module names in `:- module', `:- import_module',
and `:- use_module' declarations.
compiler/base_type_info.m:
compiler/base_type_layout.m:
Deleted these unused empty modules.
compiler/prog_data.m:
compiler/globals.m:
Move the `foreign_language' type from prog_data to globals.
compiler/mlds.m:
compiler/ml_util.m:
compiler/mlds_to_il.m:
Import `globals', for `foreign_language'.
Mmake.common.in:
trace/Mmakefile:
runtime/Mmakefile:
Rename the %.check.c targets as %.check_hdr.c,
to avoid conflicts with compiler/recompilation.check.c.
Estimated hours taken: 6
Eliminated a lot of the dependencies on the the `code_model' type,
and move that type from llds.m into a new module `code_model'.
The aim of this change is to improve the modularity of the compiler by
reducing the number of places in the compiler front-end that depend
on back-end concepts and the number of places in the MLDS back-end
which depend on the LLDS.
compiler/code_model.m:
New module. Contains the code_model type and associated
procedures.
compiler/llds.m:
Move the code_model type into code_model.m.
compiler/hlds_goal.m:
Move the goal_info_get_code_model procedure into code_model.m,
to avoid having the HLDS modules import code_model.
compiler/hlds_out.m:
Delete `hlds_out__write_code_model', since it wasn't being used.
compiler/hlds_pred.m:
Move the proc_info_interface_code_model procedure into code_model.m,
to avoid having the HLDS modules import code_model.
compiler/goal_path.m:
When computing the `maybe_cut' field for `some' goals,
compute it by comparing the determinism rather than by
comparing the goal_infos.
compiler/unique_modes.m:
Use determinism and test for soln_count = at_most_many
rather than using code_model and testing for model_non.
compiler/inlining.m:
Test for determinism nondet/multi rather than testing
for code_model model_non.
compiler/hlds_pred.m:
compiler/det_report.m:
Change valid_code_model_for_eval_method, which succeeded unless
the eval_method was minimal_model and the code_model was model_det,
to valid_determinism_for_eval_method, which succeeds unless the
eval_method is minimal_model and the determinism cannot fail.
As well as avoiding a dependency on code_model in the HLDS
modules, this also fixes a bug where det_report could give
misleading error messages, saying that `multi' was a valid
determinism for `minimal_model' predicates, when in fact the
compiler will always report a determinism error if you declare
a `minimal_model' predicate with determinism `multi'.
(Actually the code in which this bug occurs is in fact
unreachable, but this is no doubt also a bug... I'll address
that one in a separate change.)
compiler/lookup_switch.m:
Simplify the code a bit by using globals__lookup_*_option
rather than globals__get_option and then getopt__lookup_option.
compiler/*.m:
Add `import_module' declarations for `code_model', and in some
cases remove `import_module' declarations for `llds'.
Estimated hours taken: 0.01
compiler/commit_gen.m:
A new file containing the code tyhat generates code for commits.
It was left out my previous checkin.