[m-rev.] diff: support 64-bit integers in static ground terms with the LLDS backend

Julien Fischer jfischer at opturion.com
Tue Jan 23 17:30:10 AEDT 2018


I'm committing this now, as I need it to continue work on the 
addition of 64-bit integers; I'll deal with any review comments
separately.  Support for the MLDS backends will also be a separate change.

Julien.

------------------------

Support 64-bit integers in static ground terms with the LLDS backend.

compiler/handle_options.m:
compiler/options.m:
     Add a new internal option --static-ground-int64s, whose value
     says whether 64-bit integers may be placed in static data.
     (As with floats currently, we always do this.)

compiler/llds_out_data.m:
     If 64-bit integers are boxed, then emit a static constant to hold
     the value of each 64-bit integer literal.

compiler/llds.m:
compiler/llds_out_util.m:
compiler/code_info.m:
      Keep track of whether we are using unboxed int64s and static ground int64s
      at various points in the code generator.

      Add decl_ids for the labels we generate for 64-bit integer constants.

compiler/exprn_aux.m:
      Fix an XXX: properly determine whether an expression containing 64-bit
      integers is constant or not.

compiler/c_util.m:
     Add functions for converting 64-bit integers into strings giving
     the C literal representation of those integers.

diff --git a/compiler/c_util.m b/compiler/c_util.m
index 4268f80..d67f400 100644
--- a/compiler/c_util.m
+++ b/compiler/c_util.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1999-2007, 2009-2012 The University of Melbourne.
-% Copyright (C) 2013-2017 The Mercury team.
+% Copyright (C) 2013-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.
  %---------------------------------------------------------------------------%
@@ -221,12 +221,22 @@
      io::di, io::uo) is det.
  :- pred output_uint32_expr_cur_stream(uint32::in, io::di, io::uo) is det.

+    % Convert a uint64 to a string suitable for use as a C uint64_t literal.
+    % Note that the result is not suitable for use with C# or Java.
+    %
+:- func make_int64_literal(int/*XXX INT64*/) = string.
+
      % Write out an int64 as a C expression.
      %
  :- pred output_int64_expr(io.text_output_stream::in, int::in,
      io::di, io::uo) is det.
  :- pred output_int64_expr_cur_stream(int::in, io::di, io::uo) is det.

+    % Convert a uint64 to a string suitable for use as a C uint64_t literal.
+    % Note that the result is not suitable for use with C# or Java.
+    %
+:- func make_uint64_literal(int/*XXX INT64*/) = string.
+
      % Write out a uint64 as a C expression.
      %
  :- pred output_uint64_expr(io.text_output_stream::in, int::in,
@@ -884,6 +894,10 @@ 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).
@@ -897,6 +911,10 @@ output_int64_expr_cur_stream(N, !IO) :-
      io.output_stream(Stream, !IO),
      output_int64_expr(Stream, N, !IO).

+make_uint64_literal(N) = Literal :-
+    NStr = int_to_string(N),
+    string.format("UINT64_C(%s)", [s(NStr)], Literal).
+
  output_uint64_expr(Stream, N, !IO) :-
      io.write_string(Stream, "UINT64_C(", !IO),
      io.write_int(Stream, N, !IO),
diff --git a/compiler/code_info.m b/compiler/code_info.m
index bf542f5..45e60b8 100644
--- a/compiler/code_info.m
+++ b/compiler/code_info.m
@@ -512,6 +512,14 @@ init_exprn_opts(Globals) = ExprnOpts :-
          FloatDwords = no,
          DetStackFloatWidth = single_width
      ),
+    globals.lookup_bool_option(Globals, unboxed_int64s, OptUBI64s),
+    (
+        OptUBI64s = yes,
+        UBI64s = have_unboxed_int64s
+    ;
+        OptUBI64s = no,
+        UBI64s = do_not_have_unboxed_int64s
+    ),
      globals.lookup_bool_option(Globals, static_ground_floats, OptSGFloat),
      (
          OptSGFloat = yes,
@@ -520,6 +528,14 @@ init_exprn_opts(Globals) = ExprnOpts :-
          OptSGFloat = no,
          SGFloat = do_not_have_static_ground_floats
      ),
+    globals.lookup_bool_option(Globals, static_ground_int64s, OptSGInt64s),
+    (
+        OptSGInt64s = yes,
+        SGInt64s = have_static_ground_int64s
+    ;
+        OptSGInt64s = no,
+        SGInt64s = do_not_have_static_ground_int64s
+    ),
      globals.lookup_bool_option(Globals, static_code_addresses,
          OptStaticCodeAddr),
      (
@@ -529,16 +545,8 @@ init_exprn_opts(Globals) = ExprnOpts :-
          OptStaticCodeAddr = no,
          StaticCodeAddrs = do_not_have_static_code_addresses
      ),
-    globals.lookup_bool_option(Globals, unboxed_int64s, OptUBI64s),
-    (
-        OptUBI64s = yes,
-        UBI64s = have_unboxed_int64s
-    ;
-        OptUBI64s = no,
-        UBI64s = do_not_have_unboxed_int64s
-    ),
      ExprnOpts = exprn_opts(NLG, ASM, UBF, UseFloatRegs, DetStackFloatWidth,
-        SGCell, SGFloat, StaticCodeAddrs, UBI64s).
+        UBI64s, SGCell, SGFloat, SGInt64s, StaticCodeAddrs).

  :- pred max_var_slot(stack_slots::in, int::out) is det.

diff --git a/compiler/exprn_aux.m b/compiler/exprn_aux.m
index 39b7a36..1e810b9 100644
--- a/compiler/exprn_aux.m
+++ b/compiler/exprn_aux.m
@@ -127,8 +127,14 @@ const_is_constant(Const, ExprnOpts, IsConst) :-
          ( Const = llconst_int64(_)
          ; Const = llconst_uint64(_)
          ),
-        % XXX INT64.
-        IsConst = yes
+        SGInt64s = ExprnOpts ^ static_ground_int64s,
+        (
+            SGInt64s = have_static_ground_int64s,
+            IsConst = yes
+        ;
+            SGInt64s = do_not_have_static_ground_int64s,
+            IsConst = no
+        )
      ;
          Const = llconst_float(_),
          SGFloats = ExprnOpts ^ static_ground_floats,
diff --git a/compiler/handle_options.m b/compiler/handle_options.m
index 96aa2a3..83764d0 100644
--- a/compiler/handle_options.m
+++ b/compiler/handle_options.m
@@ -2355,6 +2355,18 @@ postprocess_options_lowlevel(!Globals) :-
      globals.set_option(static_ground_floats, bool(StaticGroundFloats),
          !Globals),

+    % Ditto for 64-bit integers.
+    globals.lookup_bool_option(!.Globals, unboxed_int64s, UnboxedInt64s),
+    (
+        UnboxedInt64s = yes,
+        StaticGroundInt64s = yes
+    ;
+        UnboxedInt64s = no,
+        StaticGroundInt64s=  yes
+    ),
+    globals.set_option(static_ground_int64s, bool(StaticGroundInt64s),
+        !Globals),
+
      % The setting of static_code_addresses is governed only by the settings
      % of gcc_non_local_gotos and asm_labels.
      globals.lookup_bool_option(!.Globals, gcc_non_local_gotos, NonLocalGotos),
diff --git a/compiler/llds.m b/compiler/llds.m
index 43070fa..add674b 100644
--- a/compiler/llds.m
+++ b/compiler/llds.m
@@ -1487,6 +1487,10 @@
      --->    use_float_registers
      ;       do_not_use_float_registers.

+:- type have_unboxed_int64s
+    --->    have_unboxed_int64s
+    ;       do_not_have_unboxed_int64s.
+
  :- type have_static_ground_cells
      --->    have_static_ground_cells
      ;       do_not_have_static_ground_cells.
@@ -1495,13 +1499,14 @@
      --->    have_static_ground_floats
      ;       do_not_have_static_ground_floats.

+:- type have_static_ground_int64s
+    --->    have_static_ground_int64s
+    ;       do_not_have_static_ground_int64s.
+
  :- type have_static_code_addresses
      --->    have_static_code_addresses
      ;       do_not_have_static_code_addresses.

-:- type have_unboxed_int64s
-    --->    have_unboxed_int64s
-    ;       do_not_have_unboxed_int64s.

  :- type exprn_opts
      --->    exprn_opts(
@@ -1510,10 +1515,11 @@
                  unboxed_floats          :: have_unboxed_floats,
                  float_registers         :: use_float_registers,
                  det_stack_float_width   :: stack_slot_width,
+                unboxed_int64s          :: have_unboxed_int64s,
                  static_ground_cells     :: have_static_ground_cells,
                  static_ground_floats    :: have_static_ground_floats,
-                static_code_addresses   :: have_static_code_addresses,
-                unboxed_int64s          :: have_unboxed_int64s
+                static_ground_int64s    :: have_static_ground_int64s,
+                static_code_addresses   :: have_static_code_addresses
              ).

  :- func get_nonlocal_gotos(exprn_opts) = have_non_local_gotos.
@@ -1521,10 +1527,11 @@
  :- func get_unboxed_floats(exprn_opts) = have_unboxed_floats.
  :- func get_float_registers(exprn_opts) = use_float_registers.
  :- func get_det_stack_float_width(exprn_opts) = stack_slot_width.
+:- func get_unboxed_int64s(exprn_opts) = have_unboxed_int64s.
  :- func get_static_ground_cells(exprn_opts) = have_static_ground_cells.
  :- func get_static_ground_floats(exprn_opts) = have_static_ground_floats.
+:- func get_static_ground_int64s(exprn_opts) = have_static_ground_int64s.
  :- func get_static_code_addresses(exprn_opts) = have_static_code_addresses.
-:- func get_unboxed_int64s(exprn_opts) = have_unboxed_int64s.

  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%
@@ -1800,6 +1807,7 @@ get_unboxed_floats(ExprnOpts) = ExprnOpts ^ unboxed_floats.
  get_float_registers(ExprnOpts) = ExprnOpts ^ float_registers.
  get_det_stack_float_width(ExprnOpts) = ExprnOpts ^ det_stack_float_width.
  get_static_ground_floats(ExprnOpts) = ExprnOpts ^ static_ground_floats.
+get_static_ground_int64s(ExprnOpts) = ExprnOpts ^ static_ground_int64s.
  get_static_code_addresses(ExprnOpts) = ExprnOpts ^ static_code_addresses.
  get_unboxed_int64s(ExprnOpts) = ExprnOpts ^ unboxed_int64s.

diff --git a/compiler/llds_out_data.m b/compiler/llds_out_data.m
index e90f8f5..606e4a6 100644
--- a/compiler/llds_out_data.m
+++ b/compiler/llds_out_data.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %----------------------------------------------------------------------------%
  % Copyright (C) 2009-2012 The University of Melbourne.
-% Copyright (C) 2013-2017 The Mercury team.
+% Copyright (C) 2013-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.
  %----------------------------------------------------------------------------%
@@ -119,6 +119,10 @@
      %
  :- pred float_const_expr_name(rval::in, string::out) is semidet.

+:- pred int64_const_expr_name(rval::in, string::out) is semidet.
+
+:- pred uint64_const_expr_name(rval::in, string::out) is semidet.
+
      % output_record_data_addr_decls(Info, DataId, ...) outputs the
      % declarations of any static constants, etc. that need to be declared
      % before output_data_id(Info DataId, ...) is called.
@@ -745,11 +749,55 @@ output_record_rval_decls_format(Info, Rval, FirstIndent, LaterIndent,
                  true
              )
          ;
-            Const = llconst_int64(_)
-            % XXX INT64
+            Const = llconst_int64(Int64Val),
+            UnboxedInt64s = Info ^ lout_unboxed_int64s,
+            StaticGroundInt64s = Info ^ lout_static_ground_int64s,
+            ( if
+                UnboxedInt64s = no,
+                StaticGroundInt64s = yes
+            then
+                int64_literal_name(Int64Val, Int64Name),
+                Int64Label = decl_int64_label(Int64Name),
+                ( if decl_set_is_member(Int64Label, !.DeclSet) then
+                    true
+                else
+                    decl_set_insert(Int64Label, !DeclSet),
+                    Int64String = c_util.make_int64_literal(Int64Val),
+                    output_indent(FirstIndent, LaterIndent, !.N, !IO),
+                    !:N = !.N + 1,
+                    io.write_strings(["static const int64_t ",
+                        "mercury_int64_const_", Int64Name, " = ",
+                        Int64String, ";\n"
+                    ], !IO)
+                )
+            else
+                true
+            )
          ;
-            Const = llconst_uint64(_)
-            % XXX INT64
+            Const = llconst_uint64(UInt64Val),
+            UnboxedInt64s = Info ^ lout_unboxed_int64s,
+            StaticGroundInt64s = Info ^ lout_static_ground_int64s,
+            ( if
+                UnboxedInt64s = no,
+                StaticGroundInt64s = Info ^ lout_static_ground_int64s
+            then
+                uint64_literal_name(UInt64Val, UInt64Name),
+                UInt64Label = decl_uint64_label(UInt64Name),
+                ( if decl_set_is_member(UInt64Label, !.DeclSet) then
+                    true
+                else
+                    decl_set_insert(UInt64Label, !DeclSet),
+                    UInt64String = c_util.make_uint64_literal(UInt64Val),
+                    output_indent(FirstIndent, LaterIndent, !.N, !IO),
+                    !:N = !.N + 1,
+                    io.write_strings(["static const uint64_t ",
+                        "mercury_uint64_const_", UInt64Name, " = ",
+                        UInt64String, ";\n"
+                    ], !IO)
+                )
+            else
+                true
+            )
          ;
              ( Const = llconst_true
              ; Const = llconst_false
@@ -1596,15 +1644,37 @@ output_int64_rval_as_word(Info, Rval, !IO) :-
      io::di, io::uo) is det.

  output_int64_rval(Info, Rval, IsPtr, !IO) :-
-    (
-        IsPtr = yes,
-        output_llds_type_cast(lt_data_ptr, !IO)
-    ;
-        IsPtr = no
-    ),
-    io.write_string("MR_int64_to_word(", !IO),
-    output_rval(Info, Rval, !IO),
-    io.write_string(")", !IO).
+    % For int64 constants, if we're using boxed 64-bit integers and
+    % --static-ground-int64s is enabled, we just refer to the static const
+    % which we declared earlier.
+    UnboxInt64s = Info ^ lout_unboxed_int64s,
+    StaticGroundInt64s = Info ^ lout_static_ground_int64s,
+    ( if
+        UnboxInt64s = no,
+        StaticGroundInt64s = yes,
+        int64_const_expr_name(Rval, Int64Name)
+    then
+        (
+            IsPtr = yes,
+            Cast = lt_data_ptr
+        ;
+            IsPtr = no,
+            Cast = lt_word
+        ),
+        output_llds_type_cast(Cast, !IO),
+        io.write_string("&mercury_int64_const_", !IO),
+        io.write_string(Int64Name, !IO)
+    else
+        (
+            IsPtr = yes,
+            output_llds_type_cast(lt_data_ptr, !IO)
+        ;
+            IsPtr = no
+        ),
+        io.write_string("MR_int64_to_word(", !IO),
+        output_rval(Info, Rval, !IO),
+        io.write_string(")", !IO)
+    ).

      % Output a uint64 rval, converted to type `MR_Word *'
      %
@@ -1628,15 +1698,37 @@ output_uint64_rval_as_word(Info, Rval, !IO) :-
      io::di, io::uo) is det.

  output_uint64_rval(Info, Rval, IsPtr, !IO) :-
-    (
-        IsPtr = yes,
-        output_llds_type_cast(lt_data_ptr, !IO)
-    ;
-        IsPtr = no
-    ),
-    io.write_string("MR_uint64_to_word(", !IO),
-    output_rval(Info, Rval, !IO),
-    io.write_string(")", !IO).
+    % For uint64 constants, if we're using boxed 64-bit integers and
+    % --static-ground-int64s is enabled, we just refer to the static const
+    % which we declared earlier.
+    UnboxInt64s = Info ^ lout_unboxed_int64s,
+    StaticGroundInt64s = Info ^ lout_static_ground_int64s,
+    ( if
+        UnboxInt64s = no,
+        StaticGroundInt64s = yes,
+        uint64_const_expr_name(Rval, UInt64Name)
+    then
+        (
+            IsPtr = yes,
+            Cast = lt_data_ptr
+        ;
+            IsPtr = no,
+            Cast = lt_word
+        ),
+        output_llds_type_cast(Cast, !IO),
+        io.write_string("&mercury_uint64_const_", !IO),
+        io.write_string(UInt64Name, !IO)
+    else
+        (
+            IsPtr = yes,
+            output_llds_type_cast(lt_data_ptr, !IO)
+        ;
+            IsPtr = no
+        ),
+        io.write_string("MR_uint64_to_word(", !IO),
+        output_rval(Info, Rval, !IO),
+        io.write_string(")", !IO)
+    ).

  :- pred is_aligned_dword_ptr(rval::in, rval::in, mem_ref::out) is semidet.

@@ -1924,6 +2016,35 @@ float_op_name(float_times, "times").
  float_op_name(float_divide, "divide").

  %----------------------------------------------------------------------------%
+
+    % Given an rval which is a signed 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 int64_literal_name(int::in, string::out) is det.
+
+int64_literal_name(Int64, Int64Name) :-
+    Int64Name0 = int_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.
+
+uint64_literal_name(UInt64, UInt64Name) :-
+    UInt64Name = int_to_string(UInt64). % XXX INT64.
+
+int64_const_expr_name(Expr, Name) :-
+    Expr = const(llconst_int64(Int64)),
+    int64_literal_name(Int64, Name).
+
+uint64_const_expr_name(Expr, Name) :-
+    Expr = const(llconst_uint64(UInt64)),
+    uint64_literal_name(UInt64, Name).
+
+%----------------------------------------------------------------------------%
  %
  % Declare the names of global variables.
  %
diff --git a/compiler/llds_out_util.m b/compiler/llds_out_util.m
index 0d24b7d..5c4af19 100644
--- a/compiler/llds_out_util.m
+++ b/compiler/llds_out_util.m
@@ -60,6 +60,8 @@
                  lout_unboxed_float              :: bool,
                  lout_det_stack_dword_alignment  :: bool,
                  lout_static_ground_floats       :: bool,
+                lout_unboxed_int64s             :: bool,
+                lout_static_ground_int64s       :: bool,
                  lout_use_macro_for_redo_fail    :: bool,
                  lout_trace_level                :: trace_level,
                  lout_globals                    :: globals
@@ -79,6 +81,8 @@

  :- type decl_id
      --->    decl_float_label(string)
+    ;       decl_int64_label(string)
+    ;       decl_uint64_label(string)
      ;       decl_common_type(type_num)
      ;       decl_code_addr(code_addr)
      ;       decl_rtti_id(rtti_id)
@@ -140,6 +144,9 @@ init_llds_out_info(ModuleName, SourceFileName, Globals,
      double_width_floats_on_det_stack(Globals, DetStackDwordAligment),
      globals.lookup_bool_option(Globals, static_ground_floats,
          StaticGroundFloats),
+    globals.lookup_bool_option(Globals, unboxed_int64s, UnboxedInt64s),
+    globals.lookup_bool_option(Globals, static_ground_int64s,
+        StaticGroundInt64s),
      globals.lookup_bool_option(Globals, use_macro_for_redo_fail,
          UseMacroForRedoFail),
      globals.get_trace_level(Globals, TraceLevel),
@@ -150,7 +157,8 @@ init_llds_out_info(ModuleName, SourceFileName, Globals,
          EmitCLoops, GenerateBytecode, LocalThreadEngineBase,
          ProfileCalls, ProfileTime, ProfileMemory, ProfileDeep,
          UnboxedFloat, DetStackDwordAligment, StaticGroundFloats,
-        UseMacroForRedoFail, TraceLevel, Globals).
+        UnboxedInt64s, StaticGroundInt64s, UseMacroForRedoFail,
+        TraceLevel, Globals).

  output_set_line_num(OutputLineNumbers, Context, !IO) :-
      (
diff --git a/compiler/options.m b/compiler/options.m
index 3146f00..50969d9 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1994-2012 The University of Melbourne.
-% Copyright (C) 2017 The Mercury Team.
+% Copyright (C) 2013-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.
  %---------------------------------------------------------------------------%
@@ -818,6 +818,7 @@

      ;       static_ground_cells
      ;       static_ground_floats
+    ;       static_ground_int64s
      ;       static_code_addresses

      ;       use_atomic_cells
@@ -1715,6 +1716,7 @@ option_defaults_2(optimization_option, [
      switch_multi_rec_base_first         -   bool(yes),
      static_ground_cells                 -   bool(no),
      static_ground_floats                -   bool(no),
+    static_ground_int64s                -   bool(no),
      static_code_addresses               -   bool(no),
      use_atomic_cells                    -   bool(no),
      middle_rec                          -   bool(no),
@@ -2698,6 +2700,8 @@ long_option("switch-multi-rec-base-first",  switch_multi_rec_base_first).
  long_option("static-ground-terms",  static_ground_cells).
  % static_ground_floats should be set only in handle_options.m.
  % long_option("static-ground-floats", static_ground_floats).
+% static_ground_int64s should be set only in handle_options.m.
+% long_option("static-ground-int64s", static_ground_int64s).
  % static_code_addresses should be set only in handle_options.m.
  % long_option("static-code-addresses", static_code_addresses).
  long_option("use-atomic-cells",     use_atomic_cells).


More information about the reviews mailing list