mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
compiler/hlds_pred.m:
Replace the arity field in pred_infos with a pred_form_arity field.
Move the pred_info's pred_or_func field to its usual position
in predicate/function descriptions: at the front (pred/func name/arity).
compiler/hlds_pred.m:
Change two utility operations to return pred_form_arities instead of
just arities, since they get them from pred_infos.
compiler/inst_mode_type_prop.m:
compiler/llds.m:
compiler/rtti.m:
Change some fields whose types used to be arity (or int) to be
pred_form_arity.
In llds.m, include a pred_or_func field in c_procedures,
for use in procedure-start comments.
mdbcomp/prim_data.m:
mdbcomp/program_representation.m:
Add notes about two possible future improvements along similar lines.
compiler/prog_data.m:
Add a utility function to calculate the number of extra arguments
added to predicates/functions by compiler passes such as polymorphism.
compiler/add_pragma.m:
Conform to the changes above.
Fix a bug in an error message about ":- external" pragmas:
the message used the pred_form arity instead of the user arity.
(See the diff to external2.err_exp below.)
compiler/hlds_defns.m:
Conform to the changes above.
Include pred/func prefixes before name/arity pairs in the output
where relavnt. (The user guide does not need to be updated, because
its wording permits both the old and the new behavior.)
Fix two separate bugs that referred to functions in user-facing output
with the predicate form of their arity.
compiler/table_gen.m:
compiler/unused_args.m:
Conform to the changes above.
Fix a bug in each module that referred to functions in user-facing output
with the predicate form of their arity.
compiler/recompilation.usage.m:
compiler/xml_documentation.m:
Conform to the changes above.
Mark a probable bug in each module with an XXX.
compiler/direct_arg_in_out.m:
Conform to the changes above.
Improve the wording of an error message a bit.
(See the diff to gh72_errors.err_exp below.)
compiler/accumulator.m:
compiler/bytecode_gen.m:
compiler/complexity.m:
compiler/default_func_mode.m:
compiler/det_report.m:
compiler/distance_granularity.m:
compiler/equiv_type_hlds.m:
compiler/exception_analysis.m:
compiler/higher_order.m:
compiler/hlds_defns.m:
compiler/hlds_error_util.m:
compiler/hlds_module.m:
compiler/intermod.m:
compiler/intermod_order_pred_info.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/llds_out_file.m:
compiler/mercury_compile_llds_back_end.m:
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/mode_errors.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/old_type_constraints.m:
compiler/optimize.m:
compiler/polymorphism.m:
compiler/polymorphism_goal.m:
compiler/post_typecheck.m:
compiler/pre_typecheck.m:
compiler/pred_table.m:
compiler/proc_gen.m:
compiler/rbmm.region_transformation.m:
compiler/recompilation.usage.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/simplify_goal_call.m:
compiler/ssdebug.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_initial.m:
compiler/termination.m:
compiler/trailing_analysis.m:
compiler/transform_llds.m:
compiler/tupling.m:
compiler/type_class_info.m:
compiler/typecheck.m:
compiler/typecheck_error_undef.m:
compiler/types_into_modes.m:
compiler/xml_documentation.m:
Conform to the changes above.
compiler/recompilation.m:
Add a note.
compiler/parse_tree_out_sym_name.m:
Improve variable names.
tests/invalid/external2.err_exp:
Expect the fixed arity in an error message.
tests/invalid/gh72_errors.err_exp:
Expect the expanded text of an error message.
219 lines
8.9 KiB
Mathematica
219 lines
8.9 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1998-2001,2003-2007, 2009-2011 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: transform_llds.
|
|
% Main author: petdr.
|
|
%
|
|
% This module does source to source transformations of the llds data
|
|
% structure. This is sometimes necessary to avoid limits in some compilers.
|
|
%
|
|
% This module currently transforms computed gotos into a binary search down to
|
|
% smaller computed gotos. This avoids a limitation in the lcc compiler.
|
|
%
|
|
% If accurate GC is enabled, we also append a module containing an end label
|
|
% to the list of comp_gen_c_modules.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.transform_llds.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module ll_backend.llds.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred transform_llds(globals::in, c_file::in, c_file::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.builtin_ops.
|
|
:- import_module hlds.
|
|
:- import_module hlds.code_model.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module libs.options.
|
|
:- import_module libs.trace_params.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module counter.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module set.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
transform_llds(Globals, !CFile) :-
|
|
ModuleName = !.CFile ^ cfile_modulename,
|
|
Modules0 = !.CFile ^ cfile_code,
|
|
% Split up large computed gotos.
|
|
globals.lookup_int_option(Globals, max_jump_table_size, MaxSize),
|
|
( if MaxSize = 0 then
|
|
Modules1 = Modules0
|
|
else
|
|
transform_c_module_list(Modules0, Modules1, MaxSize)
|
|
),
|
|
% Append an end label for accurate GC.
|
|
globals.get_gc_method(Globals, GC),
|
|
( if
|
|
GC = gc_accurate,
|
|
Modules1 = [_ | _]
|
|
then
|
|
list.det_last(Modules1, LastModule),
|
|
LastModule = comp_gen_c_module(LastModuleName, _),
|
|
Modules = Modules1 ++
|
|
[gen_end_label_module(ModuleName, LastModuleName)]
|
|
else
|
|
Modules = Modules1
|
|
),
|
|
!CFile ^ cfile_code := Modules.
|
|
|
|
% For LLDS native GC, we need to add a dummy comp_gen_c_module at the end
|
|
% of the list. This dummy module contains only a single dummy procedure
|
|
% which in turn contains only a single label, for which there is no
|
|
% stack layout structure. The point of this is to ensure that the
|
|
% address of this label gets inserted into the entry table, so that
|
|
% we know where the preceding procedure finishes when mapping from
|
|
% instruction pointer values to stack layout entries.
|
|
%
|
|
% Without this, we might think that the following C function was
|
|
% actually part of the last Mercury procedure in the preceding module,
|
|
% and then incorrectly use the stack layout of the Mercury procedure
|
|
% if we happened to get a heap overflow signal (SIGSEGV) while in that
|
|
% C function.
|
|
%
|
|
% Note that it is not sufficient to generate a label at end of the module,
|
|
% because GCC (e.g. GCC 3.2) sometimes reorders code within a single C
|
|
% function, so that a label declared at the end of the module might not
|
|
% be actually have highest address. So we generate a new module (which
|
|
% corresponds to a new C function). XXX Hopefully GCC won't mess with the
|
|
% order of the functions ...
|
|
%
|
|
:- func gen_end_label_module(module_name, string) = comp_gen_c_module.
|
|
|
|
gen_end_label_module(ModuleName, LastModule) = EndLabelModule :-
|
|
Arity = 0,
|
|
ProcId = hlds_pred.initial_proc_id,
|
|
PredId = hlds_pred.initial_pred_id,
|
|
PredName = "ACCURATE_GC_END_LABEL",
|
|
ProcLabel = ordinary_proc_label(ModuleName, pf_predicate, ModuleName,
|
|
PredName, Arity, proc_id_to_int(ProcId)),
|
|
Instrs = [llds_instr(label(entry_label(entry_label_local, ProcLabel)),
|
|
"label to indicate end of previous procedure")],
|
|
DummyProc = c_procedure(pf_predicate, PredName, user_arity(Arity),
|
|
proc(PredId, ProcId), ProcLabel, model_det, eff_trace_level_none,
|
|
Instrs, counter.init(0), must_not_alter_rtti, set.init),
|
|
EndLabelModule = comp_gen_c_module(LastModule ++ "_END", [DummyProc]).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred transform_c_module_list(list(comp_gen_c_module)::in,
|
|
list(comp_gen_c_module)::out, int::in) is det.
|
|
|
|
transform_c_module_list([], [], _MaxSize).
|
|
transform_c_module_list([Module0 | Module0s], [Module | Modules], MaxSize) :-
|
|
transform_c_module(Module0, Module, MaxSize),
|
|
transform_c_module_list(Module0s, Modules, MaxSize).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred transform_c_module(comp_gen_c_module::in, comp_gen_c_module::out,
|
|
int::in) is det.
|
|
|
|
transform_c_module(Module0, Module, MaxSize) :-
|
|
Module0 = comp_gen_c_module(Name, Procedures0),
|
|
transform_c_procedure_list(Procedures0, Procedures, MaxSize),
|
|
Module = comp_gen_c_module(Name, Procedures).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred transform_c_procedure_list(list(c_procedure)::in,
|
|
list(c_procedure)::out, int::in) is det.
|
|
|
|
transform_c_procedure_list([], [], _MaxSize).
|
|
transform_c_procedure_list([Proc0 | Proc0s], [Proc | Procs], MaxSize) :-
|
|
transform_c_procedure(Proc0, Proc, MaxSize),
|
|
transform_c_procedure_list(Proc0s, Procs, MaxSize).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred transform_c_procedure(c_procedure::in, c_procedure::out, int::in)
|
|
is det.
|
|
|
|
transform_c_procedure(!Proc, MaxSize) :-
|
|
ProcLabel = !.Proc ^ cproc_proc_label,
|
|
Instrs0 = !.Proc ^ cproc_code,
|
|
C0 = !.Proc ^ cproc_label_nums,
|
|
transform_instructions(Instrs0, Instrs, C0, C, ProcLabel, MaxSize),
|
|
!Proc ^ cproc_code := Instrs,
|
|
!Proc ^ cproc_label_nums := C.
|
|
|
|
:- pred transform_instructions(list(instruction)::in, list(instruction)::out,
|
|
counter::in, counter::out, proc_label::in, int::in) is det.
|
|
|
|
transform_instructions([], [], !C, _, _).
|
|
transform_instructions([Instr0 | Instrs0], Instrs, !C, ProcLabel, MaxSize) :-
|
|
transform_instructions(Instrs0, InstrsTail, !C, ProcLabel, MaxSize),
|
|
( if
|
|
Instr0 = llds_instr(computed_goto(Rval, Targets), Comment),
|
|
list.length(Targets, NumTargets),
|
|
NumTargets > MaxSize
|
|
then
|
|
split_computed_goto(Rval, Targets, Comment, InstrsHead, !C,
|
|
MaxSize, NumTargets, ProcLabel),
|
|
list.append(InstrsHead, InstrsTail, Instrs)
|
|
else
|
|
Instrs = [Instr0 | InstrsTail]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Given the pieces of a computed_goto instruction, split the table
|
|
% in half as many times as necessary to bring the jump table size
|
|
% below MaxSize, doing a binary search on the way.
|
|
%
|
|
:- pred split_computed_goto(rval::in, list(maybe(label))::in, string::in,
|
|
list(instruction)::out, counter::in, counter::out, int::in, int::in,
|
|
proc_label::in) is det.
|
|
|
|
split_computed_goto(Rval, Targets, Comment, Instrs, !C, MaxSize, NumTargets,
|
|
ProcLabel) :-
|
|
( if NumTargets =< MaxSize then
|
|
Instrs = [llds_instr(computed_goto(Rval, Targets), Comment)]
|
|
else
|
|
counter.allocate(LabelNum, !C),
|
|
Mid = NumTargets // 2,
|
|
list.det_split_list(Mid, Targets, StartTargets, EndTargets),
|
|
Index = binop(int_sub(int_type_int), Rval, const(llconst_int(Mid))),
|
|
Test = binop(int_ge(int_type_int), Rval, const(llconst_int(Mid))),
|
|
ElseAddr = code_label(internal_label(LabelNum, ProcLabel)),
|
|
IfInstr = llds_instr(if_val(Test, ElseAddr), "binary search"),
|
|
ElseInstr = llds_instr(label(internal_label(LabelNum, ProcLabel)), ""),
|
|
|
|
split_computed_goto(Rval, StartTargets, Comment ++ " then",
|
|
ThenInstrs, !C, MaxSize, Mid, ProcLabel),
|
|
split_computed_goto(Index, EndTargets, Comment ++ " else",
|
|
ElseInstrs, !C, MaxSize, NumTargets - Mid, ProcLabel),
|
|
|
|
Instrs = [IfInstr | ThenInstrs] ++ [ElseInstr | ElseInstrs]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module ll_backend.transform_llds.
|
|
%-----------------------------------------------------------------------------%
|