[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