mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 09:53:36 +00:00
Most compiler passes need to know both the names and the types
of the variables they operate on. Until now, they had to pass along
two separate data structures for that, the varset and the vartypes,
and many operations required looking a variable up in both of these.
The var table is a single data structure that records for each variable
- its name, as the varset has traditionally done,
- its type, as the vartypes has traditionally done,
- the is_dummy_type flag which says whether its type is a dummy type,
which traditionally had to computed afresh at each lookup.
Switch the MLDS code generator to use var_tables instead of varsets and
vartypes. The code generator often needs to know the name and the type
of a variable at the same time, and it often needs to know which variables'
types are dummies, often enough that precomputing this info should be a win.
compiler/var_table.m:
Add this new module which defines the var_table.
Its operations are modelled after the operation in var_types.m.
compiler/hlds.m:
compiler/notes/compiler_design.html:
Add the new module to the hlds package.
compiler/prog_type.m:
compiler/type_util.m:
Move the is_dummy_type from type_util.m, which is in the
check_hlds package, to prog_type.m, which in the parse_tree package,
to avoid having this part of the hlds package depend on check_hlds.
(It already depends on parse_tree, for a lot of different things.)
Given a function and a predicate that each took a vartypes arg,
make new versions that take a var_table arg instead.
Rationalize the argument list of the function.
compiler/ml_gen_info.m:
Replace the varset and vartypes fields of the ml_gen_info with a
var_table field.
compiler/ml_code_util.m:
Replace code that used to operate on varsets and vartypes with code
that operates on var_tables.
Create new versions of a few operations to exploit the info in var_tables.
Give some predicates more meaningful names.
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/ml_unify_gen_util.m:
Replace code that used to operate on varsets and vartypes with code
that operates on var_tables.
In ml_switch_gen.m and ml_tag_switch.m, put some predicates' arguments
into an reasonable order by moving related args next to each other.
compiler/vartypes.m:
Delete an operation that was only needed in the MLDS backend,
in code that this diff replaces.
compiler/switch_util.m:
Put the larger input first in the arg list of a predicate.
compiler/closure_gen.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/export.m:
compiler/lambda.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds.m:
compiler/llds_out_instr.m:
compiler/mark_tail_calls.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/tag_switch.m:
compiler/term_constr_util.m:
compiler/tupling.m:
compiler/unify_gen.m:
compiler/unify_gen_deconstruct.m:
compiler/var_locn.m:
Conform to the changes above.
185 lines
6.9 KiB
Mathematica
185 lines
6.9 KiB
Mathematica
%---------------------------------------------------------------------------e
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------e
|
|
% Copyright (C) 1994-2012 The University of Melbourne.
|
|
% Copyright (C) 2013-2018 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: unify_gen.m.
|
|
%
|
|
% This module handles code generation for "simple" unifications,
|
|
% i.e. those unifications which are simple enough for us to generate
|
|
% inline code.
|
|
%
|
|
% For "complicated" unifications, we generate a call to an out-of-line
|
|
% unification predicate (the call is handled in call_gen.m) - and then
|
|
% eventually generate the out-of-line code (unify_proc.m).
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.unify_gen.
|
|
:- interface.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.code_model.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module ll_backend.code_info.
|
|
:- import_module ll_backend.code_loc_dep.
|
|
:- import_module ll_backend.llds.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Generate LLDS code for a unification.
|
|
%
|
|
:- pred generate_unification(code_model::in, unification::in,
|
|
hlds_goal_info::in, llds_code::out,
|
|
code_info::in, code_info::out, code_loc_dep::in, code_loc_dep::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.builtin_ops.
|
|
:- import_module check_hlds.
|
|
:- import_module check_hlds.type_util.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module ll_backend.unify_gen_construct.
|
|
:- import_module ll_backend.unify_gen_deconstruct.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module cord.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
:- import_module term.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
generate_unification(CodeModel, Unification, GoalInfo, Code, !CI, !CLD) :-
|
|
(
|
|
Unification = assign(LHSVar, RHSVar),
|
|
expect(unify(CodeModel, model_det), $pred, "assign not det"),
|
|
generate_assignment_unification(LHSVar, RHSVar, Code, !CLD)
|
|
;
|
|
Unification = simple_test(VarA, VarB),
|
|
expect(unify(CodeModel, model_semi), $pred, "simple_test not semidet"),
|
|
generate_simple_test_unification(VarA, VarB, Code, !CI, !CLD)
|
|
;
|
|
Unification = construct(LHSVar, ConsId, RHSVars, ArgModes,
|
|
HowToConstruct, _CellIsUnique, SubInfo),
|
|
expect(unify(CodeModel, model_det), $pred, "construct not det"),
|
|
(
|
|
SubInfo = no_construct_sub_info,
|
|
MaybeTakeAddr = no,
|
|
MaybeSize = no
|
|
;
|
|
SubInfo = construct_sub_info(MaybeTakeAddr, MaybeSize)
|
|
),
|
|
( if
|
|
( variable_is_forward_live(!.CLD, LHSVar)
|
|
; MaybeTakeAddr = yes(_)
|
|
)
|
|
then
|
|
(
|
|
MaybeTakeAddr = yes(TakeAddr)
|
|
;
|
|
MaybeTakeAddr = no,
|
|
TakeAddr = []
|
|
),
|
|
generate_construction_unification(LHSVar, ConsId,
|
|
RHSVars, ArgModes, HowToConstruct, TakeAddr, MaybeSize,
|
|
GoalInfo, Code, !CI, !CLD)
|
|
else
|
|
Code = empty
|
|
)
|
|
;
|
|
Unification = deconstruct(LHSVar, ConsId, RHSVars, ArgModes,
|
|
CanFail, CanCGC),
|
|
generate_deconstruction_unification(LHSVar, ConsId, RHSVars, ArgModes,
|
|
CanFail, CanCGC, Code, !CI, !CLD)
|
|
;
|
|
Unification = complicated_unify(_, _, _),
|
|
% These should have been converted into calls to unification predicates
|
|
% by the simplification pass.
|
|
unexpected($pred, "complicated unify")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Generate code for the assignment unification LHSVar := RHSVar.
|
|
%
|
|
:- pred generate_assignment_unification(prog_var::in, prog_var::in,
|
|
llds_code::out, code_loc_dep::in, code_loc_dep::out) is det.
|
|
|
|
generate_assignment_unification(LHSVar, RHSVar, Code, !CLD) :-
|
|
( if variable_is_forward_live(!.CLD, LHSVar) then
|
|
assign_var_to_var(LHSVar, RHSVar, !CLD),
|
|
% The assignment is cached; we do not generate any code for it *here*
|
|
% (though we *will* generate code for it later, when the value
|
|
% of LHSVar is materialized).
|
|
Code = empty
|
|
else
|
|
% Mode analysis reports free-free unifications as assignments
|
|
% to a dead variable. For such unifications, we of course
|
|
% do not generate any code.
|
|
Code = empty
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% generate_simple_test_unification(VarA, VarB, Code, !CI, !CLD):
|
|
%
|
|
% We generate code for a simple test unification by flushing both variables
|
|
% from the cache, and producing code that branches to the location that is
|
|
% appropriate for a failure in the current environment if the two values
|
|
% are not the same. Simple tests are in-in unifications on enumerations,
|
|
% integers, strings and floats.
|
|
%
|
|
:- pred generate_simple_test_unification(prog_var::in, prog_var::in,
|
|
llds_code::out, code_info::in, code_info::out,
|
|
code_loc_dep::in, code_loc_dep::out) is det.
|
|
|
|
generate_simple_test_unification(VarA, VarB, Code, !CI, !CLD) :-
|
|
Type = variable_type(!.CI, VarA),
|
|
get_module_info(!.CI, ModuleInfo),
|
|
IsDummyType = is_type_a_dummy(ModuleInfo, Type),
|
|
(
|
|
IsDummyType = is_dummy_type,
|
|
Code = empty
|
|
;
|
|
IsDummyType = is_not_dummy_type,
|
|
( if Type = builtin_type(BuiltinType) then
|
|
(
|
|
BuiltinType = builtin_type_string,
|
|
EqOp = str_eq
|
|
;
|
|
BuiltinType = builtin_type_float,
|
|
EqOp = float_eq
|
|
;
|
|
BuiltinType = builtin_type_char,
|
|
EqOp = eq(int_type_int)
|
|
;
|
|
BuiltinType = builtin_type_int(IntType),
|
|
EqOp = eq(IntType)
|
|
)
|
|
else
|
|
% The else branch handles enumerations.
|
|
EqOp = eq(int_type_int)
|
|
),
|
|
produce_variable(VarA, VarCodeA, VarRvalA, !CLD),
|
|
produce_variable(VarB, VarCodeB, VarRvalB, !CLD),
|
|
fail_if_rval_is_false(binop(EqOp, VarRvalA, VarRvalB), FailCode,
|
|
!CI, !CLD),
|
|
Code = VarCodeA ++ VarCodeB ++ FailCode
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module ll_backend.unify_gen.
|
|
%---------------------------------------------------------------------------%
|