Files
mercury/runtime/mercury_construct.c
Julien Fischer 092e175f45 Add a builtin unsigned word sized integer type -- Part 1.
Add a new builtin type: uint, which is an unsigned word sized integer type.
Support for this new type will need be bootstrapped over several changes.
This is the first such change and does the following:

- Extends the compiler to recognize 'uint' as a builtin type.
- Extends the set of builtin operations to include relational and (some)
  arithmetic operations on uints.
- Extends all of the code generators to handle the above.  There are some
  limitations currently marked by 'XXX UINT'.  These will be lifted once
  the compiler recognised uint and additional library support becomes
  available.
- Extends the runtime to support uints.

compiler/prog_type.m:
compiler/prog_data.m:
compiler/builtin_lib_types.m:
    Recognize uint as a builtin type.

    Add a new alternative to the cons_id/0 type corresponding to the uint type
    -- for bootstrapping purposes its argument is currently an int.

compiler/builtin_ops.m:
    Add builtin relational and arithmetic operations on uints.  Note that the
    existing 'unsigned_le' operation is actually intended for use with signed
    values.  Rather than attempt to modify its meaning, I have just added new
    operations specific to the uint type.

compiler/hlds_data.m:
    Add a new tag type for uints.

compiler/type_ctor_info.m:
    Recognise uint as a builtin.

    Bump the RTTI version number here.

compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/dependency_graph.m:
compiler/export.m:
compiler/foreign.m:
compiler/goal_util.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.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/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.execution_path.m:
compiler/rtti.m:
compiler/special_pred.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/type_constraints.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
    Conform to the above changes to the parse tree and HLDS.

compiler/c_util.m:
    Support generating builtin operations for uints.

compiler/llds.m:
    Add a representation for uint constants to the LLDS.

    Map uints onto MR_Unsigned.

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_instr.m:
compiler/opt_debug.m:
compiler/opt_util.m:
    Support uints in the LLDS code generator.

compiler/mlds.m:
     Support uint constants in the MLDS.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_global_data.m:
compiler/ml_simplify_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/rtti_to_mlds.m:
    Conform to the above change to the MLDS.

compiler/mlds_to_c.m:
compiler/mlds_to_java.m:
compiler/mlds_to_cs.m:
     Generate the appropriate target code for uint constants and uint
     relational operations.

compiler/bytecode.m:
compiler/bytecode_gen.m:
     Handle uints 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 uints in the Erlang code generator.

library/private_builtin.m:
    Add placeholders for builtin_{unify,compare}_uint.  Since the
    bootstrapping compiler will not recognize uint as a type, we
    give them polymorphic arguments.  These can be replaced after
    this change has bootstrapped.

    Update the Java list of TypeCtorRep constants, which for some
    reason is defined here.

library/uint.m:
    New module that will eventually contain operations on uints.

library/MODULES_DOCS:
library/library.m:
     Add the uint module.

library/construct.m:
library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
mdbcomp/program_representation.m:
     Handle uints.

deep_profiler/program_representation_utils.m:
     Conform to the above change.

runtime/mercury_dotnet.cs.in:
     Update the list of TypeCtorReps for C#

java/runtime/TypeCtorRep.java:
     Update this, although the actual TypeCtorRep constants
     are defined the library.

runtime/mercury_type_info.h:
    Bump the RTTI version number.

    Add an alternative for uints to the tyepctor rep enum.

runtime/mercury_builtin_types.{h,c}:
runtime/mercury_builtin_types_proc_layouts.h:
runtime/mercury_deconstruct.c:
runtime/mercury_deep_copy_body.h:
runtime/mercury_table_type_body.h:
runtime/mercury_tabling.h:
runtime/mercury_tabling_macros.h:
runtime/mercury_unify_compare_body.h:
    Add uint as a builtin type and handle it throughout the runtime.

runtime/mercury_grade.h:
    Bump the binary compatibility version.

runtime/mercury_term_size.c:
runtime/mercury_ml_expand_body.h:
    Handle uint and fix probable bugs with the handling of ints on
    64-bit Windows.
2016-10-24 12:55:35 +11:00

357 lines
12 KiB
C

// vim: ts=4 sw=4 expandtab ft=c
// Copyright (C) 2002-2005, 2007 The University of Melbourne.
// This file may only be copied under the terms of the GNU Library General
// Public License - see the file COPYING.LIB in the Mercury distribution.
// mercury_construct.c
//
// This file provides utility functions for constructing terms, for use by
// the standard library.
#include "mercury_conf.h"
#ifndef MR_HIGHLEVEL_CODE
#include "mercury_imp.h"
#endif
#include "mercury_type_info.h"
#include "mercury_construct.h"
#include "mercury_univ.h"
#include "mercury_misc.h" // for MR_fatal_error()
static int MR_get_functor_info(MR_TypeInfo type_info, int functor_number,
MR_Construct_Info *construct_info);
// MR_get_functor_info:
//
// Extract the information for functor number `functor_number',
// for the type represented by type_info.
// We succeed if the type is some sort of discriminated union.
//
// You need to save and restore transient registers around
// calls to this function.
static int
MR_get_functor_info(MR_TypeInfo type_info, int functor_number,
MR_Construct_Info *construct_info)
{
MR_TypeCtorInfo type_ctor_info;
type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
construct_info->type_ctor_rep = MR_type_ctor_rep(type_ctor_info);
if (! MR_type_ctor_has_valid_rep(type_ctor_info)) {
MR_fatal_error("MR_get_functor_info: term of unknown representation");
}
switch (MR_type_ctor_rep(type_ctor_info)) {
case MR_TYPECTOR_REP_RESERVED_ADDR:
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
case MR_TYPECTOR_REP_DU:
case MR_TYPECTOR_REP_DU_USEREQ:
{
const MR_DuFunctorDesc *functor_desc;
if (functor_number < 0 ||
functor_number >= MR_type_ctor_num_functors(type_ctor_info))
{
MR_fatal_error("MR_get_functor_info: "
"du functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
MR_functors_du[functor_number];
construct_info->functor_info.du_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_du_functor_name;
construct_info->arity = functor_desc->MR_du_functor_orig_arity;
construct_info->arg_pseudo_type_infos =
functor_desc->MR_du_functor_arg_types;
construct_info->arg_names =
functor_desc->MR_du_functor_arg_names;
}
return MR_TRUE;
case MR_TYPECTOR_REP_ENUM:
case MR_TYPECTOR_REP_ENUM_USEREQ:
case MR_TYPECTOR_REP_DUMMY:
{
const MR_EnumFunctorDesc *functor_desc;
if (functor_number < 0 ||
functor_number >= MR_type_ctor_num_functors(type_ctor_info))
{
MR_fatal_error("MR_get_functor_info: "
"enum functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
MR_functors_enum[functor_number];
construct_info->functor_info.enum_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_enum_functor_name;
construct_info->arity = 0;
construct_info->arg_pseudo_type_infos = NULL;
construct_info->arg_names = NULL;
}
return MR_TRUE;
case MR_TYPECTOR_REP_FOREIGN_ENUM:
case MR_TYPECTOR_REP_FOREIGN_ENUM_USEREQ:
{
const MR_ForeignEnumFunctorDesc *functor_desc;
if (functor_number < 0 ||
functor_number >= MR_type_ctor_num_functors(type_ctor_info))
{
MR_fatal_error("MR_get_functor_info: "
"foreign enum functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
MR_functors_foreign_enum[functor_number];
construct_info->functor_info.foreign_enum_functor_desc
= functor_desc;
construct_info->functor_name =
functor_desc->MR_foreign_enum_functor_name;
construct_info->arity = 0;
construct_info->arg_pseudo_type_infos = NULL;
construct_info->arg_names = NULL;
}
return MR_TRUE;
case MR_TYPECTOR_REP_NOTAG:
case MR_TYPECTOR_REP_NOTAG_USEREQ:
case MR_TYPECTOR_REP_NOTAG_GROUND:
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
{
const MR_NotagFunctorDesc *functor_desc;
if (functor_number != 0) {
MR_fatal_error("MR_get_functor_info: "
"notag functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
MR_functors_notag;
construct_info->functor_info.notag_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_notag_functor_name;
construct_info->arity = 1;
construct_info->arg_pseudo_type_infos =
&functor_desc->MR_notag_functor_arg_type;
construct_info->arg_names =
&functor_desc->MR_notag_functor_arg_name;
}
return MR_TRUE;
case MR_TYPECTOR_REP_EQUIV_GROUND:
case MR_TYPECTOR_REP_EQUIV:
return MR_get_functor_info(
MR_create_type_info(
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
MR_type_ctor_layout(type_ctor_info).MR_layout_equiv),
functor_number, construct_info);
case MR_TYPECTOR_REP_TUPLE:
construct_info->functor_name = "{}";
construct_info->arity = MR_TYPEINFO_GET_VAR_ARITY_ARITY(type_info);
// Tuple types don't have pseudo-type_infos for the functors.
construct_info->arg_pseudo_type_infos = NULL;
construct_info->arg_names = NULL;
return MR_TRUE;
case MR_TYPECTOR_REP_INT:
case MR_TYPECTOR_REP_UINT:
case MR_TYPECTOR_REP_CHAR:
case MR_TYPECTOR_REP_FLOAT:
case MR_TYPECTOR_REP_STRING:
case MR_TYPECTOR_REP_BITMAP:
case MR_TYPECTOR_REP_FUNC:
case MR_TYPECTOR_REP_PRED:
case MR_TYPECTOR_REP_SUBGOAL:
case MR_TYPECTOR_REP_VOID:
case MR_TYPECTOR_REP_C_POINTER:
case MR_TYPECTOR_REP_STABLE_C_POINTER:
case MR_TYPECTOR_REP_TYPEINFO:
case MR_TYPECTOR_REP_TYPECTORINFO:
case MR_TYPECTOR_REP_PSEUDOTYPEDESC:
case MR_TYPECTOR_REP_TYPEDESC:
case MR_TYPECTOR_REP_TYPECTORDESC:
case MR_TYPECTOR_REP_TYPECLASSINFO:
case MR_TYPECTOR_REP_BASETYPECLASSINFO:
case MR_TYPECTOR_REP_ARRAY:
case MR_TYPECTOR_REP_SUCCIP:
case MR_TYPECTOR_REP_HP:
case MR_TYPECTOR_REP_CURFR:
case MR_TYPECTOR_REP_MAXFR:
case MR_TYPECTOR_REP_REDOFR:
case MR_TYPECTOR_REP_REDOIP:
case MR_TYPECTOR_REP_TRAIL_PTR:
case MR_TYPECTOR_REP_TICKET:
case MR_TYPECTOR_REP_FOREIGN:
case MR_TYPECTOR_REP_STABLE_FOREIGN:
case MR_TYPECTOR_REP_REFERENCE:
return MR_FALSE;
case MR_TYPECTOR_REP_UNKNOWN:
MR_fatal_error("MR_get_functor_info: unknown type_ctor_rep");
}
MR_fatal_error("MR_get_functor_info: unexpected fallthrough");
}
// MR_typecheck_arguments:
//
// Given a list of univs (`arg_list'), and a vector of type_infos
// (`arg_vector'), checks that they are all of the same type;
// if so, returns MR_TRUE, otherwise returns MR_FALSE;
// `arg_vector' may contain type variables, these will be filled in
// by the type arguments of `type_info'.
//
// Assumes the length of the list has already been checked.
//
// You need to save and restore transient registers around
// calls to this function.
MR_bool
MR_typecheck_arguments(MR_TypeInfo type_info, int arity, MR_Word arg_list,
const MR_PseudoTypeInfo *arg_pseudo_type_infos)
{
MR_TypeInfo arg_type_info;
MR_TypeInfo list_arg_type_info;
int comp;
int i;
// Type check the list of arguments.
for (i = 0; i < arity; i++) {
if (MR_list_is_empty(arg_list)) {
return MR_FALSE;
}
list_arg_type_info = (MR_TypeInfo) MR_field(MR_UNIV_TAG,
MR_list_head(arg_list), MR_UNIV_OFFSET_FOR_TYPEINFO);
if (MR_TYPE_CTOR_INFO_IS_TUPLE(
MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info)))
{
arg_type_info =
MR_TYPEINFO_GET_VAR_ARITY_ARG_VECTOR(type_info)[i + 1];
} else {
arg_type_info = MR_create_type_info(
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
arg_pseudo_type_infos[i]);
}
comp = MR_compare_type_info(list_arg_type_info, arg_type_info);
if (comp != MR_COMPARE_EQUAL) {
return MR_FALSE;
}
arg_list = MR_list_tail(arg_list);
}
// List should now be empty.
return MR_list_is_empty(arg_list);
}
// MR_get_functors_check_range:
//
// Check that functor_number is in range, and get the functor info if it is.
// Return MR_FALSE if it is out of range, or if MR_get_functor_info returns
// MR_FALSE, otherwise return MR_TRUE.
//
// You need to save and restore transient registers around
// calls to this function.
MR_bool
MR_get_functors_check_range(int functor_number, MR_TypeInfo type_info,
MR_Construct_Info *construct_info)
{
// Check range of functor_number, get functors vector.
return functor_number < MR_get_num_functors(type_info) &&
functor_number >= 0 &&
MR_get_functor_info(type_info, functor_number, construct_info);
}
// MR_get_num_functors:
//
// Get the number of functors for a type. If it isn't a discriminated union,
// return -1.
//
// You need to save and restore transient registers around
// calls to this function.
int
MR_get_num_functors(MR_TypeInfo type_info)
{
MR_TypeCtorInfo type_ctor_info;
type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
if (! MR_type_ctor_has_valid_rep(type_ctor_info)) {
MR_fatal_error("MR_get_num_functors: term of unknown representation");
}
switch (MR_type_ctor_rep(type_ctor_info)) {
case MR_TYPECTOR_REP_DU:
case MR_TYPECTOR_REP_DU_USEREQ:
case MR_TYPECTOR_REP_RESERVED_ADDR:
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
case MR_TYPECTOR_REP_ENUM:
case MR_TYPECTOR_REP_ENUM_USEREQ:
case MR_TYPECTOR_REP_DUMMY:
case MR_TYPECTOR_REP_FOREIGN_ENUM:
case MR_TYPECTOR_REP_FOREIGN_ENUM_USEREQ:
return MR_type_ctor_num_functors(type_ctor_info);
case MR_TYPECTOR_REP_NOTAG:
case MR_TYPECTOR_REP_NOTAG_USEREQ:
case MR_TYPECTOR_REP_NOTAG_GROUND:
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
case MR_TYPECTOR_REP_TUPLE:
return 1;
case MR_TYPECTOR_REP_EQUIV_GROUND:
case MR_TYPECTOR_REP_EQUIV:
return MR_get_num_functors(
MR_create_type_info((MR_TypeInfo *) type_info,
MR_type_ctor_layout(type_ctor_info).MR_layout_equiv));
case MR_TYPECTOR_REP_INT:
case MR_TYPECTOR_REP_UINT:
case MR_TYPECTOR_REP_CHAR:
case MR_TYPECTOR_REP_FLOAT:
case MR_TYPECTOR_REP_STRING:
case MR_TYPECTOR_REP_BITMAP:
case MR_TYPECTOR_REP_FUNC:
case MR_TYPECTOR_REP_PRED:
case MR_TYPECTOR_REP_SUBGOAL:
case MR_TYPECTOR_REP_VOID:
case MR_TYPECTOR_REP_C_POINTER:
case MR_TYPECTOR_REP_STABLE_C_POINTER:
case MR_TYPECTOR_REP_TYPEINFO:
case MR_TYPECTOR_REP_TYPECTORINFO:
case MR_TYPECTOR_REP_PSEUDOTYPEDESC:
case MR_TYPECTOR_REP_TYPEDESC:
case MR_TYPECTOR_REP_TYPECTORDESC:
case MR_TYPECTOR_REP_TYPECLASSINFO:
case MR_TYPECTOR_REP_BASETYPECLASSINFO:
case MR_TYPECTOR_REP_ARRAY:
case MR_TYPECTOR_REP_SUCCIP:
case MR_TYPECTOR_REP_HP:
case MR_TYPECTOR_REP_CURFR:
case MR_TYPECTOR_REP_MAXFR:
case MR_TYPECTOR_REP_REDOFR:
case MR_TYPECTOR_REP_REDOIP:
case MR_TYPECTOR_REP_TRAIL_PTR:
case MR_TYPECTOR_REP_TICKET:
case MR_TYPECTOR_REP_FOREIGN:
case MR_TYPECTOR_REP_STABLE_FOREIGN:
case MR_TYPECTOR_REP_REFERENCE:
return -1;
case MR_TYPECTOR_REP_UNKNOWN:
MR_fatal_error("MR_get_num_functors: unknown type_ctor_rep");
}
MR_fatal_error("MR_get_num_functors: unexpected fallthrough");
}