Files
mercury/compiler/implementation_defined_literals.m
Zoltan Somogyi 884838b9df If the backend supports constant structures, and we do not need unifications
Estimated hours taken: 8
Branches: main

If the backend supports constant structures, and we do not need unifications
to retain their original shapes, then convert each from_ground_term scope
into a unification with a cons_id that represents the ground term being
built up.

This speeds up the compilation of training_cars_full.m by about 6%.

compiler/simplify.m:
	Make the conversion if enabled. By doing the conversion in this phase,
	we don't have to teach the semantic analysis passes about unifications
	with the new cons_id, but we do get the benefit of later passes being
	faster, because they have less code to process.

compiler/const_struct.m:
	The declarative debugger does not yet know how to handle the new
	cons_id, so do not introduce it if we are preparing for declarative
	debugging.

compiler/trace_params.m:
	Export a predicate for const_struct.m.

compiler/prog_data.m:
	Add the new cons_id, ground_term_const.

compiler/hlds_data.m:
	Add the tag of the new cons_id, ground_term_const_tag.

compiler/hlds_code_util.m:
	Convert the new cons_id to the new cons_tag.

	Fix an old problem with that conversion process: it always converted
	tuple_cons to single_functor_tag. However, arity-zero tuples are
	(dummy) constants, not heap cells, so we now convert them to a (dummy)
	integer tag. This matters now because the process that generates
	code (actually data) for constant structures handles the cons_tags that
	build constants and heap cells separately. As a side benefit, we
	no longer reserve a word-sized heap cell for arity-zero tuples.

compiler/unify_gen.m:
compiler/ml_unify_gen.m:
	Implement the generation of code for arbitrary constant structures,
	not just those that can implement typeinfos and typeclass_infos.

compiler/term_norm.m:
	Compute the sizes of ground terms for each of our norms.

compiler/term_traversal.m:
	Manage the computation of sizes of ground terms.

	Simplify and thereby speed up a predicate.

compiler/term_constr_build.m:
	Note that we should manage the computation of sizes of ground terms.

compiler/term_util.m:
	Simplify the style of a predicate.

compiler/layout.m:
	Give some field names prefixes to avoid ambiguities.

compiler/bytecode_gen.m:
compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/dependency_graph.m:
compiler/erl_unify_gen.m:
compiler/export.m:
compiler/higher_order.m:
compiler/hlds_out_mode.m:
compiler/hlds_out_util.m:
compiler/implementation_defined_literals.m:
compiler/inst_check.m:
compiler/mercury_to_mercury.m:
compiler/ml_global_data.m:
compiler/ml_type_gen.m:
compiler/mode_util.m:
compiler/module_qual.m:
compiler/polymorphism.m:
compiler/prog_rep.m:
compiler/prog_type.m:
compiler/prog_util.m:
compiler/rbmm.execution_path.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/type_ctor_info.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
	Conform to the changes above.

tests/hard_coded/ground_terms.{m,exp}:
	A new test case to test the handling of ground terms.

tests/hard_coded/Mmakefile:
tests/hard_coded/Mercury.options:
	Enable the new test case.
2012-06-11 03:13:24 +00:00

235 lines
9.3 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2008-2012 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: implementation_defined_literals.m.
% Author: wangp.
%
% This module replaces "implementation-defined literals" such as $file and
% $line by real constants. We transform clauses rather than procedures
% because, currently, clauses are written out to `.opt' files and $file and
% $line need to be substituted beforehand.
%
%-----------------------------------------------------------------------------%
:- module check_hlds.implementation_defined_literals.
:- interface.
:- import_module hlds.hlds_module.
:- pred subst_impl_defined_literals(module_info::in, module_info::out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.
:- import_module hlds.hlds_clauses.
:- import_module hlds.hlds_goal.
:- import_module hlds.hlds_out.
:- import_module hlds.hlds_out.hlds_out_util.
:- import_module hlds.hlds_pred.
:- import_module libs.
:- import_module libs.handle_options.
:- import_module mdbcomp.
:- import_module mdbcomp.prim_data.
:- import_module parse_tree.
:- import_module parse_tree.prog_data.
:- import_module list.
:- import_module map.
:- import_module require.
:- import_module term.
:- type subst_literals_info
---> subst_literals_info(
module_info,
pred_info,
pred_id
).
%-----------------------------------------------------------------------------%
subst_impl_defined_literals(!ModuleInfo) :-
module_info_get_preds(!.ModuleInfo, Preds0),
map.map_values(subst_literals_in_pred(!.ModuleInfo), Preds0, Preds),
module_info_set_preds(Preds, !ModuleInfo).
:- pred subst_literals_in_pred(module_info::in, pred_id::in, pred_info::in,
pred_info::out) is det.
subst_literals_in_pred(ModuleInfo, PredId, PredInfo0, PredInfo) :-
pred_info_get_clauses_info(PredInfo0, ClausesInfo0),
clauses_info_get_clauses_rep(ClausesInfo0, ClausesRep0, ItemNumbers),
get_clause_list(ClausesRep0, Clauses0),
Info = subst_literals_info(ModuleInfo, PredInfo0, PredId),
list.map(subst_literals_in_clause(Info), Clauses0, Clauses),
set_clause_list(Clauses, ClausesRep),
clauses_info_set_clauses_rep(ClausesRep, ItemNumbers,
ClausesInfo0, ClausesInfo),
pred_info_set_clauses_info(ClausesInfo, PredInfo0, PredInfo).
:- pred subst_literals_in_clause(subst_literals_info::in, clause::in,
clause::out) is det.
subst_literals_in_clause(Info, Clause0, Clause) :-
Body0 = Clause0 ^ clause_body,
subst_literals_in_goal(Info, Body0, Body),
Clause = Clause0 ^ clause_body := Body.
:- pred subst_literals_in_goal(subst_literals_info::in, hlds_goal::in,
hlds_goal::out) is det.
subst_literals_in_goal(Info, Goal0, Goal) :-
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
(
GoalExpr0 = unify(Var, RHS0, Mode, Kind, UnifyContext),
(
RHS0 = rhs_functor(ConsId, _, _),
(
ConsId = impl_defined_const(Name),
Context = goal_info_get_context(GoalInfo0),
make_impl_defined_literal(Var, Name, Context, Info, Goal1),
Goal1 = hlds_goal(GoalExpr, _),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
( ConsId = cons(_, _, _)
; ConsId = tuple_cons(_)
; ConsId = closure_cons(_, _)
; ConsId = int_const(_)
; ConsId = float_const(_)
; ConsId = char_const(_)
; ConsId = string_const(_)
; ConsId = type_ctor_info_const(_, _, _)
; ConsId = base_typeclass_info_const(_, _, _, _)
; ConsId = type_info_cell_constructor(_)
; ConsId = typeclass_info_cell_constructor
; ConsId = type_info_const(_)
; ConsId = typeclass_info_const(_)
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
),
Goal = Goal0
)
;
RHS0 = rhs_lambda_goal(LambdaPurity, Groundness, PredOrFunc,
EvalMethod, LambdaNonLocals, LambdaQuantVars,
LambdaModes, LambdaDetism, LambdaGoal0),
subst_literals_in_goal(Info, LambdaGoal0, LambdaGoal),
RHS = rhs_lambda_goal(LambdaPurity, Groundness, PredOrFunc,
EvalMethod, LambdaNonLocals, LambdaQuantVars,
LambdaModes, LambdaDetism, LambdaGoal),
GoalExpr = unify(Var, RHS, Mode, Kind, UnifyContext),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
RHS0 = rhs_var(_),
Goal = Goal0
)
;
GoalExpr0 = negation(SubGoal0),
subst_literals_in_goal(Info, SubGoal0, SubGoal),
GoalExpr = negation(SubGoal),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = scope(Reason, SubGoal0),
% Implementation-defined literals may appear in
% from_ground_term_construct scopes.
subst_literals_in_goal(Info, SubGoal0, SubGoal),
GoalExpr = scope(Reason, SubGoal),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = conj(ConjType, Goals0),
list.map(subst_literals_in_goal(Info), Goals0, Goals),
GoalExpr = conj(ConjType, Goals),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = disj(Goals0),
list.map(subst_literals_in_goal(Info), Goals0, Goals),
GoalExpr = disj(Goals),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = switch(Var, CanFail, Cases0),
list.map(subst_literals_in_case(Info), Cases0, Cases),
GoalExpr = switch(Var, CanFail, Cases),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
subst_literals_in_goal(Info, Cond0, Cond),
subst_literals_in_goal(Info, Then0, Then),
subst_literals_in_goal(Info, Else0, Else),
GoalExpr = if_then_else(Vars, Cond, Then, Else),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
GoalExpr0 = shorthand(Shorthand0),
(
Shorthand0 = bi_implication(A0, B0),
subst_literals_in_goal(Info, A0, A),
subst_literals_in_goal(Info, B0, B),
Shorthand = bi_implication(A, B)
;
Shorthand0 = atomic_goal(GoalType, OuterVars, InnerVars,
OutputVars, MainGoal0, OrElseGoals0, OrElseInners),
subst_literals_in_goal(Info, MainGoal0, MainGoal),
list.map(subst_literals_in_goal(Info), OrElseGoals0, OrElseGoals),
Shorthand = atomic_goal(GoalType, OuterVars, InnerVars,
OutputVars, MainGoal, OrElseGoals, OrElseInners)
;
Shorthand0 = try_goal(MaybeIOVars, ResultVar, TryGoal0),
subst_literals_in_goal(Info, TryGoal0, TryGoal),
Shorthand = try_goal(MaybeIOVars, ResultVar, TryGoal)
),
GoalExpr = shorthand(Shorthand),
Goal = hlds_goal(GoalExpr, GoalInfo0)
;
( GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
; GoalExpr0 = generic_call(_, _, _, _, _)
; GoalExpr0 = plain_call(_, _, _, _, _, _)
),
Goal = Goal0
).
:- pred subst_literals_in_case(subst_literals_info::in, case::in, case::out)
is det.
subst_literals_in_case(Info, Case0, Case) :-
Case0 = case(MainConsId, OtherConsIds, Goal0),
subst_literals_in_goal(Info, Goal0, Goal),
Case = case(MainConsId, OtherConsIds, Goal).
:- pred make_impl_defined_literal(prog_var::in, string::in,
term.context::in, subst_literals_info::in, hlds_goal::out) is det.
make_impl_defined_literal(Var, Name, Context, Info, Goal) :-
Context = term.context(File, Line),
Info = subst_literals_info(ModuleInfo, PredInfo, PredId),
( Name = "file" ->
make_string_const_construction(Var, File, Goal)
; Name = "line" ->
make_int_const_construction(Var, Line, Goal)
; Name = "module" ->
ModuleName = pred_info_module(PredInfo),
Str = sym_name_to_string(ModuleName),
make_string_const_construction(Var, Str, Goal)
; Name = "pred" ->
Str = pred_id_to_string(ModuleInfo, PredId),
make_string_const_construction(Var, Str, Goal)
; Name = "grade" ->
module_info_get_globals(ModuleInfo, Globals),
grade_directory_component(Globals, Grade),
make_string_const_construction(Var, Grade, Goal)
;
% These should have been caught during type checking.
unexpected($module, $pred, "unknown literal")
).
%-----------------------------------------------------------------------------%
:- end_module check_hlds.implementation_defined_literals.
%-----------------------------------------------------------------------------%