[m-dev.] for review: demangling of names introduced by type specialization

Simon Taylor stayl at cs.mu.OZ.AU
Fri Nov 3 19:02:42 AEDT 2000



Estimated hours taken: 2

Implement demangling of predicate names introduced by type
specialization. This still doesn't work when the compiler adds
multiple prefixes to a predicate name.

profiler/demangle.m:
util/mdemangle.c:
	When demangling of a compiler-generated predicate name fails, just
	treat the predicate as an ordinary predicate. This is a temporary
	work-around for the problem of demangling names with multiple
	compiler-generated prefixes.

	Change the printing of names in the profiler to match those generated
	by the compiler (module:'p'/3 becomse `module:p/3').

tests/misc_tests/mdemangle_test.inp:
tests/misc_tests/mdemangle_test.exp:
	Test case.


Index: profiler/demangle.m
===================================================================
RCS file: /home/mercury1/repository/mercury/profiler/demangle.m,v
retrieving revision 1.10
diff -u -u -r1.10 demangle.m
--- profiler/demangle.m	2000/09/18 11:52:25	1.10
+++ profiler/demangle.m	2000/11/03 07:59:14
@@ -1,6 +1,6 @@
 %-----------------------------------------------------------------------------%
 %
-% Copyright (C) 1997-1999 The University of Melbourne.
+% Copyright (C) 1997-2000 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %
@@ -42,6 +42,7 @@
 	--->	(lambda)
 	;	deforestation
 	;	accumulator
+	;	type_spec(string)
 	.
 
 :- type data_category
@@ -210,16 +211,19 @@
 	( { Category0 \= ordinary } ->
 		remove_prefix("_"),
 		remove_maybe_module_prefix(MaybeModule,
-			["IntroducedFrom__", "DeforestationIn__", "AccFrom__"]),
+			["IntroducedFrom__", "DeforestationIn__",
+			"AccFrom__", "TypeSpecOf__"]),
 		{ MaybeModule \= yes("") }
 	;
 		remove_maybe_module_prefix(MaybeModule,
-			["IntroducedFrom__", "DeforestationIn__", "AccFrom__"])
+			["IntroducedFrom__", "DeforestationIn__",
+			"AccFrom__", "TypeSpecOf__"])
 	),
 
 	%
 	% Now we need to look at the pred name and see if it is an
 	% introduced lambda predicate.
+	% XXX handle multiple prefixes
 	%
 
 	=(PredName0),
@@ -228,36 +232,67 @@
 		( 
 			remove_prefix("IntroducedFrom__") 
 		->
-			{ IntroducedPredType = (lambda) }
+			{ IntroducedPredType0 = (lambda) }
 		;
 			remove_prefix("DeforestationIn__")
 		->
-			{ IntroducedPredType = deforestation }
+			{ IntroducedPredType0 = deforestation }
 		;
-			remove_prefix("AccFrom__"),
-			{ IntroducedPredType = accumulator }
+			remove_prefix("AccFrom__")
+		->
+			{ IntroducedPredType0 = accumulator }
+		;
+			remove_prefix("TypeSpecOf__"),
+			{ IntroducedPredType0 = type_spec("") }
 		)
 	->
-		( remove_prefix("pred__") ->
+		(
+			remove_prefix("pred__")
+		->
 			{ LambdaPredOrFunc = "pred" }
-		; remove_prefix("func__") ->
+		;
+			remove_prefix("func__")
+		->
 			{ LambdaPredOrFunc = "func" }
 		;
+			{ IntroducedPredType0 = type_spec(_) },
+			remove_prefix("pred_or_func__")
+		->
+			{ LambdaPredOrFunc = "" }
+		;
 			{ fail }
 		),
-		remove_maybe_pred_name(MPredName),
-		{ MPredName = yes(PredName) },
-		remove_int(Line),
-		remove_prefix("__"),
-		remove_int(Seq),
-		{ Category = introduced(IntroducedPredType, Line,
-			Seq, LambdaPredOrFunc) }
+		(
+			remove_maybe_pred_name(MPredName),
+			{ MPredName = yes(PredName1) },
+			( { IntroducedPredType0 = type_spec(_) } ->
+				remove_type_spec(TypeSpec),
+				{ IntroducedPredType = type_spec(TypeSpec) },
+				{ Seq = 0 },
+				{ Line = 0 }
+			;
+				{ IntroducedPredType = IntroducedPredType0 },
+				remove_int(Line),
+				remove_prefix("__"),
+				remove_int(Seq)
+			)
+		->
+			{ PredName = PredName1 },
+			{ Category = introduced(IntroducedPredType, Line,
+				Seq, LambdaPredOrFunc) }
+		;
+			% If we get here it usually means that there
+			% were multiple prefixes, which aren't dealt
+			% with properly yet. Just treat it as an
+			% ordinary name for now.
+			{ Category = ordinary },
+			{ PredName = PredName0 }
+		)
 	;
 		{ Category = Category0 },
 		{ PredName = PredName0 }
 	),
 
-
 	%
 	% Now, finally, we can construct the demangled symbol name
 	%
@@ -276,41 +311,49 @@
 	{ format_maybe_module(MaybeModule, PredName, QualifiedName) },
 	{
 		Category = unify,
-		string__format("unification predicate for type %s/%d mode %d",
+		string__format(
+			"unification predicate for type `%s/%d' mode %d",
 			[s(QualifiedName), i(Arity), i(ModeNum)],
 			MainPart)
 	;
 		Category = compare,
-		string__format("compare/3 predicate for type %s/%d",
+		string__format("compare/3 predicate for type `%s/%d'",
 			[s(QualifiedName), i(Arity)],
 			MainPart)
 	;
 		Category = index,
-		string__format("index/2 predicate for type %s/%d",
+		string__format("index/2 predicate for type `%s/%d'",
 			[s(QualifiedName), i(Arity)],
 			MainPart)
 	;
 		Category = ordinary,
-		string__format("%s %s/%d mode %d",
+		string__format("%s `%s/%d' mode %d",
 			[s(PredOrFunc), s(QualifiedName), i(Arity), i(ModeNum)],
 			MainPart)
 	;
 		Category = introduced(Type, Line, Seq, IntroPredOrFunc),
 		(
 			Type = (lambda),
-			string__format("%s goal (#%d) from %s line %d",
+			string__format("%s goal (#%d) from `%s' line %d",
 				[s(IntroPredOrFunc), i(Seq), s(QualifiedName),
 				i(Line)], MainPart)
 		;
 			Type = deforestation,
 			string__format(
-				"deforestation procedure (#%d) from %s line %d",
+			"deforestation procedure (#%d) from `%s' line %d",
 				[i(Seq), s(QualifiedName), i(Line)], MainPart)
 		;
 			Type = accumulator,
 			string__format(
-				"accumulator procedure from %s line %d",
+				"accumulator procedure from `%s' line %d",
 				[s(QualifiedName), i(Line)], MainPart)
+		;
+			Type = type_spec(TypeSpec),
+			string__format(
+				"%s `%s/%d' mode %d (type specialized %s)",
+				[s(PredOrFunc), s(QualifiedName),
+				i(Arity), i(ModeNum), s(TypeSpec)],
+				MainPart)
 		)
 	},
 	[MainPart],
@@ -379,26 +422,26 @@
 :- mode format_data(in, in, in, in, out) is semidet.
 format_data(info, MaybeModule, Name, Arity, Result) :-
 	( MaybeModule = yes(Module) ->
-		string__format("<base type_info for type '%s:%s'/%d>",
+		string__format("<type_ctor_info for type `%s:%s/%d'>",
 			[s(Module), s(Name), i(Arity)], Result)
 	;
-		string__format("<base type_info for type '%s'/%d>",
+		string__format("<type_ctor_info for type `%s/%d'>",
 			[s(Name), i(Arity)], Result)
 	).
 format_data(layout, MaybeModule, Name, Arity, Result) :-
 	( MaybeModule = yes(Module) ->
-		string__format("<type layout for type '%s:%s'/%d>",
+		string__format("<type_ctor_layout for type `%s:%s/%d'>",
 			[s(Module), s(Name), i(Arity)], Result)
 	;
-		string__format("<type layout for type '%s'/%d>",
+		string__format("<type_ctor_layout for type `%s/%d'>",
 			[s(Name), i(Arity)], Result)
 	).
 format_data(functors, MaybeModule, Name, Arity, Result) :-
 	( MaybeModule = yes(Module) ->
-		string__format("<type functors for type '%s:%s'/%d>",
+		string__format("<type_ctor_functors for type `%s:%s/%d'>",
 			[s(Module), s(Name), i(Arity)], Result)
 	;
-		string__format("<type functors for type '%s'/%d>",
+		string__format("<type_ctor_functors for type `%s/%d'>",
 			[s(Name), i(Arity)], Result)
 	).
 format_data(common, MaybeModule, _Name, Arity, Result) :-
@@ -598,6 +641,39 @@
 		MaybePredName = no
 	).
 
+:- pred remove_type_spec(string, string, string) is det.
+:- mode remove_type_spec(out, in, out) is semidet.
+
+remove_type_spec(TypeSpec, String0, String) :-
+	string__length(String0, Length),
+	Length > 2,
+	string__unsafe_index(String0, 0, '['),
+	NumBrackets = 0,
+	find_matching_close_bracket(NumBrackets, Length,
+		String0, 1, Index),
+	string__split(String0, Index + 1, TypeSpec, String).
+
+:- pred find_matching_close_bracket(int, int, string, int, int). 
+:- mode find_matching_close_bracket(in, in, in, in, out) is semidet.
+
+find_matching_close_bracket(NumBrackets0, Length, String, Index0, Index) :-
+	Index0 < Length,
+	string__unsafe_index(String, Index0, Char),
+	( Char = ']', NumBrackets0 = 0 ->
+		Index = Index0
+	;
+		% Handle matching brackets in type names.
+		( Char = '[' ->
+			NumBrackets = NumBrackets0 + 1
+		; Char = ']' ->
+			NumBrackets = NumBrackets0 - 1
+		;
+			NumBrackets = NumBrackets0
+		),
+		find_matching_close_bracket(NumBrackets, Length,
+			String, Index0 + 1, Index)
+	).
+
 :- pred maybe_remove_prefix(string, string, string).
 :- mode maybe_remove_prefix(in, in, out) is det.
 maybe_remove_prefix(Prefix) -->
@@ -630,9 +706,9 @@
 :- pred format_maybe_module(maybe(string), string, string).
 :- mode format_maybe_module(in, in, out) is det.
 format_maybe_module(no, Name, QualifiedName) :-
-	string__format("'%s'", [s(Name)], QualifiedName).
+	string__format("%s", [s(Name)], QualifiedName).
 format_maybe_module(yes(Module), Name, QualifiedName) :-
-	string__format("%s:'%s'", [s(Module), s(Name)], QualifiedName).
+	string__format("%s:%s", [s(Module), s(Name)], QualifiedName).
 
 :- pred remove_trailing_int(int, string, string).
 :- mode remove_trailing_int(out, in, out) is semidet.
Index: util/mdemangle.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mdemangle.c,v
retrieving revision 1.37
diff -u -u -r1.37 mdemangle.c
--- util/mdemangle.c	2000/09/18 11:53:19	1.37
+++ util/mdemangle.c	2000/11/03 07:39:11
@@ -37,6 +37,7 @@
 		int sizeof_suffix, int *mode_num2);
 static char *fix_mangled_ascii(char *str, char **end);
 static bool fix_mangled_special_case(char *str, char **end);
+static bool find_double_underscore(char **str, char *end);
 static bool cut_at_double_underscore(char **str, char *end);
 static bool cut_trailing_integer(char *str, char **end, int *num);
 static bool cut_trailing_underscore_integer(char *str, char **end, int *num);
@@ -155,8 +156,10 @@
 	static const char introduced[]  = "IntroducedFrom__";
 	static const char deforestation[]  = "DeforestationIn__";
 	static const char accumulator[]  = "AccFrom__";
+	static const char type_spec[]  = "TypeSpecOf__";
 	static const char pred[]  = "pred__";
 	static const char func[]  = "func__";
+	static const char porf[]  = "pred_or_func__";
 
 	static const char ua_suffix[] = "__ua"; /* added by unused_args.m */
 	static const char ua_suffix2[] = "__uab"; /* added by unused_args.m */
@@ -178,6 +181,7 @@
 		introduced,
 		deforestation,
 		accumulator,
+		type_spec,
 		NULL
 	};
 
@@ -206,19 +210,22 @@
 	bool unused_args = FALSE; /* does this proc have any unused arguments */
 	bool higher_order = FALSE; /* has this proc been specialized */
 	int internal = -1;
+	char *name_before_prefixes = NULL;
 	int lambda_line = 0;
 	int lambda_seq_number = 0;
 	char *lambda_pred_name = NULL;
+	char *end_of_lambda_pred_name = NULL;
 	const char *lambda_kind = NULL;
 	enum { ORDINARY, UNIFY, COMPARE, INDEX,
-		LAMBDA, DEFORESTATION, ACCUMULATOR }
+		LAMBDA, DEFORESTATION, ACCUMULATOR, TYPE_SPEC }
 		category;
 	enum { COMMON, INFO, LAYOUT, FUNCTORS } data_category;
 	const char * class_name;
 	int class_arity;
 	char class_arg_buf[MAX_SYMBOL_LENGTH];
 	int class_arg_num;
-	const char* class_arg;
+	const char * class_arg;
+	const char * type_spec_sub;
 
 	/*
 	** copy orig_name to a local buffer which we can modify,
@@ -404,7 +411,12 @@
 
 	/*
 	** look for "IntroducedFrom" or "DeforestationIn" or "AccFrom"
+	** of "TypeSpecOf"
+	** XXX This don't yet handle multiple prefixes. If we get an
+	** error after this point, just treat predicate name as an
+	** ordinary predicate.
 	*/
+	name_before_prefixes = start;
 	if (category == ORDINARY) {
 		if (strip_prefix(&start, introduced)) {
 			category = LAMBDA;
@@ -412,36 +424,98 @@
 			category = DEFORESTATION;
 		} else if (strip_prefix(&start, accumulator)) {
 			category = ACCUMULATOR;
+		} else if (strip_prefix(&start, type_spec)) {
+			category = TYPE_SPEC;
 		}
 	}
 
 	if (category == LAMBDA || category == DEFORESTATION || 
-			category == ACCUMULATOR) 
+			category == ACCUMULATOR || category == TYPE_SPEC) 
 	{
 		if (strip_prefix(&start, pred)) {
 			lambda_kind = "pred";
 		} else if (strip_prefix(&start, func)) {
 			lambda_kind = "func";
+		} else if (category == TYPE_SPEC
+				&& strip_prefix(&start, porf))
+		{
+			lambda_kind = "";
 		} else {
 			goto wrong_format;
 		}
 		lambda_pred_name = start;
-		if (!cut_at_double_underscore(&start, end)) {
-			goto wrong_format;
-		}
-		lambda_line = 0;
-		while (start < end && MR_isdigit(*start)) {
-			lambda_line = lambda_line * 10 + (*start - '0');
-			start++;
-		}
-		if (!cut_at_double_underscore(&start, end)) {
-			goto wrong_format;
+		if (!find_double_underscore(&start, end)) {
+			category = ORDINARY;
+			start = name_before_prefixes;
+		} else {
+			end_of_lambda_pred_name = start;
+			start += 2;
 		}
-		lambda_seq_number = 0;
-		while (start < end && MR_isdigit(*start)) {
-			lambda_seq_number = lambda_seq_number * 10 +
-				(*start - '0');
-			start++;
+		if (category == TYPE_SPEC) {
+			if (start < end && *start == '[') {
+				int nest_level = 1;
+
+				type_spec_sub = start;
+				start++;		
+				/*
+				** Handle matched brackets in type names.
+				*/
+				while (start < end) {
+					if (*start == '[') {
+						nest_level++;
+					}
+					if (*start == ']') {
+						nest_level--;
+					}
+					if (nest_level == 0) {
+						*(start + 1) = '\0';
+						break;
+					}
+					start++;
+				} 
+				if (nest_level != 0) {
+					category = ORDINARY;
+					start = name_before_prefixes;
+				} else {
+					*end_of_lambda_pred_name = '\0';
+					start = lambda_pred_name;
+				}
+			} else {	
+				category = ORDINARY;
+				start = name_before_prefixes;
+			}
+		} else if (category != ORDINARY) {
+			lambda_line = 0;
+
+			if (start >= end || !MR_isdigit(*start)) {
+				category == ORDINARY;
+				start = name_before_prefixes;
+			}
+
+			while (start < end && MR_isdigit(*start)) {
+				lambda_line = lambda_line * 10 +
+					(*start - '0');
+				start++;
+			}
+			if (strip_prefix(&start, "__")) {
+
+			    if (start < end && MR_isdigit(*start)) {
+				lambda_seq_number = 0;
+				while (start < end && MR_isdigit(*start)) {
+					lambda_seq_number =
+						lambda_seq_number * 10 +
+						(*start - '0');
+					start++;
+				}
+				*end_of_lambda_pred_name = '\0';
+			    } else {
+				category == ORDINARY;
+				start = name_before_prefixes;
+			    }
+			} else {
+				category = ORDINARY;
+				start = name_before_prefixes;
+			}
 		}
 	}
 
@@ -476,6 +550,7 @@
 			lambda_seq_number, lambda_pred_name,
 			module, lambda_line);
 		break;
+	case TYPE_SPEC:
 	default:
 		if (*module == '\0') {
 			printf("%s '%s'/%d mode %d",
@@ -485,6 +560,9 @@
 				pred_or_func, module, start, arity, mode_num);
 		}
 	}
+	if (category == TYPE_SPEC) {
+		printf(" (type specialized %s)", type_spec_sub);	
+	}
 	if (higher_order) {
 		printf(" (specialized)");
 	}
@@ -805,6 +883,22 @@
 static bool
 cut_at_double_underscore(char **start, char *end) 
 {
+	if (! find_double_underscore(start, end)) {
+		return FALSE;
+	}
+
+	**start = '\0';
+	*start = *start + 2;
+	return TRUE;
+}
+
+	/*
+	** Scan for `__' and return a pointer to the first `_'.
+	** Returns TRUE if `__' was found, FALSE otherwise.
+	*/
+static bool
+find_double_underscore(char **start, char *end) 
+{
 	char *str = *start;
 
 	while (*str != '_' || *(str + 1) != '_') {
@@ -814,8 +908,7 @@
 		str++;
 	}
 
-	*str = '\0';
-	*start = str + 2;
+	*start = str;
 	return TRUE;
 }
 
Index: tests/misc_tests/mdemangle_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/misc_tests/mdemangle_test.exp,v
retrieving revision 1.11
diff -u -u -r1.11 mdemangle_test.exp
--- tests/misc_tests/mdemangle_test.exp	1999/03/22 08:09:33	1.11
+++ tests/misc_tests/mdemangle_test.exp	2000/11/03 07:55:00
@@ -96,6 +96,15 @@
 <deforestation procedure (#4) from 'collect_vars' in module 'lp' line 153>
 <deforestation procedure (#4) from 'collect_vars' in module 'lp' line 153>
 
+	procedure introduced by type specialization
+<function 'sparse_bitset:list_to_set'/1 mode 0 (type specialized [T = var(V_2)])>
+<function 'sparse_bitset:list_to_set'/1 mode 0 (type specialized [T = var(V_2)])>
+
+	type specialization and deforestion
+	XXX this needs to be fixed
+<predicate 'doubleapp_impl:DeforestationIn__pred__TypeSpecOf__pred_or_func__double_app__[T = int]__21__0'/5 mode 0 (minus unused args)>
+<predicate 'doubleapp_impl:DeforestationIn__pred__TypeSpecOf__pred_or_func__double_app__[T = int]__21__0'/5 mode 0 (minus unused args)>
+
 	A realistic test
 ml -s asm_fast.gc.tr --no-demangle -o interpreter interpreter_init.o \
 interpreter.o -lcfloat_lib 
Index: tests/misc_tests/mdemangle_test.inp
===================================================================
RCS file: /home/mercury1/repository/tests/misc_tests/mdemangle_test.inp,v
retrieving revision 1.12
diff -u -u -r1.12 mdemangle_test.inp
--- tests/misc_tests/mdemangle_test.inp	1999/03/22 08:09:33	1.12
+++ tests/misc_tests/mdemangle_test.inp	2000/11/03 07:52:27
@@ -96,6 +96,15 @@
 mercury__lp__DeforestationIn__pred__collect_vars__153__4_3_0
 <deforestation procedure (#4) from 'collect_vars' in module 'lp' line 153>
 
+	procedure introduced by type specialization
+mercury__fn__f_115_112_97_114_115_101_95_98_105_116_115_101_116_95_95_84_121_112_101_83_112_101_99_79_102_95_95_112_114_101_100_95_111_114_95_102_117_110_99_95_95_108_105_115_116_95_116_111_95_115_101_116_95_95_91_84_32_61_32_118_97_114_40_86_95_50_41_93_1_0
+<function 'sparse_bitset:list_to_set'/1 mode 0 (type specialized [T = var(V_2)])>
+
+	type specialization and deforestion
+	XXX this needs to be fixed
+mercury__f_100_111_117_98_108_101_97_112_112_95_105_109_112_108_95_95_68_101_102_111_114_101_115_116_97_116_105_111_110_73_110_95_95_112_114_101_100_95_95_84_121_112_101_83_112_101_99_79_102_95_95_112_114_101_100_95_111_114_95_102_117_110_99_95_95_100_111_117_98_108_101_95_97_112_112_95_95_91_84_32_61_32_105_110_116_93_95_95_50_49_95_95_48_95_95_117_97_48_5_0
+<predicate 'doubleapp_impl:DeforestationIn__pred__TypeSpecOf__pred_or_func__double_app__[T = int]__21__0'/5 mode 0 (minus unused args)>
+
 	A realistic test
 ml -s asm_fast.gc.tr --no-demangle -o interpreter interpreter_init.o \
 interpreter.o -lcfloat_lib 
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list