for review: change semantics of integer shifts

Simon Taylor stayl at cs.mu.OZ.AU
Mon Mar 15 10:55:05 AEDT 1999


Estimated hours taken: 1

Change the bit shift operators to perform checking to avoid
undefined behaviour.

library/int.m:
	Add checking to `int:<<' and `int:>>'.

compiler/code_util.m:
	Replace `int:<<' and `int:>>' with `int:unchecked_left_shift' and
	`int:unchecked_right_shift' in the builtin table.

NEWS:
	Mention the changes to int.m.



--- NEWS	1999/03/14 23:31:32	1.2
+++ NEWS	1999/03/14 23:51:24
@@ -34,3 +34,11 @@
   See the "Interactive query commands" subsection of the "Debugger commands"
   section of the "Debugging" chapter of the Mercury User's Guide for details.
 
+* The semantics of `int:>>/2' and `int:<</2' has changed.
+  The results are undefined only if the left operand of
+  `int:>>/2' is negative, or if both operands of `int:<</2' are negative.
+
+  The new functions `int:unchecked_left_shift/2' and
+  `int:unchecked_right_shift/2' implement the old semantics,
+  using the C shift operators.
+

Index: code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_util.m,v
retrieving revision 1.104
diff -u -u -r1.104 code_util.m
--- code_util.m	1998/11/24 03:56:57	1.104
+++ code_util.m	1999/03/12 00:29:53
@@ -434,11 +434,11 @@
 	no, yes(Z - binop((mod), var(X), var(Y)))).
 code_util__translate_builtin_2("int", "builtin_left_shift", 0, [X, Y, Z],
 	no, yes(Z - binop((<<), var(X), var(Y)))).
-code_util__translate_builtin_2("int", "<<", 0, [X, Y, Z],
+code_util__translate_builtin_2("int", "unchecked_left_shift", 0, [X, Y, Z],
 	no, yes(Z - binop((<<), var(X), var(Y)))).
 code_util__translate_builtin_2("int", "builtin_right_shift", 0, [X, Y, Z],
 	no, yes(Z - binop((>>), var(X), var(Y)))).
-code_util__translate_builtin_2("int", ">>", 0, [X, Y, Z],
+code_util__translate_builtin_2("int", "unchecked_right_shift", 0, [X, Y, Z],
 	no, yes(Z - binop((>>), var(X), var(Y)))).
 code_util__translate_builtin_2("int", "builtin_bit_and", 0, [X, Y, Z],
 	no, yes(Z - binop((&), var(X), var(Y)))).

Index: int.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/int.m,v
retrieving revision 1.52
diff -u -u -r1.52 int.m
--- int.m	1998/01/23 12:33:19	1.52
+++ int.m	1999/03/14 23:48:11
@@ -107,13 +107,34 @@
 :- mode in rem in = uo is det.
 
 	% left shift
+	% The result is undefined if both operands are negative.
+	% If the right operand is negative, a right shift is performed.
+	% If the right operand is greater than or equal to the result of
+	% `int__bits_per_int/1', 0 is returned.
 :- func int << int = int.
 :- mode in  << in  = uo  is det.
 
+	% left shift
+	% The result is undefined if the right operand is greater
+	% than or equal to the result of `int__bits_per_int/1'.
+:- func unchecked_left_shift(int, int) = int.
+:- mode unchecked_left_shift(in, in) = uo is det.
+
 	% (arithmetic) right shift
+	% The result is undefined if the left operand is negative.
+	% if the right operand is negative, a left shift is performed.
+	% If the right operand is greater than or equal to the result of
+	% `int__bits_per_int/1', 0 is returned.
 :- func int >> int = int.
 :- mode in  >> in  = uo  is det.
 
+	% (arithmetic) right shift
+	% The result is undefined if either operand is negative,
+	% or if the right operand is greater than or equal to the
+	% result of `int__bits_per_int/1'.
+:- func unchecked_right_shift(int, int) = int.
+:- mode unchecked_right_shift(in, in) = uo is det.
+
 	% bitwise and
 :- func int /\ int = int.
 :- mode in  /\ in  = uo  is det.
@@ -220,6 +241,46 @@
 	).
 
 X mod Y = X - (X div Y) * Y.
+
+	% XXX This definition is here for bootstrapping.
+	% After the corresponding change to the compiler is installed,
+	% the compiler ignore this clause, and will internally replace
+	% the body of unchecked_left_shift with a `recursive' call.
+	% See make_hlds:add_builtin.
+unchecked_left_shift(X, Y) = X << Y.
+
+X << Y = Z :-
+	(
+		int__bits_per_int(IntBits),
+		Y > IntBits
+	->
+		Z = 0
+	;
+		Y >= 0
+	->
+		Z = unchecked_left_shift(X, Y)
+	;
+		Z = unchecked_right_shift(X, - Y)
+	).
+
+	% XXX This definition is here for bootstrapping.
+	% See the comment for unchecked_left_shift.
+unchecked_right_shift(X, Y) = X >> Y.
+
+X >> Y = Z :-
+	(
+		int__bits_per_int(IntBits),
+		Y > IntBits
+	->
+		Z = 0
+	;
+		Y >= 0
+	->
+		Z = unchecked_right_shift(X, Y)
+	;
+		Z = unchecked_left_shift(X, - Y)
+	).
+
 
 int__abs(Num, Abs) :-
 	(



More information about the developers mailing list