[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