[m-rev.] fix LLDS accurate GC bug

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Nov 13 03:15:43 AEDT 2003


Estimated hours taken: 4
Branches: main

Fix a bug with accurate GC.  The mapping from code addresses to stack
layouts was not working properly, because GCC was reordering code within
C functions (LLDS modules) so that a label at end of the module did not
necessarily have the highest address.  The solution is to put the end label
in a different C function, i.e. a new LLDS module.

runtime/mercury_goto.h:
	Back out previous attempt to solve this problem, since it didn't work.

compiler/transform_llds.m:
	If accurate GC is enabled, append a module containing a dummy end label
	at the end of the module list.

Workspace: /home/jupiter/fjh/ws-jupiter/mercury
Index: compiler/transform_llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/transform_llds.m,v
retrieving revision 1.10
diff -u -d -r1.10 transform_llds.m
--- compiler/transform_llds.m	14 Mar 2003 08:10:12 -0000	1.10
+++ compiler/transform_llds.m	12 Nov 2003 16:03:40 -0000
@@ -16,6 +16,9 @@
 % down to smaller computed gotos.  This avoids a limitation in the lcc
 % compiler.
 %
+% If accurate GC is enabled, we also append a module containing an end label
+% to the list of comp_gen_c_modules.
+%
 %-----------------------------------------------------------------------------%
 
 :- module ll_backend__transform_llds.
@@ -32,6 +35,7 @@
 
 :- implementation.
 
+:- import_module hlds__hlds_pred.
 :- import_module backend_libs__builtin_ops.
 :- import_module backend_libs__proc_label.
 :- import_module libs__globals.
@@ -39,17 +43,10 @@
 :- import_module ll_backend__opt_util.
 :- import_module parse_tree__prog_data.
 
-:- import_module bool, int, list, require, std_util, counter.
+:- import_module bool, int, string, list, require, std_util, counter.
 
 transform_llds(LLDS0, LLDS) -->
-	globals__io_lookup_int_option(max_jump_table_size, Size),
-	(
-		{ Size = 0 }
-	->
-		{ LLDS = LLDS0 }
-	;
-		transform_c_file(LLDS0, LLDS)
-	).
+	transform_c_file(LLDS0, LLDS).
 
 %-----------------------------------------------------------------------------%
 
@@ -58,7 +55,60 @@
 
 transform_c_file(c_file(ModuleName, HeaderInfo, A, B, C, D, Modules0),
 		c_file(ModuleName, HeaderInfo, A, B, C, D, Modules)) -->
-	transform_c_module_list(Modules0, Modules).
+	% split up large computed gotos
+	globals__io_lookup_int_option(max_jump_table_size, MaxJumpTableSize),
+	( { MaxJumpTableSize = 0 } ->
+		{ Modules1 = Modules0 }
+	;
+		transform_c_module_list(Modules0, Modules1)
+	),
+	% append an end label for accurate GC
+	globals__io_get_gc_method(GC),
+	{ GC = accurate, Modules1 \= [] ->
+		list__last_det(Modules1, LastModule),
+		LastModule = comp_gen_c_module(LastModuleName, _),
+		Modules = Modules1 ++
+			[gen_end_label_module(ModuleName, LastModuleName)]
+	;
+		Modules = Modules1
+	}.
+
+%
+% For LLDS native GC, we need to add a dummy comp_gen_c_module at the end of
+% the list.  This dummy module contains only a single dummy procedure which
+% in turn contains only a single label, for which there is no stack layout
+% structure.  The point of this is to ensure that the address of this label
+% gets inserted into the entry table, so that we know where the preceding
+% procedure finishes when mapping from instruction pointer values to stack
+% layout entries.
+%
+% Without this, we might think that the following C function was
+% actually part of the last Mercury procedure in the preceding module,
+% and then incorrectly use the stack layout of the Mercury procedure
+% if we happened to get a heap overflow signal (SIGSEGV) while in that
+% C function.
+%
+% Note that it is not sufficient to generate a label at end of the module,
+% because GCC (e.g. GCC 3.2) sometimes reorders code within a single C
+% function, so that a label declared at the end of the module might not
+% be actually have highest address.  So we generate a new module (which
+% corresponds to a new C function).  XXX Hopefully GCC won't mess with the
+% order of the functions...
+%
+:- func gen_end_label_module(module_name, string) = comp_gen_c_module.
+gen_end_label_module(ModuleName, LastModule) = EndLabelModule :-
+	Arity = 0,
+	ProcId = hlds_pred__initial_proc_id,
+	PredId = hlds_pred__initial_pred_id,
+	PredName = "ACCURATE_GC_END_LABEL",
+	ProcLabel = proc(ModuleName, predicate, ModuleName, PredName,
+		Arity, ProcId),
+	Instrs = [label(local(ProcLabel)) -
+		"label to indicate end of previous procedure"],
+	DummyProc = c_procedure(PredName, Arity, proc(PredId, ProcId),
+				Instrs, ProcLabel,
+				counter__init(0), must_not_alter_rtti),
+	EndLabelModule = comp_gen_c_module(LastModule ++ "_END", [DummyProc]).
 
 %-----------------------------------------------------------------------------%
 
@@ -132,6 +182,7 @@
 transform_instruction(Instr0, ProcLabel, C0, Instrs, C) -->
 	globals__io_lookup_int_option(max_jump_table_size, Size),
 	(
+		{ Size \= 0 },
 		{ Instr0 = computed_goto(_Rval, Labels) - _},
 		{ list__length(Labels, L) },
 		{ L > Size }
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.37
diff -u -d -r1.37 mercury_goto.h
--- runtime/mercury_goto.h	22 Oct 2003 05:56:07 -0000	1.37
+++ runtime/mercury_goto.h	12 Nov 2003 16:06:55 -0000
@@ -108,23 +108,6 @@
   #define MR_MODULE_STATIC_OR_EXTERN static
 #endif
 
-/*
-** For LLDS native GC, we need to record the addresses of the end of modules
-** in the entry table, so that we know where each procedure finishes when
-** mapping from instruction pointer values to stack layout entries.
-** Without this, we might think that the following C function was
-** actually part of the preceding Mercury procedure, and then incorrectly
-** use the stack layout of the Mercury procedure if we happened to
-** get a heap overflow signal (SIGSEGV) while in that C function.
-*/
-#ifdef MR_NATIVE_GC
-  #define MR_MAYBE_DEFINE_MODULE_END_LABEL MR_define_local(module_end_label)
-  #define MR_MAYBE_INIT_MODULE_END_LABEL() MR_init_local(module_end_label)
-#else
-  #define MR_MAYBE_DEFINE_MODULE_END_LABEL /* nothing */
-  #define MR_MAYBE_INIT_MODULE_END_LABEL() /* nothing */
-#endif
-
 /*---------------------------------------------------------------------------*/
 
 /* MACHINE SPECIFIC STUFF REQUIRED FOR NON-LOCAL GOTOS */
@@ -555,8 +538,7 @@
 		goto *MR_dummy_identify_function(			\
 			&&MR_PASTE2(module_name,_dummy_label));		\
 		MR_PASTE2(module_name,_dummy_label):			\
-		{							\
-			MR_MAYBE_INIT_MODULE_END_LABEL();
+		{
   #else /* gcc version <= egcs 1.1.2 */
     #define MR_BEGIN_MODULE(module_name)				\
 	MR_MODULE_STATIC_OR_EXTERN void module_name(void);		\
@@ -565,14 +547,13 @@
 		MR_PRETEND_ADDRESS_IS_USED(				\
 			&&MR_PASTE2(module_name,_dummy_label));		\
 		MR_PASTE2(module_name,_dummy_label):			\
-		{							\
-			MR_MAYBE_INIT_MODULE_END_LABEL();
+		{
   #endif /* gcc version <= egcs 1.1.2 */
   /* initialization code for module goes between MR_BEGIN_MODULE */
   /* and MR_BEGIN_CODE */
   #define MR_BEGIN_CODE } return; {
   /* body of module goes between MR_BEGIN_CODE and MR_END_MODULE */
-  #define MR_END_MODULE MR_MAYBE_DEFINE_MODULE_END_LABEL; } }
+  #define MR_END_MODULE } }
 
 
   #if defined(MR_USE_ASM_LABELS)
@@ -704,10 +685,9 @@
 
   #define MR_BEGIN_MODULE(module_name)	\
 	MR_MODULE_STATIC_OR_EXTERN MR_Code* module_name(void); \
-	MR_MODULE_STATIC_OR_EXTERN MR_Code* module_name(void) { \
-		MR_MAYBE_INIT_MODULE_END_LABEL();
+	MR_MODULE_STATIC_OR_EXTERN MR_Code* module_name(void) {
   #define MR_BEGIN_CODE			return 0;
-  #define MR_END_MODULE			MR_MAYBE_DEFINE_MODULE_END_LABEL; }
+  #define MR_END_MODULE			}
 
   #define MR_declare_entry(label)		extern MR_Code *label(void)
   #define MR_declare_static(label)		static MR_Code *label(void)
-- 
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