[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