diff: fix for bug with polymorphic pragma c_code inlining
Fergus Henderson
fjh at murlibobo.cs.mu.OZ.AU
Tue May 6 15:44:09 AEST 1997
Fix a bug in inlining of polymorphic pragma c_code procedures.
(The previous fix was not quite complete.)
compiler/pragma_c_gen.m:
Use the original argument types field for the pragma variable
type conversions, rather than looking up the actual types of the
arguments. (In the previous change, I fixed the type declarations
for the pragma variables, but forgot to fix the assignments
to and from those variables.)
Index: pragma_c_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.7
diff -u -r1.7 pragma_c_gen.m
--- pragma_c_gen.m 1997/05/05 11:17:25 1.7
+++ pragma_c_gen.m 1997/05/06 04:38:36
@@ -88,13 +88,13 @@
% there is nothing that needs restoring.
pragma_c_gen__generate_pragma_c_code(CodeModel, C_Code, MayCallMercury,
- PredId, ProcId, Args, Names, OrigArgTypes, _GoalInfo, Code) -->
+ PredId, ProcId, ArgVars, Names, OrigArgTypes, _GoalInfo,
+ Code) -->
% First we need to get a list of input and output arguments
- code_info__get_pred_proc_arginfo(PredId, ProcId, ArgInfo),
- { make_c_arg_list(Args, Names, ArgNames) },
- { assoc_list__from_corresponding_lists(ArgNames, ArgInfo, ArgModes) },
- { pragma_select_in_args(ArgModes, InArgs) },
- { pragma_select_out_args(ArgModes, OutArgs) },
+ code_info__get_pred_proc_arginfo(PredId, ProcId, ArgInfos),
+ { make_c_arg_list(ArgVars, Names, OrigArgTypes, ArgInfos, Args) },
+ { pragma_select_in_args(Args, InArgs) },
+ { pragma_select_out_args(Args, OutArgs) },
( { MayCallMercury = will_not_call_mercury } ->
{ SaveVarsCode = empty }
@@ -111,7 +111,7 @@
call_gen__save_variables(OutArgsSet, SaveVarsCode)
),
- { make_pragma_decls(ArgNames, OrigArgTypes, Decls) },
+ { make_pragma_decls(Args, Decls) },
get_pragma_input_vars(InArgs, Inputs, InputVarsCode),
( { CodeModel = model_semi } ->
% We have to clear r1 for C code that gets inlined
@@ -195,49 +195,55 @@
%---------------------------------------------------------------------------%
-:- type c_arg ---> c_arg(var, maybe(string)).
+:- type c_arg
+ ---> c_arg(
+ var,
+ maybe(string), % name
+ type, % original type before
+ % inlining/specialization
+ % (the actual type may be an instance
+ % of this type, if this type is
+ % polymorphic).
+ arg_info
+ ).
:- pred make_c_arg_list(list(var)::in, list(maybe(string))::in,
- list(c_arg)::out) is det.
+ list(type)::in, list(arg_info)::in, list(c_arg)::out) is det.
-make_c_arg_list(Vars, Names, ArgNames) :-
- make_c_arg_list_2(Vars, Names, [], ArgNames0),
- list__reverse(ArgNames0, ArgNames).
-
-:- pred make_c_arg_list_2(list(var)::in, list(maybe(string))::in,
- list(c_arg)::in, list(c_arg)::out) is det.
-
-make_c_arg_list_2([], [], ArgNames, ArgNames).
-make_c_arg_list_2([Var | Vars], [Name | Names], ArgNames0, ArgNames) :-
- make_c_arg_list_2(Vars, Names, [c_arg(Var, Name) | ArgNames0],
- ArgNames).
-
-make_c_arg_list_2([], [_ | _], _, _) :-
- error("pragma_c_gen:make_c_arg_list_2 - length mismatch").
-make_c_arg_list_2([_ | _], [], _, _) :-
- error("pragma_c_gen:make_c_arg_list_2 - length mismatch").
+make_c_arg_list(Vars, Names, Types, ArgInfos, ArgList) :-
+ ( Vars = [], Names = [], Types = [], ArgInfos = [] ->
+ ArgList = []
+ ; Vars = [V|Vs], Names = [N|Ns], Types = [T|Ts], ArgInfos = [A|As] ->
+ Arg = c_arg(V, N, T, A),
+ make_c_arg_list(Vs, Ns, Ts, As, Args),
+ ArgList = [Arg | Args]
+ ;
+ error("pragma_c_gen:make_c_arg_list - length mismatch")
+ ).
:- pred get_c_arg_list_vars(list(c_arg)::in, list(var)::out) is det.
get_c_arg_list_vars([], []).
-get_c_arg_list_vars([c_arg(Var, _) | Args], [Var | Vars1]) :-
- get_c_arg_list_vars(Args, Vars1).
+get_c_arg_list_vars([Arg | Args], [Var | Vars]) :-
+ Arg = c_arg(Var, _, _, _),
+ get_c_arg_list_vars(Args, Vars).
%---------------------------------------------------------------------------%
% pragma_select_out_args returns the list of variables which are outputs for
% a procedure
-:- pred pragma_select_out_args(assoc_list(c_arg, arg_info)::in,
- list(c_arg)::out) is det.
+:- pred pragma_select_out_args(list(c_arg)::in, list(c_arg)::out) is det.
pragma_select_out_args([], []).
-pragma_select_out_args([V - arg_info(_Loc, Mode) | Rest], Out) :-
+pragma_select_out_args([Arg | Rest], Out) :-
pragma_select_out_args(Rest, Out0),
+ Arg = c_arg(_, _, _, ArgInfo),
+ ArgInfo = arg_info(_Loc, Mode),
(
Mode = top_out
->
- Out = [V | Out0]
+ Out = [Arg | Out0]
;
Out = Out0
).
@@ -245,16 +251,17 @@
% pragma_select_in_args returns the list of variables which are inputs for
% a procedure
-:- pred pragma_select_in_args(assoc_list(c_arg, arg_info)::in,
- list(c_arg)::out) is det.
+:- pred pragma_select_in_args(list(c_arg)::in, list(c_arg)::out) is det.
pragma_select_in_args([], []).
-pragma_select_in_args([V - arg_info(_Loc, Mode) | Rest], In) :-
+pragma_select_in_args([Arg | Rest], In) :-
pragma_select_in_args(Rest, In0),
+ Arg = c_arg(_, _, _, ArgInfo),
+ ArgInfo = arg_info(_Loc, Mode),
(
Mode = top_in
->
- In = [V | In0]
+ In = [Arg | In0]
;
In = In0
).
@@ -265,23 +272,20 @@
% data structure in the llds. It is essentially a list of pairs of type and
% variable name, so that declarations of the form "Type Name;" can be made.
-:- pred make_pragma_decls(list(c_arg)::in, list(type)::in,
- list(pragma_c_decl)::out) is det.
+:- pred make_pragma_decls(list(c_arg)::in, list(pragma_c_decl)::out) is det.
-make_pragma_decls([], [], []).
-make_pragma_decls([c_arg(_Arg, ArgName) | ArgNames], [OrigType | OrigTypes],
- Decls) :-
+make_pragma_decls([], []).
+make_pragma_decls([Arg | Args], Decls) :-
+ Arg = c_arg(_Var, ArgName, OrigType, _ArgInfo),
( ArgName = yes(Name) ->
Decl = pragma_c_decl(OrigType, Name),
- Decls = [Decl | Decls1],
- make_pragma_decls(ArgNames, OrigTypes, Decls1)
+ make_pragma_decls(Args, Decls1),
+ Decls = [Decl | Decls1]
;
% if the variable doesn't occur in the ArgNames list,
% it can't be used, so we just ignore it
- make_pragma_decls(ArgNames, OrigTypes, Decls)
+ make_pragma_decls(Args, Decls)
).
-make_pragma_decls([_|_], [], _) :- error("make_pragma_decls: length mismatch").
-make_pragma_decls([], [_|_], _) :- error("make_pragma_decls: length mismatch").
%---------------------------------------------------------------------------%
@@ -290,17 +294,17 @@
% and the corresponding rvals assigned to those (C) variables.
:- pred get_pragma_input_vars(list(c_arg)::in, list(pragma_c_input)::out,
- code_tree::out, code_info::in, code_info::out) is det.
+ code_tree::out, code_info::in, code_info::out) is det.
get_pragma_input_vars([], [], empty) --> [].
-get_pragma_input_vars([c_arg(Arg, MaybeName) | Args], Inputs, Code) -->
+get_pragma_input_vars([Arg | Args], Inputs, Code) -->
+ { Arg = c_arg(Var, MaybeName, Type, _ArgInfo) },
( { MaybeName = yes(Name) } ->
- code_info__variable_type(Arg, Type),
- code_info__produce_variable(Arg, Code0, Rval),
+ code_info__produce_variable(Var, Code0, Rval),
{ Input = pragma_c_input(Name, Type, Rval) },
+ get_pragma_input_vars(Args, Inputs1, Code1),
{ Inputs = [Input | Inputs1] },
- { Code = tree(Code0, Code1) },
- get_pragma_input_vars(Args, Inputs1, Code1)
+ { Code = tree(Code0, Code1) }
;
% if the variable doesn't occur in the ArgNames list,
% it can't be used, so we just ignore it
@@ -310,15 +314,16 @@
%---------------------------------------------------------------------------%
% pragma_acquire_regs acquires a list of registers in which to place each
-% of the given variables.
+% of the given arguments.
:- pred pragma_acquire_regs(list(c_arg)::in, list(lval)::out,
code_info::in, code_info::out) is det.
pragma_acquire_regs([], []) --> [].
-pragma_acquire_regs([c_arg(V, _) | Vars], [Reg | Regs]) -->
- code_info__acquire_reg_for_var(V, Reg),
- pragma_acquire_regs(Vars, Regs).
+pragma_acquire_regs([Arg | Args], [Reg | Regs]) -->
+ { Arg = c_arg(Var, _, _, _) },
+ code_info__acquire_reg_for_var(Var, Reg),
+ pragma_acquire_regs(Args, Regs).
%---------------------------------------------------------------------------%
@@ -330,20 +335,21 @@
list(pragma_c_output)::out, code_info::in, code_info::out) is det.
place_pragma_output_args_in_regs([], [], []) --> [].
-place_pragma_output_args_in_regs([_X | _Xs], [], []) -->
- { error("place_pragma_output_args_in_regs: list length mismatch") }.
-place_pragma_output_args_in_regs([], [_X | _Xs], []) -->
- { error("place_pragma_output_args_in_regs: list length mismatch") }.
-place_pragma_output_args_in_regs([Arg | Args], [Reg | Regs], [O | Outputs]) -->
- ( { Arg = c_arg(A, yes(Name)) } ->
- code_info__variable_type(A, Type),
- code_info__release_reg(Reg),
- code_info__set_var_location(A, Reg),
- { O = pragma_c_output(Reg, Type, Name) },
- place_pragma_output_args_in_regs(Args, Regs, Outputs)
+place_pragma_output_args_in_regs([Arg | Args], [Reg | Regs],
+ [Output | Outputs]) -->
+ { Arg = c_arg(Var, MaybeName, OrigType, _ArgInfo) },
+ code_info__release_reg(Reg),
+ code_info__set_var_location(Var, Reg),
+ ( { MaybeName = yes(Name) } ->
+ { Output = pragma_c_output(Reg, OrigType, Name) }
;
- { error("place_pragma_output_args_in_regs") }
- ).
+ { error("place_pragma_output_args_in_regs: unnamed arg") }
+ ),
+ place_pragma_output_args_in_regs(Args, Regs, Outputs).
+place_pragma_output_args_in_regs([_|_], [], _) -->
+ { error("place_pragma_output_args_in_regs: length mismatch") }.
+place_pragma_output_args_in_regs([], [_|_], _) -->
+ { error("place_pragma_output_args_in_regs: length mismatch") }.
%---------------------------------------------------------------------------%
More information about the developers
mailing list