[m-rev.] for review: add builtin 64-bit integer types -- part 2

Julien Fischer jfischer at opturion.com
Wed Jan 31 00:53:24 AEDT 2018


On Tue, 30 Jan 2018, Zoltan Somogyi wrote:

> Attached is my review of the changes to the compiler;
> I will look at the changes to the library tomorrow.

I have fixed a couple of errors in the library since I posted
this change, as given by the folowing diff:

diff --git a/library/int64.m b/library/int64.m
index 6c15948..f037ad9 100644
--- a/library/int64.m
+++ b/library/int64.m
@@ -55,12 +55,12 @@
      %
  :- func abs(int64) = int64.

-    % unchecked_abs(X) retursn the absolute value of X, except that if the
+    % unchecked_abs(X) returns the absolute value of X, except that if the
      % result is undefined if X = int64.min_int64.
      %
  :- func unchecked_abs(int64) = int64.

-    % nabs(X) retursn the negative absolute value of X.
+    % nabs(X) returns the negative absolute value of X.
      % Unlike abs/1 this function is defined for X = int64.min_int64.
      %
  :- func nabs(int64) = int64.
diff --git a/library/uint64.m b/library/uint64.m
index 2d3d120..eff1069 100644
--- a/library/uint64.m
+++ b/library/uint64.m
@@ -193,7 +193,7 @@
  "
      if (I < 0) {
          SUCCESS_INDICATOR = MR_FALSE;
-    } else if ((uint64_t)I > (uint64_t)UINT32_MAX) {
+    } else if ((uint64_t)I > (uint64_t)INT64_MAX) {
          SUCCESS_INDICATOR = MR_FALSE;
      } else {
          U = (uint64_t) I;

> I see that the largest part of the diff is the test cases,
> including .exp files. I don't think any human can really
> check these without dying of boredom.

The main point of all those tests is to ensure we are producing
identical results across all of the different backends.

> Each line of the output now gives the result of a Mercury
> operation on 64 bit ints/uints. How hard would it be to
> follow every line with the result of the same operation,
> but executed in C?

Executing them in C for the non-C backends would be quite difficult ;-)

> Then all we would have to do is to check that every such line pair is
> identical, a task that is trivial to automate.

Ok, I'll see about this as a separate change.

> diff --git a/compiler/c_util.m b/compiler/c_util.m
> index d67f400..4eded72 100644
> --- a/compiler/c_util.m
> +++ b/compiler/c_util.m
> @@ -331,6 +331,7 @@
>
>  :- import_module bool.
>  :- import_module int.
> +:- import_module int64.
>  :- import_module integer.
>  :- import_module require.
>  :- import_module string.
> @@ -894,30 +895,38 @@ output_uint32_expr(Stream, N, !IO) :-
>      io.write_uint32(Stream, N, !IO),
>      io.write_string(Stream, ")", !IO).
> 
> -make_int64_literal(N) = Literal :-
> -    NStr = int_to_string(N),
> -    string.format("INT64_C(%s)", [s(NStr)], Literal).
> -
>  output_uint32_expr_cur_stream(N, !IO) :-
>      io.output_stream(Stream, !IO),
>      output_uint32_expr(Stream, N, !IO).
> 
> +make_int64_literal(N) = Literal :-
> +    ( if N = min_int64 then
> +        Literal = "INT64_MIN"
> +    else
> +        NStr = int64_to_string(N),
> +        string.format("INT64_C(%s)", [s(NStr)], Literal)
> +    ).
> +
> 
> Is there any particular reason why there is make_Uint64_literal?

I don't understand your comment here.

...

> diff --git a/compiler/hlds_out_util.m b/compiler/hlds_out_util.m
> index a047df4..f0d1948 100644
> --- a/compiler/hlds_out_util.m
> +++ b/compiler/hlds_out_util.m
> @@ -2,7 +2,7 @@
>  % vim: ft=mercury ts=4 sw=4 et
>  %-----------------------------------------------------------------------------%
>  % Copyright (C) 2009-2012 The University of Melbourne.
> -% Copyright (C) 2014-2017 The Mercury team.
> +% Copyright (C) 2014-2018 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.
>  %-----------------------------------------------------------------------------%
> @@ -719,13 +719,13 @@ functor_cons_id_to_string(ModuleInfo, VarSet, VarNamePrint, ConsId, ArgVars)
>      ;
>          ConsId = int64_const(Int64),
>          Str = functor_to_string(VarSet, VarNamePrint,
> -            term.integer(base_10, integer(Int64), signed,
> +            term.integer(base_10, integer.from_int64(Int64), signed,
>                  size_64_bit),
>              ArgVars)
>      ;
>          ConsId = uint64_const(UInt64),
>          Str = functor_to_string(VarSet, VarNamePrint,
> -            term.integer(base_10, integer(UInt64), unsigned,
> +            term.integer(base_10, integer.from_uint64(UInt64), unsigned,
>                  size_64_bit),
>              ArgVars)
>      ;
> 
> Why do this via functors?

There is no good reason that I can see.  (The int_const case always did that
and the other cases just copied it.)

> Why not just convert to integer and print that, as
> cons_id_and_vars_or_arity_to_string does?

Done.

> diff --git a/compiler/llds_out_data.m b/compiler/llds_out_data.m
> index 1cb82ed..bb47efd 100644
> --- a/compiler/llds_out_data.m
> +++ b/compiler/llds_out_data.m
> @@ -2021,20 +2021,20 @@ float_op_name(float_divide, "divide").
>      % a name for that rval that is suitable for use in a C identifier.
>      % Different rvals must be given different names.
>      %
> -:- pred int64_literal_name(int::in, string::out) is det.
> +:- pred int64_literal_name(int64::in, string::out) is det.
>
>  int64_literal_name(Int64, Int64Name) :-
> -    Int64Name0 = int_to_string(Int64),
> +    Int64Name0 = int64_to_string(Int64),
>      string.replace_all(Int64Name0, "-", "neg", Int64Name).
>
>      % Given an rval which is an unsigned 64-bit integer literal, return
>      % a name for that rval that is suitable for use in a C identifier.
>      % Different rvals must be given different names.
>      %
> -:- pred uint64_literal_name(int::in, string::out) is det.
> +:- pred uint64_literal_name(uint64::in, string::out) is det.
>
>  uint64_literal_name(UInt64, UInt64Name) :-
> -    UInt64Name = int_to_string(UInt64). % XXX INT64.
> +    UInt64Name = uint64_to_string(UInt64).
> 
> To me, the results of those functions don't look to be suitable
> to use as C identifiers (since most will start with digits).

The wording of the comment is taken from that of float_literal_name.  I have
reworded it and the int64 / uint64 versions thus:

   Given an rval which is an {int64,uint64,float) literal, return a name
   for that rval that is suitable for use as a suffix of a C identifier.
   Different rvals must be given different names.

> diff --git a/compiler/parse_tree_out_info.m b/compiler/parse_tree_out_info.m
> index ff0454d..215ea5f 100644
> --- a/compiler/parse_tree_out_info.m
> +++ b/compiler/parse_tree_out_info.m
> @@ -365,6 +383,18 @@ output_uint32(U32, Str0, Str) :-
>      S = string.uint32_to_string(U32) ++ "u32",
>      string.append(Str0, S, Str).
> 
> +:- pred output_int64(int64::in, string::di, string::uo) is det.
> +
> +output_int64(I64, Str0, Str) :-
> +    S = string.int64_to_string(I64) ++ "i64",
> +    string.append(Str0, S, Str).
> +
> +:- pred output_uint64(uint64::in, string::di, string::uo) is det.
> +
> +output_uint64(U64, Str0, Str) :-
> +    S = string.uint64_to_string(U64) ++ "u64",
> +    string.append(Str0, S, Str).
> +
> 
> These look like they are not used in this module. Are they used anywhere else?

Yes, they are used in one of instances for the output/1 type class further
above in the same module.

Julien.


More information about the reviews mailing list