[m-dev.] [for review] Changes to config and bytecode (again!)
Bert THOMPSON
aet at cs.mu.oz.au
Mon Apr 14 12:16:26 AEST 1997
Fergus,
Here's a new diff with mods.
|> ! Float64 float64;
|> ! unsigned char *raw_mem_p;
|> !
|> ! float64 = (Float64) FloatVal;
|
|Do you need this cast? Why?
It makes it obvious that the type of FloatVal (Float) and the
type of float64 (Float64) need not be the same.
Other points dealt with.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Estimated hours taken: 3
We added to mercury_types.h the type Float64, which is a 64-bit IEEE-754
floating point type that may be either big-endian or little-endian.
In order to do this, we also added tests in configure.in to
find a 64-bit floating-point C type on the platform.
Another test added to configure.in is the platform endianness.
We need this in order to dump a float to bytecode in a manner portable
between all platforms on which we're interested in running Mercury.
We also change output_float and output_int in compiler/bytecode.m
to dump floats and ints respectively in a portable way.
In compiler/bytecode.m, we also make a gratuitous renaming of
output_two_byte() to output_short(). All uses of output_two_byte()
were effectively to dump a short.
configure.in
runtime/
conf.h.in
mercury_types.h
compiler/
bytecode.m
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Index: configure.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/configure.in,v
retrieving revision 1.88
diff -c -r1.88 configure.in
*** 1.88 1997/03/27 09:13:35
--- configure.in 1997/04/13 06:34:43
***************
*** 760,765 ****
--- 760,873 ----
fi
AC_SUBST(HAVE_BOXED_FLOATS)
#-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether float is 64-bit)
+ AC_CACHE_VAL(mercury_cv_float_is_64_bit,
+ AC_TRY_RUN([
+ #include <limits.h>
+ int main() {
+ if (sizeof(float) * CHAR_BIT == 64)
+ exit(0);
+ else
+ exit(1);
+ }],
+ [mercury_cv_float_is_64_bit=yes],
+ [mercury_cv_float_is_64_bit=no],
+ [mercury_cv_float_is_64_bit=no])
+ )
+ AC_MSG_RESULT($mercury_cv_float_is_64_bit)
+ if test "$mercury_cv_float_is_64_bit" = yes; then
+ AC_DEFINE(FLOAT_IS_64_BIT)
+ fi
+ AC_SUBST(FLOAT_IS_64_BIT)
+ #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether double is 64-bit)
+ AC_CACHE_VAL(mercury_cv_double_is_64_bit,
+ AC_TRY_RUN([
+ #include <limits.h>
+ int main() {
+ if (sizeof(double) * CHAR_BIT == 64)
+ exit(0);
+ else
+ exit(1);
+ }],
+ [mercury_double_is_64_bit=yes],
+ [mercury_double_is_64_bit=no],
+ [mercury_double_is_64_bit=no])
+ )
+ AC_MSG_RESULT($mercury_double_is_64_bit)
+ if test "$mercury_double_is_64_bit" = yes; then
+ AC_DEFINE(DOUBLE_IS_64_BIT)
+ fi
+ AC_SUBST(DOUBLE_IS_64_BIT)
+ #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether long double is 64-bit)
+ AC_CACHE_VAL(mercury_cv_long_double_is_64_bit,
+ AC_TRY_RUN([
+ #include <limits.h>
+ int main() {
+ if (sizeof(long double) * CHAR_BIT == 64)
+ exit(0);
+ else
+ exit(1);
+ }],
+ [mercury_cv_long_double_is_64_bit=yes],
+ [mercury_cv_long_double_is_64_bit=no],
+ [mercury_cv_long_double_is_64_bit=no])
+ )
+ AC_MSG_RESULT($mercury_cv_long_double_is_64_bit)
+ if test "$mercury_cv_long_double_is_64_bit" = yes; then
+ AC_DEFINE(LONG_DOUBLE_IS_64_BIT)
+ fi
+ AC_SUBST(LONG_DOUBLE_IS_64_BIT)
+ #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether architecture is big-endian)
+ AC_CACHE_VAL(mercury_cv_is_bigender,
+ AC_TRY_RUN([
+ int main() {
+ int x = 1;
+ unsigned char *x_p;
+
+ x_p = (unsigned char*) &x;
+
+ if (*x_p == 0)
+ exit(0);
+ else
+ exit(1);
+ }],
+ [mercury_cv_is_bigender=yes],
+ [mercury_cv_is_bigender=no],
+ [mercury_cv_is_bigender=no])
+ )
+ AC_MSG_RESULT($mercury_cv_is_bigender)
+ if test "$mercury_cv_is_bigender" = yes; then
+ AC_DEFINE(BIG_ENDIAN)
+ fi
+ AC_SUBST(BIG_ENDIAN)
+ #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether architecture is little-endian)
+ AC_CACHE_VAL(mercury_cv_is_littleender,
+ AC_TRY_RUN([
+ int main() {
+ int x = 1;
+ unsigned char *x_p;
+
+ x_p = (unsigned char*) &x;
+
+ if (*x_p == 1)
+ exit(0);
+ else
+ exit(1);
+ }],
+ [mercury_cv_is_littleender=yes],
+ [mercury_cv_is_littleender=no],
+ [mercury_cv_is_littleender=no])
+ )
+ AC_MSG_RESULT($mercury_cv_is_littleender)
+ if test "$mercury_cv_is_littleender" = yes; then
+ AC_DEFINE(LITTLE_ENDIAN)
+ fi
+ AC_SUBST(LITTLE_ENDIAN)
+ #-----------------------------------------------------------------------------#
#
# For Irix 5, gcc labels don't work with shared libraries,
# so if we're using gcc labels, we need to use non-shared libraries,
Index: runtime/conf.h.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/conf.h.in,v
retrieving revision 1.13
diff -c -r1.13 conf.h.in
*** 1.13 1997/02/27 05:45:02
--- conf.h.in 1997/04/13 06:35:45
***************
*** 55,60 ****
--- 55,65 ----
** SIGACTION_FIELD the name of the field in the sigaction struct
** (either sa_handler or sa_sigaction).
** PARALLEL we are configuring for parallel execution
+ ** FLOAT_IS_64_BITS The C type `float' is 64-bit on this host.
+ ** DOUBLE_IS_64_BITS The C type `double' is 64-bit on this host.
+ ** LONG_DOUBLE_IS_64_BITS The C type `long double' is 64-bit on this host.
+ ** BIG_ENDIAN This host is big-endian.
+ ** LITTLE_ENDIAN This host is little-endian.
*/
#undef WORD_TYPE
***************
*** 81,85 ****
--- 86,95 ----
#undef HAVE_SIGACTION
#undef SIGACTION_FIELD
#undef PARALLEL
+ #undef FLOAT_IS_64_BIT
+ #undef DOUBLE_IS_64_BIT
+ #undef LONG_DOUBLE_IS_64_BIT
+ #undef BIG_ENDIAN
+ #undef LITTLE_ENDIAN
#endif /* CONF_H */
Index: runtime/mercury_types.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_types.h,v
retrieving revision 1.2
diff -c -r1.2 mercury_types.h
*** 1.2 1997/02/12 02:15:57
--- mercury_types.h 1997/04/13 06:39:23
***************
*** 24,29 ****
--- 24,45 ----
typedef unsigned WORD_TYPE Unsigned;
typedef void Code; /* code addresses are `void *' */
+ /*
+ ** Float64 is required for the bytecode.
+ ** XXX: We should also check for IEEE-754 compliance.
+ */
+
+ #if FLOAT_IS_64_BIT
+ typedef float Float64;
+ #elif DOUBLE_IS_64_BIT
+ typedef double Float64;
+ #elif LONG_DOUBLE_IS_64_BIT
+ typedef long double Float64;
+ #else
+ #error For Mercury bytecode, we require 64-bit IEEE-754 floating point
+ #endif
+
+
/* continuation function type, for --high-level-C option */
typedef void (*Cont) (void);
Index: compiler/bytecode.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/bytecode.m,v
retrieving revision 1.23
diff -c -r1.23 bytecode.m
*** 1.23 1997/03/24 06:00:57
--- bytecode.m 1997/04/14 02:10:20
***************
*** 125,131 ****
:- pred bytecode__version(int::out) is det.
! bytecode__version(8).
output_bytecode_file(FileName, ByteCodes) -->
io__tell_binary(FileName, Result),
--- 125,131 ----
:- pred bytecode__version(int::out) is det.
! bytecode__version(9).
output_bytecode_file(FileName, ByteCodes) -->
io__tell_binary(FileName, Result),
***************
*** 133,139 ****
{ Result = ok }
->
{ bytecode__version(Version) },
! output_two_byte(Version),
output_bytecode_list(ByteCodes),
io__told_binary
;
--- 133,139 ----
{ Result = ok }
->
{ bytecode__version(Version) },
! output_short(Version),
output_bytecode_list(ByteCodes),
io__told_binary
;
***************
*** 152,157 ****
--- 152,158 ----
{ Result = ok }
->
{ bytecode__version(Version) },
+ io__write_string("bytecode_version "),
io__write_int(Version),
io__write_string("\n"),
debug_bytecode_list(ByteCodes),
***************
*** 303,309 ****
output_args(semidet_success_check) --> [].
output_args(fail) --> [].
output_args(context(Line)) -->
! output_two_byte(Line).
output_args(not_supported) --> [].
:- pred debug_args(byte_code, io__state, io__state).
--- 304,310 ----
output_args(semidet_success_check) --> [].
output_args(fail) --> [].
output_args(context(Line)) -->
! output_short(Line).
output_args(not_supported) --> [].
:- pred debug_args(byte_code, io__state, io__state).
***************
*** 495,501 ****
:- mode output_length(in, di, uo) is det.
output_length(Length) -->
! output_two_byte(Length).
:- pred debug_length(int, io__state, io__state).
:- mode debug_length(in, di, uo) is det.
--- 496,502 ----
:- mode output_length(in, di, uo) is det.
output_length(Length) -->
! output_short(Length).
:- pred debug_length(int, io__state, io__state).
:- mode debug_length(in, di, uo) is det.
***************
*** 537,543 ****
:- mode output_var(in, di, uo) is det.
output_var(Var) -->
! output_two_byte(Var).
:- pred output_vars(list(byte_var), io__state, io__state).
:- mode output_vars(in, di, uo) is det.
--- 538,544 ----
:- mode output_var(in, di, uo) is det.
output_var(Var) -->
! output_short(Var).
:- pred output_vars(list(byte_var), io__state, io__state).
:- mode output_vars(in, di, uo) is det.
***************
*** 567,573 ****
:- mode output_temp(in, di, uo) is det.
output_temp(Var) -->
! output_two_byte(Var).
:- pred debug_temp(byte_temp, io__state, io__state).
:- mode debug_temp(in, di, uo) is det.
--- 568,574 ----
:- mode output_temp(in, di, uo) is det.
output_temp(Var) -->
! output_short(Var).
:- pred debug_temp(byte_temp, io__state, io__state).
:- mode debug_temp(in, di, uo) is det.
***************
*** 665,671 ****
:- mode output_label_id(in, di, uo) is det.
output_label_id(LabelId) -->
! output_two_byte(LabelId).
:- pred debug_label_id(int, io__state, io__state).
:- mode debug_label_id(in, di, uo) is det.
--- 666,672 ----
:- mode output_label_id(in, di, uo) is det.
output_label_id(LabelId) -->
! output_short(LabelId).
:- pred debug_label_id(int, io__state, io__state).
:- mode debug_label_id(in, di, uo) is det.
***************
*** 682,688 ****
output_byte(0),
output_string(ModuleId),
output_string(Functor),
! output_two_byte(Arity),
output_tag(Tag).
output_cons_id(int_const(IntVal)) -->
output_byte(1),
--- 683,689 ----
output_byte(0),
output_string(ModuleId),
output_string(Functor),
! output_short(Arity),
output_tag(Tag).
output_cons_id(int_const(IntVal)) -->
output_byte(1),
***************
*** 1086,1095 ****
{ error("byte does not fit in eight bits") }
).
! :- pred output_two_byte(int, io__state, io__state).
! :- mode output_two_byte(in, di, uo) is det.
! output_two_byte(Val) -->
{ Val1 is Val >> 8 },
{ Val2 is Val mod 256 },
( { Val1 < 256 } ->
--- 1087,1102 ----
{ error("byte does not fit in eight bits") }
).
! /*
! ** Spit out a `short' in a portable format.
! ** This format is: big-endian, 16-bit, 2's-complement.
! **
! ** NOTE: We -assume- the machine architecture uses 2's-complement.
! */
! :- pred output_short(int, io__state, io__state).
! :- mode output_short(in, di, uo) is det.
! output_short(Val) -->
{ Val1 is Val >> 8 },
{ Val2 is Val mod 256 },
( { Val1 < 256 } ->
***************
*** 1099,1132 ****
{ error("small integer does not fit in sixteen bits") }
).
:- pred output_int(int, io__state, io__state).
:- mode output_int(in, di, uo) is det.
! output_int(Val) -->
! { Val1 is Val >> 24 },
! { Val2 is (Val >> 16) mod 256 },
! { Val3 is (Val >> 8) mod 256 },
! { Val4 is Val mod 256 },
! ( { Val1 < 256 } ->
! io__write_byte(Val1),
! io__write_byte(Val2),
! io__write_byte(Val3),
! io__write_byte(Val4)
;
! { error("integer does not fit in thirtytwo bits") }
).
:- pred output_float(float, io__state, io__state).
:- mode output_float(in, di, uo) is det.
output_float(Val) -->
! % XXX This is just temporary; we ought to find a way to write out
! % the float as a sequence of bytes. Requiring the compiling and
! % debugging platform to have the same FP representation is better
! % than silently rounding/truncating float values given to the
! % debugger.
! { string__float_to_string(Val, Str) },
! output_string(Str).
%---------------------------------------------------------------------------%
--- 1106,1237 ----
{ error("small integer does not fit in sixteen bits") }
).
+ /*
+ ** Spit out an `int' in a portable `highest common denominator' format.
+ ** This format is: big-endian, 64-bit, 2's-complement int.
+ **
+ ** NOTE: We -assume- the machine architecture uses 2's-complement.
+ */
:- pred output_int(int, io__state, io__state).
:- mode output_int(in, di, uo) is det.
! output_int(IntVal) -->
! { int__bits_per_int(IntBits) },
! (
! { IntBits > int64_bits } ->
! { error("size of int is larger than size of bytecode integer.")}
! ;
! { ZeroPadBytes is (int64_bits - IntBits) // bits_per_byte },
! output_padding_zeros(ZeroPadBytes),
! { FirstByteToDump is int64_bytes - ZeroPadBytes - 1 },
! output_int_bytes(FirstByteToDump, IntVal)
! ).
!
! :- func int64_bits = int.
! :- mode int64_bits = out is det.
!
! int64_bits = bits_per_byte * int64_bytes.
!
! :- func int64_bytes = int.
! :- mode int64_bytes = out is det.
!
! int64_bytes = 8.
!
! :- func bits_per_byte = int.
! :- mode bits_per_byte = out is det.
!
! bits_per_byte = 8.
!
! :- pred output_padding_zeros(int, io__state, io__state).
! :- mode output_padding_zeros(in, di, uo) is det.
!
! output_padding_zeros(N) -->
! ( { N > 0 } ->
! io__write_byte(0),
! { N1 is N - 1 },
! output_padding_zeros(N1)
! ;
! { true }
! ).
!
! :- pred output_int_bytes(int, int, io__state, io__state).
! :- mode output_int_bytes(in, in, di, uo) is det.
!
! output_int_bytes(N, IntVal) -->
! ( { N >= 0 } ->
! { N8 is N * 8 },
! { Byte is (IntVal >> N8) mod 256 },
! { N1 is N - 1 },
! io__write_byte(Byte),
! output_int_bytes(N1, IntVal)
;
! { true }
).
+ /*
+ ** Spit out a `float' in a portable `highest common denominator format.
+ ** This format is: big-endian, 64-bit, IEEE-754 floating point value.
+ **
+ ** NOTE: We -assume- the machine architecture uses IEEE-754.
+ */
:- pred output_float(float, io__state, io__state).
:- mode output_float(in, di, uo) is det.
output_float(Val) -->
! { float_to_float64_bytes(Val, B0, B1, B2, B3, B4, B5, B6, B7) },
! output_byte(B0),
! output_byte(B1),
! output_byte(B2),
! output_byte(B3),
! output_byte(B4),
! output_byte(B5),
! output_byte(B6),
! output_byte(B7).
!
! /*
! ** Convert a `float' to the representation used in the bytecode.
! ** That is, a sequence of eight bytes.
! */
! :- pred float_to_float64_bytes(float::in,
! int::out, int::out, int::out, int::out,
! int::out, int::out, int::out, int::out) is det.
! :- pragma(c_code,
! float_to_float64_bytes(FloatVal::in, B0::out, B1::out, B2::out, B3::out,
! B4::out, B5::out, B6::out, B7::out),
! "
!
! {
! Float64 float64;
! unsigned char *raw_mem_p;
!
! float64 = (Float64) FloatVal;
! raw_mem_p = (unsigned char*) &float64;
!
! #if defined(BIG_ENDIAN)
! B0 = raw_mem_p[0];
! B1 = raw_mem_p[1];
! B2 = raw_mem_p[2];
! B3 = raw_mem_p[3];
! B4 = raw_mem_p[4];
! B5 = raw_mem_p[5];
! B6 = raw_mem_p[6];
! B7 = raw_mem_p[7];
! #elif defined(LITTLE_ENDIAN)
! B7 = raw_mem_p[0];
! B6 = raw_mem_p[1];
! B5 = raw_mem_p[2];
! B4 = raw_mem_p[3];
! B3 = raw_mem_p[4];
! B2 = raw_mem_p[5];
! B1 = raw_mem_p[6];
! B0 = raw_mem_p[7];
! #else
! #error Weird-endian architecture
! #endif
! }
!
! "
! ).
%---------------------------------------------------------------------------%
More information about the developers
mailing list