[m-rev.] for review: fix float precision bug
Fergus Henderson
fjh at cs.mu.OZ.AU
Wed Nov 6 14:39:21 AEDT 2002
This fixes a bug reported by Peter Moulder.
Estimated hours taken: 4
Branches: main
Reorganize the code in the compiler to centralize the code which handles
output of floating point literals, and fix a bug where we were not outputting
them with sufficient precision.
compiler/c_util.m:
Add new routines make_float_literal and output_float_literal.
These output to 17 digits precision.
compiler/mlds_to_c.m:
compiler/llds_out.m:
compiler/mlds_to_java.m:
compiler/ilasm.m:
Use the new routines.
tests/hard_coded/Mmakefile:
tests/hard_coded/float_consistency.m:
tests/hard_coded/float_consistency.exp:
A regression test.
Workspace: /home/ceres/fjh/mercury
Index: compiler/c_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/c_util.m,v
retrieving revision 1.11
diff -u -d -r1.11 c_util.m
--- compiler/c_util.m 6 Aug 2002 00:30:46 -0000 1.11
+++ compiler/c_util.m 22 Oct 2002 05:50:48 -0000
@@ -8,8 +8,10 @@
% Main author: fjh.
% This module defines utility routines that are useful when
-% generating and/or emitting C code. Changes to this module may require
-% changes to be made to java_util.m
+% generating and/or emitting C code. Some of these routines are
+% also useful with other languages whose syntax is similar to C.
+
+% NOTE: changes to this module may require changes to be made to java_util.m.
%-----------------------------------------------------------------------------%
@@ -19,6 +21,9 @@
:- import_module backend_libs__builtin_ops.
%-----------------------------------------------------------------------------%
+%
+% Line numbering.
+%
% set_line_num(FileName, LineNum):
% emit a #line directive to set the specified filename & linenum
@@ -34,6 +39,9 @@
:- mode c_util__reset_line_num(di, uo) is det.
%-----------------------------------------------------------------------------%
+%
+% String and character handling.
+%
% Print out a string suitably escaped for use as a C string literal.
% This doesn't actually print out the enclosing double quotes --
@@ -69,6 +77,22 @@
%-----------------------------------------------------------------------------%
%
+% Float literals.
+%
+
+ % Convert a float to a string suitable for use as a C (or Java, or IL)
+ % floating point literal.
+:- func c_util__make_float_literal(float) = string.
+
+ % As above, but write the string to the current output stream
+ % rather than returning it.
+:- pred c_util__output_float_literal(float::in, io__state::di, io__state::uo)
+ is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Operators.
+%
% The following predicates all take as input an operator,
% check if it is an operator of the specified kind,
% and if so, return the name of the corresponding C operator
@@ -117,6 +141,9 @@
:- import_module list, bool.
%-----------------------------------------------------------------------------%
+%
+% Line numbering.
+%
c_util__set_line_num(File, Line) -->
globals__io_lookup_bool_option(line_numbers, LineNumbers),
@@ -156,6 +183,12 @@
).
%-----------------------------------------------------------------------------%
+%
+% String and character handling.
+%
+% XXX we should check to ensure that we don't accidentally generate
+% trigraph sequences in string literals.
+%
c_util__output_quoted_string(S0) -->
c_util__output_quoted_multi_string(string__length(S0), S0).
@@ -251,6 +284,8 @@
:- mode escape_any_char(in, out) is det.
% Convert a character to the corresponding C octal escape code.
+ % XXX This assumes that the target language compiler's representation
+ % of characters is the same as the Mercury compiler's.
escape_any_char(Char, EscapeCodeChars) :-
char__to_int(Char, Int),
string__int_to_base_string(Int, 8, OctalString0),
@@ -258,6 +293,28 @@
EscapeCodeChars = ['\\' | string__to_char_list(OctalString)].
%-----------------------------------------------------------------------------%
+%
+% Floating point literals.
+%
+% XXX These routines do not yet handle infinities and NaNs properly.
+
+ % This is used by the C, Java, and IL back-ends,
+ % so the output must be valid syntax in all three languages.
+ %
+ % We output literals using 17 digits of precision.
+ % This is the minimum needed to be able to convert IEEE
+ % double-precision floating point values to strings and
+ % back again without losing precision.
+ %
+make_float_literal(Float) = string__format("%#.17g", [f(Float)]).
+
+output_float_literal(Float) -->
+ io__write_string(make_float_literal(Float)).
+
+%-----------------------------------------------------------------------------%
+%
+% Operators.
+%
c_util__unary_prefix_op(mktag, "MR_mktag").
c_util__unary_prefix_op(tag, "MR_tag").
Index: compiler/ilasm.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ilasm.m,v
retrieving revision 1.34
diff -u -d -r1.34 ilasm.m
--- compiler/ilasm.m 20 Mar 2002 12:36:22 -0000 1.34
+++ compiler/ilasm.m 22 Oct 2002 05:47:40 -0000
@@ -274,6 +274,7 @@
:- import_module char, string, pprint, getopt.
:- import_module require, int, term_io, varset, bool.
:- import_module libs__globals, libs__options, hlds__error_util.
+:- import_module backend_libs__c_util. % for output_float_literal
% Some versions of the IL assembler enforce a rule that if you output
@@ -1144,10 +1145,10 @@
io__write_int(IntConst)
; { Type = float32, Const = f(FloatConst) } ->
io__write_string("ldc.r4\t"),
- io__write_float(FloatConst)
+ c_util__output_float_literal(FloatConst)
; { Type = float64, Const = f(FloatConst) } ->
io__write_string("ldc.r8\t"),
- io__write_float(FloatConst)
+ c_util__output_float_literal(FloatConst)
;
{ error("Inconsistent arguments in ldc instruction") }
).
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.201
diff -u -d -r1.201 llds_out.m
--- compiler/llds_out.m 29 Sep 2002 10:30:41 -0000 1.201
+++ compiler/llds_out.m 6 Nov 2002 03:32:15 -0000
@@ -2257,8 +2257,8 @@
;
{ decl_set_insert(DeclSet0, FloatLabel,
DeclSet) },
- { string__float_to_string(FloatVal,
- FloatString) },
+ { FloatString = c_util__make_float_literal(
+ FloatVal) },
output_indent(FirstIndent, LaterIndent, N0),
{ N = N0 + 1 },
io__write_strings([
@@ -2422,7 +2422,7 @@
% value of the float const, with "pt" instead
% of ".", "plus" instead of "+", and "neg" instead of "-".
%
- string__float_to_string(Float, FloatName0),
+ FloatName0 = c_util__make_float_literal(Float),
string__replace_all(FloatName0, ".", "pt", FloatName1),
string__replace_all(FloatName1, "+", "plus", FloatName2),
string__replace_all(FloatName2, "-", "neg", FloatName).
@@ -4037,7 +4037,7 @@
% do arithmetic in `float' rather than `double'
% if `Float' is `float' not `double'.
output_llds_type_cast(float),
- io__write_float(FloatVal).
+ c_util__output_float_literal(FloatVal).
output_rval_const(string_const(String)) -->
io__write_string("MR_string_const("""),
output_c_quoted_string(String),
@@ -4113,7 +4113,7 @@
output_rval_static_const(int_const(N)) -->
io__write_int(N).
output_rval_static_const(float_const(FloatVal)) -->
- io__write_float(FloatVal).
+ c_util__output_float_literal(FloatVal).
output_rval_static_const(string_const(String)) -->
io__write_string("MR_string_const("""),
output_c_quoted_string(String),
@@ -4427,6 +4427,9 @@
(
string__first_char(String, Char, Rest)
->
+ % XXX This will cause ABI incompatibilities between
+ % compilers which are built in grades that have
+ % different character representations.
char__to_int(Char, Code),
string__int_to_string(Code, CodeString),
string__append("_", CodeString, ThisCharString),
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.139
diff -u -d -r1.139 mlds_to_c.m
--- compiler/mlds_to_c.m 4 Oct 2002 10:02:30 -0000 1.139
+++ compiler/mlds_to_c.m 4 Nov 2002 05:04:33 -0000
@@ -3387,7 +3387,7 @@
% do arithmetic in `float' rather than `double'
% if `MR_Float' is `float' not `double'.
io__write_string("(MR_Float) "),
- io__write_float(FloatVal).
+ c_util__output_float_literal(FloatVal).
mlds_output_rval_const(string_const(String)) -->
% the cast avoids the following gcc warning
% "assignment discards qualifiers from pointer target type"
Index: compiler/mlds_to_java.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_java.m,v
retrieving revision 1.32
diff -u -d -r1.32 mlds_to_java.m
--- compiler/mlds_to_java.m 1 Aug 2002 11:52:20 -0000 1.32
+++ compiler/mlds_to_java.m 21 Oct 2002 08:21:01 -0000
@@ -60,8 +60,10 @@
:- import_module ml_backend__ml_util.
:- import_module ml_backend__java_util.
-:- import_module backend_libs__c_util. % XXX needed for c_util__output_quoted_string
- % c_util_output_quoted_multi_string
+:- import_module backend_libs__c_util.
+ % XXX needed for c_util__output_quoted_string,
+ % c_util__output_quoted_multi_string, and
+ % c_util__make_float_literal.
:- import_module ll_backend__llds_out. % XXX needed for llds_out__name_mangle,
% llds_out__sym_name_mangle,
% llds_out__make_base_typeclass_info_name,
@@ -2932,7 +2934,7 @@
io__write_int(N).
output_rval_const(float_const(FloatVal)) -->
- io__write_float(FloatVal).
+ c_util__output_float_literal(FloatVal).
output_rval_const(string_const(String)) -->
io__write_string(""""),
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.173
diff -u -d -r1.173 Mmakefile
--- tests/hard_coded/Mmakefile 23 Oct 2002 13:41:52 -0000 1.173
+++ tests/hard_coded/Mmakefile 6 Nov 2002 03:21:27 -0000
@@ -50,6 +50,7 @@
export_test \
factt \
failure_unify \
+ float_consistency \
float_field \
float_map \
float_reg \
Index: tests/hard_coded/float_consistency.exp
===================================================================
RCS file: tests/hard_coded/float_consistency.exp
diff -N tests/hard_coded/float_consistency.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/float_consistency.exp 6 Nov 2002 03:20:11 -0000
@@ -0,0 +1,2 @@
+Calc_one = Lit_one: true
+Calc_one/9.0 = Lit_one/9.0: true
Index: tests/hard_coded/float_consistency.m
===================================================================
RCS file: tests/hard_coded/float_consistency.m
diff -N tests/hard_coded/float_consistency.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/float_consistency.m 6 Nov 2002 03:29:37 -0000
@@ -0,0 +1,23 @@
+% This test case tests that the compiler's constant propagation for
+% floating point division produce the same value as that produced
+% by doing the division at runtime.
+% This is a regression test; versions of the compiler prior to Nov 2002
+% failed this test at -O3 and higher.
+:- module float_consistency.
+:- interface.
+:- import_module io.
+:- pred main(state::di, state::uo) is det.
+
+:- implementation.
+:- import_module float, string.
+main -->
+ { Lit_one = 1.0 },
+ { Calc_one = same_as(Lit_one) },
+ print("Calc_one = Lit_one: " ++
+ (if Calc_one = Lit_one then "true" else "false")), nl,
+ print("Calc_one/9.0 = Lit_one/9.0: " ++
+ (if Calc_one/9.0 = Lit_one/9.0 then "true" else "false")), nl.
+
+:- pragma no_inline(same_as/1).
+:- func same_as(float) = float.
+same_as(X) = X.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list