mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
compiler/inst_lookup.m:
compiler/inst_mode_type_prop.m:
compiler/inst_test.m:
compiler/inst_util.m:
compiler/mode_util.m:
compiler/type_util.m:
Move these modules from the check_hlds package to the hlds package.
The reason is that all the content of five of these modules, and
most of the content of one module (inst_util.m) is not used
exclusively during semantic checking passes. (A later diff
should deal with the exception.) Some are used by the pass that
builds the initial HLDS, and all are used by middle-end and backend
passes. The move therefore reduces the number of inappropriate imports
of the check_hlds package.
compiler/check_hlds.m:
compiler/hlds.m:
Effect the transfer.
compiler/*.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-2020, 2022, 2024-2025 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 hlds.hlds_module.
|
|
:- import_module hlds.type_util.
|
|
:- 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),
|
|
NonLocals = goal_info_get_nonlocals(GoalInfo),
|
|
generate_deconstruction_unification(NonLocals, 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_cmp(eq)
|
|
;
|
|
BuiltinType = builtin_type_float,
|
|
EqOp = float_cmp(eq)
|
|
;
|
|
BuiltinType = builtin_type_char,
|
|
EqOp = int_cmp(int_type_int, eq)
|
|
;
|
|
BuiltinType = builtin_type_int(IntType),
|
|
EqOp = int_cmp(IntType, eq)
|
|
)
|
|
else
|
|
% The else branch handles enumerations.
|
|
EqOp = int_cmp(int_type_int, eq)
|
|
),
|
|
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.
|
|
%---------------------------------------------------------------------------%
|