for review: fix for inlining of polymorphic procedures
Simon Taylor
stayl at cs.mu.OZ.AU
Thu Feb 19 12:15:11 AEDT 1998
Hi Fergus,
Could you please review this.
Simon.
Estimated hours taken: 2
Fix a bug in the optimization where polymorphism.m passes a
base_type_info in place of a type_info for non-polymorphic types.
The type of the variable was `base_type_info' not `type_info'.
This caused inlining.m to be unable to compute a type substitution,
and code_util__cons_id_to_tag aborted on an unsubstituted type
variable.
compiler/polymorphism.m
Set the type of `base_type_info's passed where a `type_info'
is expected to `type_info'.
compiler/common.m
Don't do common structure elimination on structures
which are of different types, since that could cause
similar bugs.
tests/valid/inlining_bug.m
Regression test.
Index: common.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/common.m,v
retrieving revision 1.47
diff -u -r1.47 common.m
--- common.m 1998/01/23 12:56:21 1.47
+++ common.m 1998/02/19 01:11:43
@@ -250,27 +250,45 @@
%---------------------------------------------------------------------------%
+ % /*
% Two structures have compatible representations if the top
% level of their types are unifiable. % For example, if we have
%
- % :- type maybe_err(T) --> ok(T) ; err(string).
+ % :- type maybe_err(T) --> ok(T) ; err(string).
%
- % :- pred p(maybe_err(foo)::in, maybe_err(bar)::out) is semidet.
- % p(err(X), err(X)).
+ % :- pred p(maybe_err(foo)::in, maybe_err(bar)::out) is semidet.
+ % p(err(X), err(X)).
%
% then we want to reuse the `err(X)' in the first arg rather than
% constructing a new copy of it for the second arg.
% The two occurrences of `err(X)' have types `maybe_err(int)'
% and `maybe(float)', but we know that they have the same
% representation.
+ % */
+ %
+ % We don't do this any more because it leaves the HLDS ill-typed.
+ % Specifically inlining can't compute type substitutions when the
+ % types of the arguments to a call don't match the types of the
+ % arguments. Now we only consider two types compatible if they are
+ % exactly the same. -stayl
:- pred common__compatible_types(type, type).
:- mode common__compatible_types(in, in) is semidet.
+common__compatible_types(term__variable(Var), term__variable(Var)).
common__compatible_types(Type1, Type2) :-
- type_to_type_id(Type1, TypeId1, _),
- type_to_type_id(Type2, TypeId2, _),
- TypeId1 = TypeId2.
+ type_to_type_id(Type1, TypeId1, Args1),
+ type_to_type_id(Type2, TypeId2, Args2),
+ TypeId1 = TypeId2,
+ common__compatible_type_lists(Args1, Args2).
+
+:- pred common__compatible_type_lists(list(type), list(type)).
+:- mode common__compatible_type_lists(in, in) is semidet.
+
+common__compatible_type_lists([], []).
+common__compatible_type_lists([Type1 | Types1], [Type2 | Types2]) :-
+ common__compatible_types(Type1, Type2),
+ common__compatible_type_lists(Types1, Types2).
%---------------------------------------------------------------------------%
Index: polymorphism.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/polymorphism.m,v
retrieving revision 1.128
diff -u -r1.128 polymorphism.m
--- polymorphism.m 1998/02/15 06:48:35 1.128
+++ polymorphism.m 1998/02/19 00:29:33
@@ -1731,8 +1731,16 @@
IsHigherOrder = no
->
Var = BaseVar,
+
+ % Since this base_type_info is pretending to be
+ % a type_info, we need to adjust its type.
+ % Since base_type_info_const cons_ids are handled
+ % specially, this should not cause problems.
+ construct_type(qualified("mercury_builtin", "type_info") - 1,
+ [Type], NewBaseVarType),
+ map__det_update(VarTypes0, BaseVar, NewBaseVarType, VarTypes),
+
VarSet = VarSet0,
- VarTypes = VarTypes0,
ExtraGoals = ExtraGoals0
;
% Unfortunately, if we have higher order terms, we
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/valid/Mmakefile,v
retrieving revision 1.10
diff -u -r1.10 Mmakefile
--- Mmakefile 1998/02/09 00:44:42 1.10
+++ Mmakefile 1998/02/19 00:43:23
@@ -40,6 +40,7 @@
higher_order_implied_mode.m \
ho_inst.m \
ho_func_call.m \
+ inlining_bug.m \
inhibit_warn_test.m \
implied_mode.m \
indexing.m \
%
% Regression test for an abort in code generation.
% When the actual type for a polymorphic argument is non-polymorphic,
% only the base_type_info is passed, avoiding the construction of
% a type_info. The problem was that the type of the type_info argument
% was being set to `mercury_builtin:base_type_info' rather than
% `type_info'. In the code to compute the type substitution in inlining,
% type_list_subsumes failed on the argument types, and no substitution
% was produced. code_util__cons_id_to_tag then aborted when asked to
% find the tag for a constructor of a variable type.
%
:- module inlining_bug.
:- interface.
:- pred calling_pred(int::in) is semidet.
:- implementation.
:- import_module int, list.
:- type my_pair(A) ---> pair(A, A).
calling_pred(_) :-
Plus1 = lambda([Int0::in, IntPair::out] is det,
IntPair = pair(Int0, Int0)),
called_pred(Plus1, [1,2,3], [X | Ys]),
X = pair(2, 2),
Ys = [pair(3, 3), pair(4, 4)].
:- pred called_pred(pred(T, U), list(T), list(U)) is det.
:- mode called_pred(pred(in, out) is det, in, out) is semidet.
:- pragma inline(called_pred/3).
called_pred(P, [A | As], [B | Bs]) :-
call(P, A, B),
list__map(P, As, Bs).
More information about the developers
mailing list