Move uint_emu.m's contents into int_emu.m ...

... as a preliminary for extending the emulation to sized ints and uints.

compiler/int_emu.m:
    Move all the emulation operations from uint_emu.m to int_emu.m,
    moving each uint operation next to its int equivalent. To make this
    possible without naming conflicts, add a distinguishing prefix
    to the name of each emulation predicate. (The emulations of each op
    for signed and unsigned ints are related though somewhat different,
    and both the similarities and differences are easily visible and checkable
    when their code is next to each other.)

    On the other hand, the emulation code for an operation for e.g.
    int/int8/int16/int32/int64 can be *identical* when the number of bits
    is a parameter of that code, and the next diff will exploit this fact.

    Unify the target_bits_per_int predicate from int_emu.m and the
    target_bits_per_uint predicate from uint_emu.m, which had exactly
    the same logic, and call it target_word_bits.

compiler/uint_emu.m:
    Delete this module.

compiler/libs.m:
    Delete both int_emu.m and uint_emu as a submodule of this package.

compiler/parse_tree.m:
    Move int_emu.m to become a submodule of this package, to allow the next
    change to it to use the some_int_const type in prog_data.m.

compiler/notes/compiler_design.html:
    Generalize the description of int_emu.m. Note that the description
    of uint_emu.m cannot be deleted, because it didn't exist :-(

compiler/const_prop.m:
compiler/simplify_goal_call.m:
    Conform to the changes above.
This commit is contained in:
Zoltan Somogyi
2023-04-18 12:59:55 +10:00
parent 713d541ada
commit 67bb8fce33
7 changed files with 258 additions and 313 deletions

View File

@@ -51,9 +51,8 @@
:- implementation.
:- import_module hlds.make_goal.
:- import_module libs.int_emu.
:- import_module libs.options.
:- import_module libs.uint_emu.
:- import_module parse_tree.int_emu.
:- import_module bool.
:- import_module float.
@@ -238,13 +237,13 @@ evaluate_det_call_int_1(Globals, ProcName, ModeNum, X, OutputArg, ConsId) :-
ModeNum = 0,
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
target_bits_per_int(Globals, bits_per_int(BitsPerInt)),
target_word_bits(Globals, word_bits(BitsPerWord)),
(
ProcName = "bits_per_int",
ConsId = some_int_const(int_const(BitsPerInt))
ConsId = some_int_const(int_const(BitsPerWord))
;
ProcName = "ubits_per_int",
ConsId = some_int_const(uint_const(uint.det_from_int(BitsPerInt)))
ConsId = some_int_const(uint_const(uint.det_from_int(BitsPerWord)))
)
).
@@ -259,13 +258,13 @@ evaluate_det_call_uint_1(Globals, ProcName, ModeNum, X, OutputArg, ConsId) :-
ModeNum = 0,
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
target_bits_per_uint(Globals, bits_per_uint(BitsPerUInt)),
target_word_bits(Globals, word_bits(WordBits)),
(
ProcName = "bits_per_uint",
ConsId = some_int_const(int_const(BitsPerUInt))
ConsId = some_int_const(int_const(WordBits))
;
ProcName = "ubits_per_uint",
ConsId = some_int_const(uint_const(uint.det_from_int(BitsPerUInt)))
ConsId = some_int_const(uint_const(uint.det_from_int(WordBits)))
)
).
@@ -287,35 +286,35 @@ evaluate_det_call_int_2(Globals, ProcName, ModeNum, X, Y,
;
ProcName = "-",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.minus(BitsPerInt, 0, XVal, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_minus(BitsPerWord, 0, XVal, OutputArgVal)
;
ProcName = "\\",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
target_bits_per_int(Globals, TargetBitsPerInt),
TargetBitsPerInt = bits_per_int(int.bits_per_int),
target_word_bits(Globals, TargetBitsPerWord),
TargetBitsPerWord = word_bits(int.bits_per_int),
OutputArgVal = \ XVal
;
ProcName = "floor_to_multiple_of_bits_per_int",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.floor_to_multiple_of_bits_per_int(XVal, BitsPerInt,
target_word_bits(Globals, BitsPerWord),
int_floor_to_multiple_of_bits_per_int(XVal, BitsPerWord,
OutputArgVal)
;
ProcName = "quot_bits_per_int",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.quot_bits_per_int(XVal, BitsPerInt, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_quot_bits_per_int(XVal, BitsPerWord, OutputArgVal)
;
ProcName = "times_bits_per_int",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.times_bits_per_int(XVal, BitsPerInt, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_times_bits_per_int(XVal, BitsPerWord, OutputArgVal)
;
ProcName = "rem_bits_per_int",
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.rem_bits_per_int(XVal, BitsPerInt, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_rem_bits_per_int(XVal, BitsPerWord, OutputArgVal)
).
:- pred evaluate_det_call_uint_2(globals::in, string::in, int::in,
@@ -330,8 +329,9 @@ evaluate_det_call_uint_2(Globals, ProcName, ModeNum, X, Y,
X ^ arg_inst = bound(_, _, [bound_functor(FunctorX, [])]),
FunctorX = some_int_const(uint_const(XVal)),
globals.lookup_bool_option(Globals, pregenerated_dist, no),
target_bits_per_uint(Globals, TargetBitsPerUInt),
TargetBitsPerUInt = bits_per_uint(uint.bits_per_uint),
target_word_bits(Globals, TargetWordBits),
% ZZZ
TargetWordBits = word_bits(uint.bits_per_uint),
OutputArg = Y,
OutputArgVal = \ XVal
).
@@ -409,35 +409,35 @@ evaluate_det_call_int_3_mode_0(Globals, ProcName, X, Y, Z,
; ProcName = ">>" ; ProcName = "unchecked_right_shift"
),
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
target_word_bits(Globals, BitsPerWord),
require_complete_switch [ProcName]
(
( ProcName = "+" ; ProcName = "plus" ),
int_emu.plus(BitsPerInt, XVal, YVal, OutputArgVal)
int_plus(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = "-" ; ProcName = "minus" ),
int_emu.minus(BitsPerInt, XVal, YVal, OutputArgVal)
int_minus(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = "*" ; ProcName = "times" ),
int_emu.times(BitsPerInt, XVal, YVal, OutputArgVal)
int_times(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = "//"
; ProcName = "/"
; ProcName = "unchecked_quotient"
),
int_emu.quotient(BitsPerInt, XVal, YVal, OutputArgVal)
int_quotient(BitsPerWord, XVal, YVal, OutputArgVal)
;
ProcName = "mod",
int_emu.mod(BitsPerInt, XVal, YVal, OutputArgVal)
int_mod(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = "rem" ; ProcName = "unchecked_rem" ),
int_emu.rem(BitsPerInt, XVal, YVal, OutputArgVal)
int_rem(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = "<<" ; ProcName = "unchecked_left_shift" ),
int_emu.left_shift(BitsPerInt, XVal, YVal, OutputArgVal)
int_left_shift(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = ">>" ; ProcName = "unchecked_right_shift" ),
int_emu.right_shift(BitsPerInt, XVal, YVal, OutputArgVal)
int_right_shift(BitsPerWord, XVal, YVal, OutputArgVal)
)
;
ProcName = "/\\",
@@ -452,13 +452,13 @@ evaluate_det_call_int_3_mode_0(Globals, ProcName, X, Y, Z,
;
FunctorY = some_int_const(uint_const(YVal)),
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
target_word_bits(Globals, BitsPerWord),
(
( ProcName = "<<u" ; ProcName = "unchecked_left_ushift" ),
int_emu.left_ushift(BitsPerInt, XVal, YVal, OutputArgVal)
int_left_ushift(BitsPerWord, XVal, YVal, OutputArgVal)
;
( ProcName = ">>u" ; ProcName = "unchecked_right_ushift" ),
int_emu.right_ushift(BitsPerInt, XVal, YVal, OutputArgVal)
int_right_ushift(BitsPerWord, XVal, YVal, OutputArgVal)
)
),
OutputArg = Z.
@@ -477,8 +477,8 @@ evaluate_det_call_int_3_mode_1(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(int_const(ZVal)),
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.minus(BitsPerInt, ZVal, YVal, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_minus(BitsPerWord, ZVal, YVal, OutputArgVal)
;
ProcName = "-",
Y ^ arg_inst = bound(_, _, [bound_functor(FunctorY, [])]),
@@ -487,8 +487,8 @@ evaluate_det_call_int_3_mode_1(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(int_const(ZVal)),
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.plus(BitsPerInt, YVal, ZVal, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_plus(BitsPerWord, YVal, ZVal, OutputArgVal)
;
ProcName = "xor",
X ^ arg_inst = bound(_, _, [bound_functor(FunctorX, [])]),
@@ -514,8 +514,8 @@ evaluate_det_call_int_3_mode_2(Globals, ProcName, X, Y, Z,
OutputArg = Y,
OutputArg = Y,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.minus(BitsPerInt, ZVal, XVal, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_minus(BitsPerWord, ZVal, XVal, OutputArgVal)
;
ProcName = "-",
X ^ arg_inst = bound(_, _, [bound_functor(FunctorX, [])]),
@@ -525,8 +525,8 @@ evaluate_det_call_int_3_mode_2(Globals, ProcName, X, Y, Z,
OutputArg = Y,
OutputArg = Y,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
int_emu.target_bits_per_int(Globals, BitsPerInt),
int_emu.minus(BitsPerInt, XVal, ZVal, OutputArgVal)
target_word_bits(Globals, BitsPerWord),
int_minus(BitsPerWord, XVal, ZVal, OutputArgVal)
;
ProcName = "xor",
Y ^ arg_inst = bound(_, _, [bound_functor(FunctorY, [])]),
@@ -568,35 +568,35 @@ evaluate_det_call_uint_3_mode_0(Globals, ProcName, X, Y, Z,
; ProcName = ">>u" ; ProcName = "unchecked_right_ushift"
),
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
target_word_bits(Globals, WordBits),
require_complete_switch [ProcName]
(
( ProcName = "+" ; ProcName = "plus" ),
uint_emu.plus(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_plus(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = "-" ; ProcName = "minus" ),
uint_emu.minus(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_minus(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = "*" ; ProcName = "times" ),
uint_emu.times(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_times(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = "//"
; ProcName = "/"
; ProcName = "unchecked_quotient"
),
uint_emu.quotient(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_quotient(WordBits, XVal, YVal, OutputArgVal)
;
ProcName = "mod",
uint_emu.mod(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_mod(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = "rem" ; ProcName = "unchecked_rem" ),
uint_emu.rem(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_rem(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = "<<u" ; ProcName = "unchecked_left_ushift" ),
uint_emu.left_ushift(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_left_ushift(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = ">>u" ; ProcName = "unchecked_right_ushift" ),
uint_emu.right_ushift(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_right_ushift(WordBits, XVal, YVal, OutputArgVal)
)
;
ProcName = "/\\",
@@ -611,13 +611,13 @@ evaluate_det_call_uint_3_mode_0(Globals, ProcName, X, Y, Z,
;
ConstY = int_const(YVal),
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
target_word_bits(Globals, WordBits),
(
( ProcName = "<<" ; ProcName = "unchecked_left_shift" ),
uint_emu.left_shift(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_left_shift(WordBits, XVal, YVal, OutputArgVal)
;
( ProcName = ">>" ; ProcName = "unchecked_right_shift" ),
uint_emu.right_shift(BitsPerUInt, XVal, YVal, OutputArgVal)
uint_right_shift(WordBits, XVal, YVal, OutputArgVal)
)
),
OutputArg = Z.
@@ -636,8 +636,8 @@ evaluate_det_call_uint_3_mode_1(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(uint_const(ZVal)),
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
uint_emu.minus(BitsPerUInt, ZVal, YVal, OutputArgVal)
target_word_bits(Globals, WordBits),
uint_minus(WordBits, ZVal, YVal, OutputArgVal)
;
ProcName = "-",
Y ^ arg_inst = bound(_, _, [bound_functor(FunctorY, [])]),
@@ -646,8 +646,8 @@ evaluate_det_call_uint_3_mode_1(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(uint_const(ZVal)),
OutputArg = X,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
uint_emu.plus(BitsPerUInt, YVal, ZVal, OutputArgVal)
target_word_bits(Globals, WordBits),
uint_plus(WordBits, YVal, ZVal, OutputArgVal)
;
ProcName = "xor",
X ^ arg_inst = bound(_, _, [bound_functor(FunctorX, [])]),
@@ -672,8 +672,8 @@ evaluate_det_call_uint_3_mode_2(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(uint_const(ZVal)),
OutputArg = Y,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
uint_emu.minus(BitsPerUInt, ZVal, XVal, OutputArgVal)
target_word_bits(Globals, WordBits),
uint_minus(WordBits, ZVal, XVal, OutputArgVal)
;
ProcName = "-",
X ^ arg_inst = bound(_, _, [bound_functor(FunctorX, [])]),
@@ -682,8 +682,8 @@ evaluate_det_call_uint_3_mode_2(Globals, ProcName, X, Y, Z,
FunctorZ = some_int_const(uint_const(ZVal)),
OutputArg = Y,
globals.lookup_bool_option(Globals, pregenerated_dist, no),
uint_emu.target_bits_per_uint(Globals, BitsPerUInt),
uint_emu.minus(BitsPerUInt, XVal, ZVal, OutputArgVal)
target_word_bits(Globals, WordBits),
uint_minus(WordBits, XVal, ZVal, OutputArgVal)
;
ProcName = "xor",
Y ^ arg_inst = bound(_, _, [bound_functor(FunctorY, [])]),

View File

@@ -1,10 +1,10 @@
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% Copyright (C) 2015 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.
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
% File: int_emu.m.
% Main author: wangp.
@@ -13,137 +13,227 @@
% succeed only if the result is defined for the given arguments, and the result
% can be represented by the `int' type of the host compiler.
%
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module libs.int_emu.
:- module parse_tree.int_emu.
:- interface.
:- import_module libs.
:- import_module libs.globals.
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- type bits_per_int
---> bits_per_int(int).
:- type word_bits
---> word_bits(int).
% Return the number of bits per int for the selected compilation target.
%
:- pred target_bits_per_int(globals::in, bits_per_int::out) is det.
:- pred target_word_bits(globals::in, word_bits::out) is det.
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- pred plus(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred int_plus(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_plus(word_bits::in, uint::in, uint::in, uint::out) is semidet.
:- pred minus(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred times(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred quotient(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred mod(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred rem(bits_per_int::in, int::in, int::in, int::out) is semidet.
%----------------------------------------------------------------------------%
:- pred left_shift(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred left_ushift(bits_per_int::in, int::in, uint::in, int::out) is semidet.
:- pred right_shift(bits_per_int::in, int::in, int::in, int::out) is semidet.
:- pred right_ushift(bits_per_int::in, int::in, uint::in, int::out) is semidet.
%----------------------------------------------------------------------------%
:- pred floor_to_multiple_of_bits_per_int(int::in, bits_per_int::in, int::out)
:- pred int_minus(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_minus(word_bits::in, uint::in, uint::in, uint::out)
is semidet.
:- pred quot_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
:- pred int_times(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_times(word_bits::in, uint::in, uint::in, uint::out)
is semidet.
:- pred times_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
:- pred int_quotient(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_quotient(word_bits::in, uint::in, uint::in, uint::out)
is semidet.
:- pred rem_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
:- pred int_mod(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_mod(word_bits::in, uint::in, uint::in, uint::out) is semidet.
%----------------------------------------------------------------------------%
%----------------------------------------------------------------------------%
:- pred int_rem(word_bits::in, int::in, int::in, int::out) is semidet.
:- pred uint_rem(word_bits::in, uint::in, uint::in, uint::out) is semidet.
%---------------------------------------------------------------------------%
:- pred int_left_shift(word_bits::in, int::in, int::in, int::out)
is semidet.
:- pred int_left_ushift(word_bits::in, int::in, uint::in, int::out)
is semidet.
:- pred uint_left_shift(word_bits::in, uint::in, int::in, uint::out)
is semidet.
:- pred uint_left_ushift(word_bits::in, uint::in, uint::in, uint::out)
is semidet.
:- pred int_right_shift(word_bits::in, int::in, int::in, int::out)
is semidet.
:- pred int_right_ushift(word_bits::in, int::in, uint::in, int::out)
is semidet.
:- pred uint_right_shift(word_bits::in, uint::in, int::in, uint::out)
is semidet.
:- pred uint_right_ushift(word_bits::in, uint::in, uint::in, uint::out)
is semidet.
%---------------------------------------------------------------------------%
:- pred int_floor_to_multiple_of_bits_per_int(int::in, word_bits::in,
int::out) is semidet.
:- pred int_quot_bits_per_int(int::in, word_bits::in, int::out) is semidet.
:- pred int_times_bits_per_int(int::in, word_bits::in, int::out)
is semidet.
:- pred int_rem_bits_per_int(int::in, word_bits::in, int::out) is semidet.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.options.
:- import_module int.
:- import_module integer.
:- import_module uint.
:- import_module libs.options.
%---------------------------------------------------------------------------%
%----------------------------------------------------------------------------%
target_bits_per_int(Globals, bits_per_int(BitsPerInt)) :-
target_word_bits(Globals, word_bits(WordBits)) :-
globals.get_target(Globals, Target),
(
Target = target_c,
globals.lookup_int_option(Globals, bits_per_word, BitsPerInt)
globals.lookup_int_option(Globals, bits_per_word, WordBits)
;
( Target = target_csharp
; Target = target_java
),
BitsPerInt = 32
WordBits = 32
).
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
plus(BitsPerInt, X, Y, Z) :-
to_int_in_range(BitsPerInt, integer(X) + integer(Y), Z).
int_plus(WordBits, X, Y, Z) :-
to_int_in_range(WordBits, integer(X) + integer(Y), Z).
minus(BitsPerInt, X, Y, Z) :-
to_int_in_range(BitsPerInt, integer(X) - integer(Y), Z).
uint_plus(WordBits, X, Y, Z) :-
to_uint_in_range(WordBits,
integer.from_uint(X) + integer.from_uint(Y), Z).
times(BitsPerInt, X, Y, Z) :-
to_int_in_range(BitsPerInt, integer(X) * integer(Y), Z).
%---------------------%
quotient(BitsPerInt, X, Y, Z) :-
int_minus(WordBits, X, Y, Z) :-
to_int_in_range(WordBits, integer(X) - integer(Y), Z).
uint_minus(WordBits, X, Y, Z) :-
to_uint_in_range(WordBits,
integer.from_uint(X) - integer.from_uint(Y), Z).
%---------------------%
int_times(WordBits, X, Y, Z) :-
to_int_in_range(WordBits, integer(X) * integer(Y), Z).
uint_times(WordBits, X, Y, Z) :-
to_uint_in_range(WordBits,
integer.from_uint(X) * integer.from_uint(Y), Z).
%---------------------%
int_quotient(WordBits, X, Y, Z) :-
Y \= 0,
to_int_in_range(BitsPerInt, integer(X) // integer(Y), Z).
to_int_in_range(WordBits, integer(X) // integer(Y), Z).
mod(BitsPerInt, X, Y, Z) :-
uint_quotient(WordBits, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(WordBits,
integer.from_uint(X) // integer.from_uint(Y), Z).
%---------------------%
int_mod(WordBits, X, Y, Z) :-
Y \= 0,
to_int_in_range(BitsPerInt, integer(X) mod integer(Y), Z).
to_int_in_range(WordBits, integer(X) mod integer(Y), Z).
rem(BitsPerInt, X, Y, Z) :-
uint_mod(WordBits, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(WordBits,
integer.from_uint(X) mod integer.from_uint(Y), Z).
%---------------------%
int_rem(WordBits, X, Y, Z) :-
Y \= 0,
to_int_in_range(BitsPerInt, integer(X) rem integer(Y), Z).
to_int_in_range(WordBits, integer(X) rem integer(Y), Z).
%----------------------------------------------------------------------------%
uint_rem(WordBits, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(WordBits,
integer.from_uint(X) rem integer.from_uint(Y), Z).
left_shift(BitsPerInt, X, Y, Z) :-
BitsPerInt = bits_per_int(N),
%---------------------------------------------------------------------------%
int_left_shift(WordBits, X, Y, Z) :-
WordBits = word_bits(N),
Y >= 0,
Y < N,
to_int_in_range(BitsPerInt, integer(X) << Y, Z).
to_int_in_range(WordBits, integer(X) << Y, Z).
left_ushift(BitsPerInt, X, UY, Z) :-
BitsPerInt = bits_per_int(N),
int_left_ushift(WordBits, X, UY, Z) :-
WordBits = word_bits(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_int_in_range(BitsPerInt, integer(X) << Y, Z).
to_int_in_range(WordBits, integer(X) << Y, Z).
right_shift(BitsPerInt, X, Y, Z) :-
BitsPerInt = bits_per_int(N),
uint_left_shift(WordBits, X, Y, Z) :-
WordBits = word_bits(N),
Y >= 0,
Y < N,
to_int_in_range(BitsPerInt, integer(X) >> Y, Z).
to_uint_in_range(WordBits, integer.from_uint(X) << Y, Z).
right_ushift(BitsPerInt, X, UY, Z) :-
BitsPerInt = bits_per_int(N),
uint_left_ushift(WordBits, X, UY, Z) :-
WordBits = word_bits(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_int_in_range(BitsPerInt, integer(X) >> Y, Z).
to_uint_in_range(WordBits, integer.from_uint(X) << Y, Z).
%----------------------------------------------------------------------------%
%---------------------%
floor_to_multiple_of_bits_per_int(X, BitsPerInt, FloorInt) :-
BitsPerInt = bits_per_int(N),
int_right_shift(WordBits, X, Y, Z) :-
WordBits = word_bits(N),
Y >= 0,
Y < N,
to_int_in_range(WordBits, integer(X) >> Y, Z).
int_right_ushift(WordBits, X, UY, Z) :-
WordBits = word_bits(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_int_in_range(WordBits, integer(X) >> Y, Z).
uint_right_shift(WordBits, X, Y, Z) :-
WordBits = word_bits(N),
Y >= 0,
Y < N,
to_uint_in_range(WordBits, integer.from_uint(X) >> Y, Z).
uint_right_ushift(WordBits, X, UY, Z) :-
WordBits = word_bits(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_uint_in_range(WordBits, integer.from_uint(X) >> Y, Z).
%---------------------------------------------------------------------------%
int_floor_to_multiple_of_bits_per_int(X, WordBits, FloorInt) :-
WordBits = word_bits(N),
Trunc = integer(X) // integer(N),
Floor0 = Trunc * integer(N),
( if Floor0 > integer(X) then
@@ -151,29 +241,36 @@ floor_to_multiple_of_bits_per_int(X, BitsPerInt, FloorInt) :-
else
Floor = Floor0
),
to_int_in_range(BitsPerInt, Floor, FloorInt).
to_int_in_range(WordBits, Floor, FloorInt).
quot_bits_per_int(X, BitsPerInt, Z) :-
BitsPerInt = bits_per_int(Y),
quotient(BitsPerInt, X, Y, Z).
int_quot_bits_per_int(X, WordBits, Z) :-
WordBits = word_bits(Y),
int_quotient(WordBits, X, Y, Z).
times_bits_per_int(X, BitsPerInt, Z) :-
BitsPerInt = bits_per_int(Y),
times(BitsPerInt, X, Y, Z).
int_times_bits_per_int(X, WordBits, Z) :-
WordBits = word_bits(Y),
int_times(WordBits, X, Y, Z).
rem_bits_per_int(X, BitsPerInt, Z) :-
BitsPerInt = bits_per_int(Y),
rem(BitsPerInt, X, Y, Z).
int_rem_bits_per_int(X, WordBits, Z) :-
WordBits = word_bits(Y),
int_rem(WordBits, X, Y, Z).
%----------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- pred to_int_in_range(bits_per_int::in, integer::in, int::out) is semidet.
:- pred to_int_in_range(word_bits::in, integer::in, int::out) is semidet.
to_int_in_range(bits_per_int(BitsPerInt), Integer, Int) :-
Integer >= -pow(integer(2), integer(BitsPerInt - 1)),
Integer =< pow(integer(2), integer(BitsPerInt - 1)) - one,
to_int_in_range(word_bits(WordBits), Integer, Int) :-
Integer >= -pow(integer(2), integer(WordBits - 1)),
Integer =< pow(integer(2), integer(WordBits - 1)) - one,
integer.to_int(Integer, Int).
%----------------------------------------------------------------------------%
:- end_module libs.int_emu.
%----------------------------------------------------------------------------%
:- pred to_uint_in_range(word_bits::in, integer::in, uint::out) is semidet.
to_uint_in_range(word_bits(WordBits), Integer, UInt) :-
Integer >= integer.zero,
Integer =< pow(integer(2), integer(WordBits)),
integer.to_uint(Integer, UInt).
%---------------------------------------------------------------------------%
:- end_module parse_tree.int_emu.
%---------------------------------------------------------------------------%

View File

@@ -38,10 +38,8 @@
:- include_module dependency_graph.
:- include_module file_util.
:- include_module graph_colour.
:- include_module int_emu.
:- include_module md5.
:- include_module pickle.
:- include_module uint_emu.
:- include_module va_map.
% OS interfaces not provided by the standard library.

View File

@@ -2387,7 +2387,7 @@ It is used by smart recompilation and `mmc --make'.
graph_colour.m does graph colouring.
This is used by the LLDS back-end for register allocation.
<li>
int_emu.m emulates `int' operations for a given number of bits per int.
int_emu.m emulates integer operations on values with a given number of bits.
<li>
lp.m implements the linear programming algorithm
for optimizing a set of linear constraints on floats

View File

@@ -87,6 +87,7 @@
% Utility routines.
:- include_module builtin_lib_types.
:- include_module check_type_inst_mode_defns.
:- include_module int_emu.
:- include_module item_util.
:- include_module prog_detism.
:- include_module prog_event.

View File

@@ -81,7 +81,6 @@
:- import_module hlds.pred_table.
:- import_module libs.
:- import_module libs.globals.
:- import_module libs.int_emu.
:- import_module libs.optimization_options.
:- import_module libs.options.
:- import_module mdbcomp.
@@ -89,6 +88,7 @@
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.builtin_lib_types.
:- import_module parse_tree.int_emu.
:- import_module parse_tree.parse_tree_out_info.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_data_foreign.
@@ -1373,16 +1373,16 @@ simplify_improve_arith_shift_cmp_ops(IntType, InstMap0, ModuleName, PredName,
% it isn't.
IntType = int_type_int,
Args = [X, Y],
target_bits_per_int(Globals, bits_per_int(TargetBitsPerInt)),
simplify_make_int_ico_op(ModuleName, Op, X, TargetBitsPerInt, Y,
target_word_bits(Globals, word_bits(WordBits)),
simplify_make_int_ico_op(ModuleName, Op, X, WordBits, Y,
ImprovedGoalExpr, !.GoalInfo, !Info)
;
PredName = "times_bits_per_int",
IntType = int_type_int,
Args = [X, Y],
Op = "*",
target_bits_per_int(Globals, bits_per_int(TargetBitsPerInt)),
simplify_make_int_ico_op(ModuleName, Op, X, TargetBitsPerInt, Y,
target_word_bits(Globals, word_bits(WordBits)),
simplify_make_int_ico_op(ModuleName, Op, X, WordBits, Y,
ImprovedGoalExpr, !.GoalInfo, !Info)
;
( PredName = "/", Op = "unchecked_quotient"
@@ -1682,8 +1682,8 @@ int_type_target_bits(Globals, IntType) = IntTypeBits :-
( IntType = int_type_int
; IntType = int_type_uint
),
target_bits_per_int(Globals, bits_per_int(TargetBitsPerInt)),
IntTypeBits = TargetBitsPerInt
target_word_bits(Globals, word_bits(WordBits)),
IntTypeBits = WordBits
;
( IntType = int_type_int8
; IntType = int_type_uint8

View File

@@ -1,151 +0,0 @@
%----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%----------------------------------------------------------------------------%
% Copyright (C) 2017 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.
%----------------------------------------------------------------------------%
%
% File: uint_emu.m.
% Main author: juliensf.
%
% Emulate `uint' operations for a given number of bits per int. These
% predicates succeed only if the result is defined for the given arguments, and
% the result can be represented by the `uint' type of the host compiler.
%
%----------------------------------------------------------------------------%
:- module libs.uint_emu.
:- interface.
:- import_module libs.globals.
%----------------------------------------------------------------------------%
:- type bits_per_uint
---> bits_per_uint(int).
% Return the number of bits per uint for the selected compilation target.
%
:- pred target_bits_per_uint(globals::in, bits_per_uint::out) is det.
%----------------------------------------------------------------------------%
:- pred plus(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred minus(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred times(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred quotient(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred mod(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred rem(bits_per_uint::in, uint::in, uint::in, uint::out) is semidet.
:- pred left_shift(bits_per_uint::in, uint::in, int::in, uint::out)
is semidet.
:- pred left_ushift(bits_per_uint::in, uint::in, uint::in, uint::out)
is semidet.
:- pred right_shift(bits_per_uint::in, uint::in, int::in, uint::out)
is semidet.
:- pred right_ushift(bits_per_uint::in, uint::in, uint::in, uint::out)
is semidet.
%----------------------------------------------------------------------------%
%----------------------------------------------------------------------------%
:- implementation.
:- import_module libs.options.
:- import_module int.
:- import_module integer.
:- import_module uint.
%----------------------------------------------------------------------------%
target_bits_per_uint(Globals, bits_per_uint(BitsPerUInt)) :-
globals.get_target(Globals, Target),
(
Target = target_c,
globals.lookup_int_option(Globals, bits_per_word, BitsPerUInt)
;
( Target = target_csharp
; Target = target_java
),
BitsPerUInt = 32
).
%----------------------------------------------------------------------------%
plus(BitsPerUInt, X, Y, Z) :-
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) + integer.from_uint(Y), Z).
minus(BitsPerUInt, X, Y, Z) :-
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) - integer.from_uint(Y), Z).
times(BitsPerUInt, X, Y, Z) :-
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) * integer.from_uint(Y), Z).
quotient(BitsPerUInt, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) // integer.from_uint(Y), Z).
mod(BitsPerUInt, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) mod integer.from_uint(Y), Z).
rem(BitsPerUInt, X, Y, Z) :-
Y \= 0u,
to_uint_in_range(BitsPerUInt,
integer.from_uint(X) rem integer.from_uint(Y), Z).
%----------------------------------------------------------------------------%
left_shift(BitsPerUInt, X, Y, Z) :-
BitsPerUInt = bits_per_uint(N),
Y >= 0,
Y < N,
to_uint_in_range(BitsPerUInt, integer.from_uint(X) << Y, Z).
left_ushift(BitsPerUInt, X, UY, Z) :-
BitsPerUInt = bits_per_uint(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_uint_in_range(BitsPerUInt, integer.from_uint(X) << Y, Z).
right_shift(BitsPerUInt, X, Y, Z) :-
BitsPerUInt = bits_per_uint(N),
Y >= 0,
Y < N,
to_uint_in_range(BitsPerUInt, integer.from_uint(X) >> Y, Z).
right_ushift(BitsPerUInt, X, UY, Z) :-
BitsPerUInt = bits_per_uint(N),
Y = uint.cast_to_int(UY),
% While UY cannot be negative, Y can be.
Y >= 0,
Y < N,
to_uint_in_range(BitsPerUInt, integer.from_uint(X) >> Y, Z).
%----------------------------------------------------------------------------%
:- pred to_uint_in_range(bits_per_uint::in, integer::in, uint::out) is semidet.
to_uint_in_range(bits_per_uint(BitsPerUInt), Integer, UInt) :-
Integer >= integer.zero,
Integer =< pow(integer(2), integer(BitsPerUInt)),
integer.to_uint(Integer, UInt).
%----------------------------------------------------------------------------%
:- end_module libs.uint_emu.
%----------------------------------------------------------------------------%