mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-05-01 01:04:43 +00:00
Add the new builtin types: int8, uint8, int16, uint16, int32 and uint32.
Support for these new types will need to be bootstrapped over several changes.
This is the first such change and does the following:
- Extends the compiler to recognise 'int8', 'uint8', 'int16', 'uint16', 'int32'
and 'uint32' as builtin types.
- Extends the set of builtin arithmetic, bitwise and relational operators to
cover the new types.
- Extends all of the code generators to handle new types. There currently lots
of limitations and placeholders marked by 'XXX FIXED SIZE INT'. These will
be lifted in later changes.
- Extends the runtimes to support the new types.
- Adds new modules to the standard library intended to hold the basic
operations on the new types. (These are currently empty and not documented.)
This change does not introduce the two 64-bit types, 'int64' and 'uint64'.
Their implementation is more complicated and is best left to a separate change.
compiler/prog_type.m:
compiler/prog_data.m:
compiler/builtin_lib_types.m:
Recognise int8, uint8, int16, uint16, int32 and uint32 as builtin types.
Add new type, int_type/0,that enumerates all the possible integer types.
Extend the cons_id/0 type to cover the new types.
compiler/builtin_ops.m:
Parameterize the integer operations in the unary_op/0 and binary_op/0
types by the new int_type/0 type.
Add builtin operations for all the new types.
compiler/hlds_data.m:
Add new tag types for the new types.
compiler/hlds_pred.m:
Parameterize integers in the table_trie_step/0 type.
compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/export.m:
compiler/foreign.m:
compiler/goal_util.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_dependency_graph.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/implementation_defined_literals.m:
compiler/inst_check.m:
compiler/mercury_to_mercury.m:
compiler/mode_util.m:
compiler/module_qual.qualify_items.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_to_term.m:
compiler/parse_type_name.m:
compiler/polymorphism.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_rep_tables.m:
compiler/prog_util.m:
compiler/rbmm.exection_path.m:
compiler/rtti.m:
compiler/rtti_to_mlds.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/type_constraints.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
Conform to the above changes to the parse tree and HLDS.
compiler/c_util.m:
Support generating the builtin operations for the new types.
doc/reference_manual.texi:
Add the new types to the list of reserved type names.
Add the mapping from the new types to their target language types.
These are commented out for now.
compiler/llds.m:
Replace the lt_integer/0 and lt_unsigned functors of the llds_type/0,
with a single lt_int/1 functor that is parameterized by the int_type/0
type.
Add a representations for constants of the new types to the LLDS.
compiler/call_gen.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/llds_out_data.m:
compiler/llds_out_global.m:
compiler/llds_out_instr.m:
compiler/lookup_switch.m:
compiler/middle_rec.m:
compiler/peephole.m:
compiler/pragma_c_gen.m:
compiler/stack_layout.m:
compiler/string_switch.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
compiler/trace_gen.m:
compiler/transform_llds.m:
Support the new types in the LLDS code generator.
compiler/mlds.m:
Support constants of the new types in the MLDS.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_simplify_switch.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_target_util.m:
Conform to the above changes to the MLDS.
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Generate the appropriate target code for constants of the new
types and operations involving them.
compiler/bytecode.m:
compiler/bytecode_gen.m:
Handle the new types in the bytecode generator; we just abort if we
encounter them for now.
compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_call_gen.m:
compiler/erl_code_util.m:
compiler/erl_rtti.m:
compiler/erl_unify_gen.m:
Handle the new types in the Erlang code generator.
library/private_builtin.m:
Add placeholders for the builtin unify and compare operations for
the new types. Since the bootstrapping compiler will not recognise
the new types we give the polymorphic arguments. These can be
replaced after this change has bootstrapped.
Update the Java list of TypeCtorRep constants.
library/int8.m:
library/int16.m:
library/int32.m:
library/uint8.m:
library/uint16.m:
library/uint32.m:
New modules that will eventually contain builtin operations
on the new types.
library/library.m:
library/MODULES_UNDOC:
Do not include the above modules in the library documentation
for now.
library/construct.m:
library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
deep_profiler/program_representation_utils.m:
mdbcomp/program_representation.m:
Handle the new types.
runtime/mercury_dotnet.cs.in:
java/runtime/TypeCtorRep.java:
runtime/mercury_type_info.h:
Update the list of TypeCtorReps.
configure.ac:
runtime/mercury_conf.h.in:
Check for the header stdint.h.
runtime/mercury_std.h:
Include stdint.h; abort if that header is no present.
runtime/mercury_builtin_types.[ch]:
runtime/mercury_builtin_types_proc_layouts.h:
runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
runtime/mercury_deep_copy_body.h:
runtime/mercury_ml_expand_body.h
runtime/mercury_table_type_body.h:
runtime/mercury_tabling_macros.h:
runtime/mercury_tabling_preds.h:
runtime/mercury_term_size.c:
runtime/mercury_unify_compare_body.h:
Add the new builtin types and handle them throughout the runtime.
218 lines
8.8 KiB
Mathematica
218 lines
8.8 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 hlds.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.builtin_ops.
|
|
:- import_module hlds.code_model.
|
|
:- import_module libs.options.
|
|
:- 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(PredName, Arity, proc(PredId, ProcId), ProcLabel,
|
|
model_det, 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.
|
|
%-----------------------------------------------------------------------------%
|