[for review] Changes to config and bytecode (again!)

Bert Thompson aet at cs.mu.oz.au
Sat Apr 12 18:52:53 AEST 1997


Zoltan,

Can you please review these changes...

Bert

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Estimated hours taken: 2

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 a test in configure.in to see if
the C type `double' is 64-bit 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
*** configure.in	1997/03/27 09:13:35	1.88
--- configure.in	1997/04/10 09:14:42
***************
*** 760,765 ****
--- 760,833 ----
  fi
  AC_SUBST(HAVE_BOXED_FLOATS)
  #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether double is 64-bits)
+ AC_CACHE_VAL(mercury_cv_float64,
+ 	AC_TRY_RUN([
+ 	#include <limits.h>
+ 	int main() {
+ 		if (sizeof(double) * CHAR_BIT == 64)
+ 			exit(0);
+ 		else
+ 			exit(1);
+ 	}],
+ 	[mercury_cv_float64=yes],
+ 	[mercury_cv_float64=no],
+ 	[mercury_cv_float64=no])
+ )
+ AC_MSG_RESULT($mercury_cv_float64)
+ if test "$mercury_cv_float64" = yes; then
+ 	AC_DEFINE(DOUBLE_IS_64_BITS)
+ fi
+ AC_SUBST(DOUBLE_IS_64_BITS)
+ #-----------------------------------------------------------------------------#
+ AC_MSG_CHECKING(whether architecture is big-endian)
+ AC_CACHE_VAL(mercury_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_is_bigender=yes],
+ 	[mercury_is_bigender=no],
+ 	[mercury_is_bigender=no])
+ )
+ AC_MSG_RESULT($mercury_is_bigender)
+ if test "$mercury_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_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_is_littleender=yes],
+ 	[mercury_is_littleender=no],
+ 	[mercury_is_littleender=no])
+ )
+ AC_MSG_RESULT($mercury_is_littleender)
+ if test "$mercury_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: compiler/bytecode.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/bytecode.m,v
retrieving revision 1.23
diff -c -r1.23 bytecode.m
*** bytecode.m	1997/03/24 06:00:57	1.23
--- bytecode.m	1997/04/12 08:23:49
***************
*** 121,131 ****
  :- implementation.
  
  :- import_module hlds_pred.
! :- import_module char, library, int, string, require.
  
  :- pred bytecode__version(int::out) is det.
  
! bytecode__version(8).
  
  output_bytecode_file(FileName, ByteCodes) -->
  	io__tell_binary(FileName, Result),
--- 121,131 ----
  :- implementation.
  
  :- import_module hlds_pred.
! :- import_module char, library, int, string, require, globals, options.
  
  :- 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,1227 ----
  		{ 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 mahcine architecture uses 2's-complement.
+ */
  :- pred output_int(int, io__state, io__state).
  :- mode output_int(in, di, uo) is det.
  
  output_int(Val) -->
! 	globals__io_lookup_int_option(bytes_per_word, IntBytes),
! 	% Is Integer 32-bits?
! 	( { IntBytes = 4 } ->
! 		io__write_byte(0),
! 		io__write_byte(0),
! 		io__write_byte(0),
! 		io__write_byte(0),
! 		{ Val0 is (Val >> 24) mod 256 },
! 		{ Val1 is (Val >> 16) mod 256 },
! 		{ Val2 is (Val >> 8) mod 256 },
! 		{ Val3 is (Val >> 0) mod 256 },
! 		io__write_byte(Val0),
! 		io__write_byte(Val1),
! 		io__write_byte(Val2),
! 		io__write_byte(Val3)
! 	% Is Integer 64-bits?
! 	; { IntBytes = 8 } ->
! 		{Val0 is (Val >> 56) mod 256 },
! 		{Val1 is (Val >> 48) mod 256 },
! 		{Val2 is (Val >> 40) mod 256 },
! 		{Val3 is (Val >> 32) mod 256 },
! 		{Val4 is (Val >> 24) mod 256 },
! 		{Val5 is (Val >> 16) mod 256 },
! 		{Val6 is (Val >> 8) mod 256 },
! 		{Val7 is (Val >> 0) mod 256 },
! 		io__write_byte(Val0),
  		io__write_byte(Val1),
  		io__write_byte(Val2),
  		io__write_byte(Val3),
! 		io__write_byte(Val4),
! 		io__write_byte(Val5),
! 		io__write_byte(Val6),
! 		io__write_byte(Val7)
  	;
! 		/*
! 		** XXX: We currently have no interest in architectures
! 		** where int is neither 32- nor 64-bit.
! 		*/
! 		{ error("integer is neither 32 nor 64 bits") }
  	).
+ 		
  
+ /*
+ ** 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
! 	}
! 	
! 	"
! ).
  
  %---------------------------------------------------------------------------%
  
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
*** conf.h.in	1997/02/27 05:45:02	1.13
--- conf.h.in	1997/04/10 09:14:56
***************
*** 81,85 ****
--- 81,88 ----
  #undef	HAVE_SIGACTION
  #undef	SIGACTION_FIELD
  #undef	PARALLEL
+ #undef	DOUBLE_IS_64_BITS
+ #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
*** mercury_types.h	1997/02/12 02:15:57	1.2
--- mercury_types.h	1997/04/12 08:30:06
***************
*** 24,29 ****
--- 24,40 ----
  typedef unsigned WORD_TYPE	Unsigned;
  typedef void			Code;	/* code addresses are `void *' */
  
+ /*
+ ** Float64 is required for the bytecode.
+ */
+ 
+ #if	DOUBLE_IS_64_BITS
+ 	typedef double			Float64;
+ #else
+ 	#error	For Mercury bytecode, we require double to be 64-bit IEEE-754.
+ #endif
+ 
+ 
  /* continuation function type, for --high-level-C option */
  typedef void (*Cont) (void);
  



More information about the developers mailing list