[m-rev.] for review: improve procname mangling for .NET backend.

Tyson Dowd trd at cs.mu.OZ.AU
Wed May 9 23:24:18 AEST 2001


On 09-May-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 09-May-2001, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> > Index: compiler/mlds_to_il.m
> ...
> > +	%
> > +	% We mangle as follows:
> > +	%	- Problem:
> > +	%	  Two preds or funcs with different arities in Mercury end
> > +	%	  up having the same types and arities in IL.
> 
> I suggest adding a bit more here to explain why that can happen, e.g.
> 
> 	%	  Two preds or funcs with different arities in Mercury end
> 	%	  up having the same types and arities in IL, e.g. because
> 	%	  one of them takes io__state arguments which get omitted
> 	%	  in IL.

Done.

> 
> > +	%	- Problem:
> > +	%	  A semidet pred returns its success value, and so has
> > +	%	  the same return type (bool) as a function.
> > +	%
> > +	%	  To avoid this, we mangle all semidet preds and
> > +	%	  functions to include whether they are a pred or a
> > +	%	  function using _p or _f.
> 
> The spec is not clear here: do you mean to mangle all functions
> or just semidet functions?  The code below just mangles semidet
> functions, but that's wrong, because the clash you're thinking of
> here occurs when you have a det function and a semidet predicate, e.g.
> 	
> 	:- func foo(int) = bool
> 	:- pred foo(int::in) is semidet.
> 	% both map to `bool foo_1(int)'

I thought the code mangled semidet predicates *and* functions.
Which is more than it needs to do.

Actually the case for the clash here is a bit more complex.  The pred
and function will differ in arity by 1 (foo_1_p and foo_2 above).
So you need to find a case where they have the same arity in the source,
which will of course mean that their IL type signatures will be of
different arity (being a semidet pred adds one to your IL arity).

 	:- func foo(int) = bool
 	:- pred foo(int::in) is semidet.
	map to 'bool foo_2(int)' and 'bool foo_1(int)'

 	:- func foo(int) = bool
 	:- pred foo(int::in, int::in) is semidet.
	map to 'bool foo_2(int)' and 'bool foo_2(int, int)'

However, if a dummy argument is removed, or arguments are added, then we
have trouble.

 	:- func foo(int) = bool
 	:- pred foo(int::in, io__state::di) is semidet.
	map to 'bool foo_2(int)' and 'bool foo_2(int)'


Actually, it might be fruitful to only add the _arity if the predicate
has dummy arguments removed or type_info arguments added.   In all other
cases it should be safe to leave the arity off. 
But we should think about this one.

> 
> Anyway, to avoid a collision, you only need to mangle one of the two
> clashing identifiers; so you could just mangle semidet preds, and leave
> the functions alone.  I think that would be a nicer approach.

That's fine too. 

> 
> However, there is another problem which you didn't mention.
> The same thing can occur for predicates which are not semidet:
> 	
> 	:- func foo(int::out) = (int::in) is det.
> 	:- pred foo(int::out, int::in) is det.
> 	% both map to `void foo_2(int &, int)'
> 
> That needs to be fixed.

Ok, so non-default mode funcs should be mangled with _f.

> I think that it may be possible to have conflicts with user names
> in the case where there is a <modulename>.  However, this is a minor
> issue; it's probably OK to just XXX it for now.

Ok, no problems.

Here's an incremental diff that addresses these problems.

--- zzlog.mangling2	Wed May  9 01:50:03 2001
+++ zzlog.mangling4	Wed May  9 23:22:36 2001
@@ -10,11 +10,12 @@
 compiler/mlds.m:
 compiler/mlds_to_c.m:
 compiler/mlds_to_java.m:
-	Add the code_model to the proc_label.
+	Add the code_model and a boolean indicating whether this
+	function has a non-default (in, in, in, out) mode to the proc_label.
 
 compiler/mlds_to_il.m:
 	Mangle much more carefully.  We still mangle in a predictable,
 	context-insensitive manner, however we take advantage of the
-	.NET backend to avoid name clashes in most cases.
-
+	overloading available in the .NET backend to avoid name clashes
+	in most cases.
 
diff -u compiler/ml_code_util.m compiler/ml_code_util.m
--- compiler/ml_code_util.m
+++ compiler/ml_code_util.m
@@ -1183,7 +1183,7 @@
 ml_gen_pred_label_from_rtti(RttiProcLabel, MLDS_PredLabel, MLDS_Module) :-
 	RttiProcLabel = rtti_proc_label(PredOrFunc, ThisModule, PredModule,	
 		PredName, PredArity, ArgTypes, _PredId, ProcId,
-		_VarSet, _HeadVars, _ArgModes, CodeModel,
+		_VarSet, _HeadVars, ArgModes, CodeModel,
 		IsImported, _IsPseudoImported, _IsExported,
 		IsSpecialPredInstance),
 	(
@@ -1245,14 +1245,28 @@
 			DefiningModule = PredModule,
 			MaybeDeclaringModule = no
 		),
+		(
+			PredOrFunc = function,
+			not (default_func_arg_modes(ArgModes))
+		->
+			NonDefaultModeFunc = yes
+		;
+			NonDefaultModeFunc = no
+		),
 		MLDS_PredLabel = pred(PredOrFunc, MaybeDeclaringModule,
-				PredName, PredArity, CodeModel)
+				PredName, PredArity, CodeModel,
+				NonDefaultModeFunc)
 	),
 	MLDS_Module = mercury_module_name_to_mlds(DefiningModule).
 
 ml_gen_new_label(Label) -->
 	ml_gen_info_new_label(LabelNum),
 	{ string__format("label_%d", [i(LabelNum)], Label) }.
+
+:- pred default_func_arg_modes(list(arg_mode)::in) is semidet.
+default_func_arg_modes([top_out]).
+default_func_arg_modes([top_in, ArgMode2 | ArgModes]) :- 
+	default_func_arg_modes([ArgMode2 | ArgModes]).
 
 %-----------------------------------------------------------------------------%
 %
diff -u compiler/ml_elim_nested.m compiler/ml_elim_nested.m
--- compiler/ml_elim_nested.m
+++ compiler/ml_elim_nested.m
@@ -607,7 +607,7 @@
 :- func ml_pred_label_name(mlds__pred_label) = string.
 
 ml_pred_label_name(pred(PredOrFunc, MaybeDefiningModule, Name, Arity,
-		_CodeModel)) = LabelName :-
+		_CodeModel, _NonDefaultModeFunc)) = LabelName :-
 	( PredOrFunc = predicate, Suffix = "p"
 	; PredOrFunc = function, Suffix = "f"
 	),
diff -u compiler/ml_util.m compiler/ml_util.m
--- compiler/ml_util.m
+++ compiler/ml_util.m
@@ -143,7 +143,7 @@
 	list__member(Defn, Defns),
 	Defn = mlds__defn(Name, _, _, _),
 	Name = function(FuncName, _, _, _), 
-	FuncName = pred(predicate, _, "main", 2, _).
+	FuncName = pred(predicate, _, "main", 2, _, _).
 
 can_optimize_tailcall(Name, Call) :-
 	Call = call(_Signature, FuncRval, MaybeObject, _CallArgs,
diff -u compiler/mlds.m compiler/mlds.m
--- compiler/mlds.m
+++ compiler/mlds.m
@@ -1376,7 +1376,8 @@
 			maybe(mercury_module_name),
 			string,			% name
 			arity,			% arity
-			code_model		% code model
+			code_model,		% code model
+			bool			% non-default mode function
 		)
 			
 	;	special_pred(
diff -u compiler/mlds_to_c.m compiler/mlds_to_c.m
--- compiler/mlds_to_c.m
+++ compiler/mlds_to_c.m
@@ -1337,7 +1337,7 @@
 			%
 			{ Name = function(PredLabel, _, _, _) },
 			{ PredLabel = pred(predicate, no, "main", 2,
-				model_det) }
+				model_det, no) }
 		;
 			%
 			% don't module-qualify base_typeclass_infos
@@ -1370,7 +1370,7 @@
 		%
 		{ QualifiedName = qual(_ModuleName, Name) },
 		{ Name = PredLabel - _ProcId },
-		{ PredLabel = pred(predicate, no, "main", 2, model_det) }
+		{ PredLabel = pred(predicate, no, "main", 2, model_det, no) }
 	->
 		mlds_output_proc_label(Name)
 	;
@@ -1424,7 +1424,7 @@
 :- mode mlds_output_pred_label(in, di, uo) is det.
 
 mlds_output_pred_label(pred(PredOrFunc, MaybeDefiningModule, Name, Arity,
-		_CodeModel)) -->
+		_CodeModel, _NonDefaultModeFunc)) -->
 	( { PredOrFunc = predicate, Suffix = "p" }
 	; { PredOrFunc = function, Suffix = "f" }
 	),
diff -u compiler/mlds_to_il.m compiler/mlds_to_il.m
--- compiler/mlds_to_il.m
+++ compiler/mlds_to_il.m
@@ -329,7 +329,8 @@
 			% If this is main, add the entrypoint, set a
 			% flag, and call the initialization instructions
 			% in the cctor of this module.
-		( { PredLabel = pred(predicate, no, "main", 2, model_det) },
+		( { PredLabel = pred(predicate, no, "main", 2, model_det,
+			no) },
 		  { MaybeSeqNum = no }
 		->
 			{ EntryPoint = [entrypoint] },
@@ -1972,8 +1973,10 @@
 	%
 	% We mangle as follows:
 	%	- Problem:
-	%	  Two preds or funcs with different arities in Mercury end
-	%	  up having the same types and arities in IL.
+	%	  Two preds or funcs with different arities in Mercury
+	%	  end up having the same types and arities in IL, e.g.
+	%	  because one of them takes io__state arguments which
+	%	  get omitted in IL.                                       
 	%
 	%	  To avoid this we append _<arity> to every procedure
 	%	  name.
@@ -1982,12 +1985,19 @@
 	%	  A semidet pred returns its success value, and so has
 	%	  the same return type (bool) as a function.
 	%
-	%	  To avoid this, we mangle all semidet preds and
-	%	  functions to include whether they are a pred or a
-	%	  function using _p or _f.
+	%	  To avoid this, we mangle all semidet predicates
+	%	  to indicate that they are a pred by appending _p.
 	%
 	%	- Problem:
-	%	  A predicate or function with more than one mode
+	%	  A function with modes other than the default (in, in,
+	%	  in = out) may clash with a predicate which has the
+	%	  same types and modes.
+	%
+	%	  To avoid this, we mangle all functions with
+	%	  non-default modes by adding _f to the procedure name.
+	%
+	%	- Problem:
+	%	  A predicate or function with more than one mode.
 	%
 	%	  To avoid this, we mangle all modes > 0 by adding
 	%	  _m<modenum> to the procedure name.
@@ -2008,22 +2018,27 @@
 	% it isn't possible to generate names that conflict with user
 	% names. 
 	%
-predlabel_to_id(pred(PredOrFunc, MaybeModuleName, Name, Arity, CodeModel),
-			ProcId, MaybeSeqNum, Id) :-
+	% XXX I think that it may be possible to have conflicts with
+	% user names in the case where there is a <modulename>. - fjh
+	%
+predlabel_to_id(pred(PredOrFunc, MaybeModuleName, Name, Arity, CodeModel,
+	NonDefaultModeFunc), ProcId, MaybeSeqNum, Id) :-
 		( MaybeModuleName = yes(ModuleName) ->
 			mlds_to_il__sym_name_to_string(ModuleName, MStr),
 			string__format("%s_", [s(MStr)], MaybeModuleStr)
 		;
 			MaybeModuleStr = ""
 		),
-		( CodeModel = model_semi ->
-			( 
-				PredOrFunc = predicate,
-				PredOrFuncStr = "_p" 
-			;
-				PredOrFunc = function,
-				PredOrFuncStr = "_f" 
-			)
+		( 
+			CodeModel = model_semi,
+			PredOrFunc = predicate
+		->
+			PredOrFuncStr = "_p" 
+		;
+			PredOrFunc = function,
+			NonDefaultModeFunc = yes
+		->
+			PredOrFuncStr = "_f" 
 		;
 			PredOrFuncStr = ""
 		),
diff -u compiler/mlds_to_java.m compiler/mlds_to_java.m
--- compiler/mlds_to_java.m
+++ compiler/mlds_to_java.m
@@ -346,7 +346,7 @@
    	 	( 
 			Label = special_pred(PredName, _, _, _) 
 		;
-			Label = pred(_, _, PredName, _, _)
+			Label = pred(_, _, PredName, _, _, _)
 		)
 	->
 		
@@ -1120,7 +1120,7 @@
 :- mode output_pred_label(in, di, uo) is det.
 
 output_pred_label(pred(PredOrFunc, MaybeDefiningModule, Name, Arity,
-		_CodeModel)) -->
+		_CodeModel, _NonDefaultModeFunc)) -->
 	( { PredOrFunc = predicate, Suffix = "p" }
 	; { PredOrFunc = function, Suffix = "f" }
 	),

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
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