for review: bug fix for semidet pragma c_code [repost]
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Jan 16 18:10:00 AEDT 1998
Hi,
Apparently majordomo was down today, so I'm reposting these.
-----Forwarded message from Fergus Henderson <fjh at cs.mu.OZ.AU>-----
Message-ID: <19980115121834.53396 at murlibobo.cs.mu.OZ.AU>
Date: Thu, 15 Jan 1998 12:18:34 +1100
From: Fergus Henderson <fjh at cs.mu.OZ.AU>
To: Mercury Developers <mercury-developers at cs.mu.OZ.AU>
Subject: for review: bug fix for semidet pragma c_code
Zoltan, can you please review this one?
--------------------
Fix a bug where semidet pragma c_codes didn't work in non-gc grades.
compiler/pragma_c_gen.m:
Fix the above-mentioned bug. The problem was that in the following
code fragment
{ <the c code itself> }
#ifndef CONSERVATIVE_GC
restore_registers();
#endif
the C code would assign to SUCCESS_INDICATOR, which is #defined
to `r1', and then the call to restore_registers() would clobber r1.
In the process of fixing the bug, reorganize the code for
generating ordinary (det/semi) pragma_c so that it more closely
matches the layout of the code it generates, and add a few comments.
tests/hard_coded/Mmakefile:
Re-enable the `pragma_import' test which uncovered this bug.
cvs diff compiler/pragma_c_gen.m tests/hard_coded/Mmakefile
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.12
diff -u -r1.12 pragma_c_gen.m
--- pragma_c_gen.m 1998/01/13 10:13:22 1.12
+++ pragma_c_gen.m 1998/01/14 16:16:25
@@ -46,23 +46,29 @@
% must be able to fit into the middle of a procedure, since such
% pragma_c_codes can be inlined. This code is of the following form:
%
-% <save live variables onto the stack> /* see note (1) below */
-% {
+% <save live variables onto the stack> /* see note (1) below */
+% {
% <declaration of one local variable for each arg>
% <assignment of input values from registers to local variables>
% save_registers(); /* see notes (1) and (2) below */
% { <the c code itself> }
+% <for semidet code, check of r1>
% #ifndef CONSERVATIVE_GC
% restore_registers(); /* see notes (1) and (3) below */
% #endif
% <assignment of the output values from local variables to registers>
-% }
+% }
+%
+% In the case of a semidet pragma c_code, the above is followed by
%
-% In the case of a semidet pragma c_code, this is followed by
+% goto skip_label;
+% fail_label:
+% <code to fail>
+% skip_label:
%
-% if (r1) goto label;
-% <code to fail>
-% label:
+% and the <check of r1> is of the form
+%
+% if (!r1) GOTO_LABEL(fail_label);
%
% The code we generate for nondet pragma_c_code assumes that this code is
% the only thing between the procedure prolog and epilog; such pragma_c_codes
@@ -300,13 +306,17 @@
pragma_c_gen__ordinary_pragma_c_code(CodeModel, MayCallMercury,
PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
C_Code, Context, Code) -->
+ %
% First we need to get a list of input and output arguments
+ %
code_info__get_pred_proc_arginfo(PredId, ProcId, ArgInfos),
{ make_c_arg_list(ArgVars, ArgDatas, OrigArgTypes, ArgInfos, Args) },
{ pragma_select_in_args(Args, InArgs) },
{ pragma_select_out_args(Args, OutArgs) },
- { make_pragma_decls(Args, Decls) },
+ %
+ % Generate code to <save live variables on stack>
+ %
( { MayCallMercury = will_not_call_mercury } ->
{ SaveVarsCode = empty }
;
@@ -322,86 +332,141 @@
call_gen__save_variables(OutArgsSet, SaveVarsCode)
),
+ %
+ % Generate the values of input variables.
+ % (NB we need to be careful that the rvals generated here
+ % remain valid below.)
+ %
get_pragma_input_vars(InArgs, InputDescs, InputVarsCode),
+
+ %
+ % For semidet pragma c_code, we have to move anything that is
+ % currently in r1 elsewhere, so that the C code can assign to
+ % SUCCESS_INDICATOR without clobbering anything important.
+ %
( { CodeModel = model_semi } ->
- % We have to clear r1 for C code that gets inlined
- % so that it is safe to assign to SUCCESS_INDICATOR.
- code_info__clear_r1(ShuffleR1_Code),
-
- ( { MayCallMercury = will_not_call_mercury } ->
- []
- ;
- % the C code may call Mercury code which clobbers
- % the regs
- code_info__clear_all_registers
- ),
+ code_info__clear_r1(ShuffleR1_Code)
+ ;
+ { ShuffleR1_Code = empty }
+ ),
- % C code goes here
+ %
+ % Generate <declaration of one local variable for each arg>
+ %
+ { make_pragma_decls(Args, Decls) },
- code_info__get_next_label(SkipLabel),
- code_info__generate_failure(FailCode),
- { TestCode = node([
- if_val(lval(reg(r, 1)), label(SkipLabel)) -
- "Test for success of pragma_c_code"
- ]) },
- { SkipLabelCode = node([
- label(SkipLabel) - ""
- ]) },
- { CheckFailureCode =
- tree(TestCode,
- tree(FailCode,
- SkipLabelCode))
- },
+ %
+ % <assignment of input values from registers to local vars>
+ %
+ { InputComp = pragma_c_inputs(InputDescs) },
- code_info__lock_reg(reg(r, 1)),
- pragma_acquire_regs(OutArgs, Regs),
- code_info__unlock_reg(reg(r, 1))
+ %
+ % save_registers(); /* see notes (1) and (2) above */
+ %
+ { MayCallMercury = will_not_call_mercury ->
+ SaveRegsComp = pragma_c_raw_code("")
;
- { ShuffleR1_Code = empty },
-
- % c code goes here
-
- ( { MayCallMercury = will_not_call_mercury } ->
- []
- ;
- % the C code may call Mercury code which clobbers
- % the regs
- code_info__clear_all_registers
- ),
+ SaveRegsComp = pragma_c_raw_code(
+ "\tsave_registers();\n"
+ )
+ },
- { CheckFailureCode = empty },
+ %
+ % <The C code itself>
+ %
+ { C_Code_Comp = pragma_c_user_code(Context, C_Code) },
- pragma_acquire_regs(OutArgs, Regs)
+ %
+ % <for semidet code, check of r1>
+ %
+ ( { CodeModel = model_semi } ->
+ code_info__get_next_label(FailLabel),
+ { llds_out__get_label(FailLabel, yes, FailLabelStr) },
+ { string__format("\tif (!r1) GOTO_LABEL(%s);\n",
+ [s(FailLabelStr)], CheckR1_String) },
+ { CheckR1_Comp = pragma_c_raw_code(CheckR1_String) },
+ { MaybeFailLabel = yes(FailLabel) }
+ ;
+ { CheckR1_Comp = pragma_c_raw_code("") },
+ { MaybeFailLabel = no }
),
- place_pragma_output_args_in_regs(OutArgs, Regs, OutputDescs),
- { C_Code_Comp = pragma_c_user_code(Context, C_Code) },
+ %
+ % #ifndef CONSERVATIVE_GC
+ % restore_registers(); /* see notes (1) and (3) above */
+ % #endif
+ %
{ MayCallMercury = will_not_call_mercury ->
- WrappedComp = [C_Code_Comp]
+ RestoreRegsComp = pragma_c_raw_code("")
;
- SaveRegsComp = pragma_c_raw_code(
- "\tsave_registers();\n"
- ),
RestoreRegsComp = pragma_c_raw_code(
- "#ifndef CONSERVATIVE_GC\n\trestore_registers();\n#endif\n"
- ),
- WrappedComp = [SaveRegsComp, C_Code_Comp, RestoreRegsComp]
+ "#ifndef CONSERVATIVE_GC\n\trestore_registers();\n#endif\n"
+ )
},
- { InputComp = pragma_c_inputs(InputDescs) },
+
+ %
+ % The C code may have called Mercury code which clobbered the regs,
+ % in which case we need to tell the code_info that they have been
+ % clobbered.
+ %
+ ( { MayCallMercury = will_not_call_mercury } ->
+ []
+ ;
+ code_info__clear_all_registers
+ ),
+
+ %
+ % <assignment of the output values from local variables to registers>
+ %
+ pragma_acquire_regs(OutArgs, Regs),
+ place_pragma_output_args_in_regs(OutArgs, Regs, OutputDescs),
{ OutputComp = pragma_c_outputs(OutputDescs) },
- { list__append([InputComp | WrappedComp], [OutputComp], Components) },
+ %
+ % join all the components of the pragma_c together
+ %
+ { Components = [InputComp, SaveRegsComp, C_Code_Comp,
+ CheckR1_Comp, RestoreRegsComp, OutputComp] },
{ PragmaCCode = node([
- pragma_c(Decls, Components, MayCallMercury, no) -
+ pragma_c(Decls, Components, MayCallMercury, MaybeFailLabel) -
"Pragma C inclusion"
]) },
+ %
+ % for semidet code, we need to insert the failure handling code here:
+ %
+ % goto skip_label;
+ % fail_label:
+ % <code to fail>
+ % skip_label:
+ %
+ ( { MaybeFailLabel = yes(TheFailLabel) } ->
+ code_info__get_next_label(SkipLabel),
+ code_info__generate_failure(FailCode),
+ { GotoSkipLabelCode = node([
+ goto(label(SkipLabel)) - "Skip past failure code"
+ ]) },
+ { SkipLabelCode = node([ label(SkipLabel) - "" ]) },
+ { FailLabelCode = node([ label(TheFailLabel) - "" ]) },
+ { FailureCode =
+ tree(GotoSkipLabelCode,
+ tree(FailLabelCode,
+ tree(FailCode,
+ SkipLabelCode)))
+ }
+ ;
+ { FailureCode = empty }
+ ),
+
+ %
+ % join all code fragments together
+ %
{ Code =
tree(SaveVarsCode,
tree(InputVarsCode,
tree(ShuffleR1_Code,
tree(PragmaCCode,
- CheckFailureCode))))
+ FailureCode))))
}.
%---------------------------------------------------------------------------%
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.6
diff -u -r1.6 Mmakefile
--- Mmakefile 1998/01/14 02:16:28 1.6
+++ Mmakefile 1998/01/14 16:24:08
@@ -70,10 +70,6 @@
MCFLAGS-ho_order = --optimize-higher-order
MCFLAGS-no_fully_strict = --no-fully-strict
-# XXX the `pragma_import' test does not yet work in non-gc grades
-
-GRADEFLAGS-pragma_import = --gc conservative
-
# no_fully_strict is expected to fail (it calls error/1)
# so we need to ignore the exit status (hence the leading `-')
no_fully_strict.out: no_fully_strict
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
-----End of forwarded message-----
-----Forwarded message from Fergus Henderson <fjh at cs.mu.OZ.AU>-----
Message-ID: <19980115153033.58494 at murlibobo.cs.mu.OZ.AU>
Date: Thu, 15 Jan 1998 15:30:33 +1100
From: Fergus Henderson <fjh at cs.mu.OZ.AU>
To: Mercury Developers <mercury-developers at cs.mu.OZ.AU>
Subject: Re: for review: bug fix for semidet pragma c_code
References: <19980115121834.53396 at murlibobo.cs.mu.OZ.AU>
In-Reply-To: <19980115121834.53396 at murlibobo.cs.mu.OZ.AU>; from Fergus Henderson on Thu, Jan 15, 1998 at 12:18:34PM +1100
On 15-Jan-1998, I wrote:
> Zoltan, can you please review this one?
>
> --------------------
>
> Fix a bug where semidet pragma c_codes didn't work in non-gc grades.
More testing revealed that this bug fix happened to trigger another bug.
compiler/dupelim.m:
Fix a bug in dupelim__build_maps: a lambda expression was using
the same variable name (`Label') as the code outside it,
resulting in it accidentally capturing that variable rather
than being a fresh variable.
Index: dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.30
diff -u -u -r1.30 dupelim.m
--- dupelim.m 1998/01/13 10:11:50 1.30
+++ dupelim.m 1998/01/15 04:21:17
@@ -114,8 +114,8 @@
),
AddPragmaReferredLabels = lambda(
[Instr::in, FoldFixed0::in, FoldFixed::out] is det, (
- ( Instr = pragma_c(_, _, _, yes(Label)) - _ ->
- set__insert(FoldFixed0, Label, FoldFixed)
+ ( Instr = pragma_c(_, _, _, yes(PragmaLabel)) - _ ->
+ set__insert(FoldFixed0, PragmaLabel, FoldFixed)
;
FoldFixed = FoldFixed0
)
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
-----End of forwarded message-----
-----Forwarded message from Fergus Henderson <fjh at cs.mu.OZ.AU>-----
Message-ID: <19980115175214.45729 at murlibobo.cs.mu.OZ.AU>
Date: Thu, 15 Jan 1998 17:52:14 +1100
From: Fergus Henderson <fjh at cs.mu.OZ.AU>
To: Mercury Developers <mercury-developers at cs.mu.OZ.AU>
Subject: Re: for review: bug fix for semidet pragma c_code
References: <19980115121834.53396 at murlibobo.cs.mu.OZ.AU> <19980115153033.58494 at murlibobo.cs.mu.OZ.AU>
In-Reply-To: <19980115153033.58494 at murlibobo.cs.mu.OZ.AU>; from Fergus Henderson on Thu, Jan 15, 1998 at 03:30:33PM +1100
On 15-Jan-1998, I wrote:
> On 15-Jan-1998, I wrote:
> >
> > Fix a bug where semidet pragma c_codes didn't work in non-gc grades.
>
> More testing revealed that this bug fix happened to trigger another bug.
... and another one.
compiler/frameopt.m:
Fix a bug in possible_targets/2: the possible targets for
a `pragma_c' instruction include the label, if it has one.
compiler/opt_util.m:
Update the comments for component_can_branch_away/2
to reflect the fact that pragma_c_raw_code components for
semidet pragma c_codes can branch away. Also check for the
special case of an empty string in pragma_c_raw_code.
cvs diff compiler/frameopt.m compiler/opt_util.m
Index: compiler/frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.67
diff -u -r1.67 frameopt.m
--- frameopt.m 1998/01/13 10:12:01 1.67
+++ frameopt.m 1998/01/15 06:40:17
@@ -687,7 +687,14 @@
possible_targets(discard_tickets_to(_), []).
possible_targets(incr_sp(_, _), []).
possible_targets(decr_sp(_), []).
-possible_targets(pragma_c(_, _, _, _), []).
+possible_targets(pragma_c(_, _, _, MaybeLabel), List) :-
+ (
+ MaybeLabel = no,
+ List = []
+ ;
+ MaybeLabel = yes(Label),
+ List = [Label]
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.88
diff -u -r1.88 opt_util.m
--- opt_util.m 1998/01/13 10:13:08 1.88
+++ opt_util.m 1998/01/15 06:45:02
@@ -1012,6 +1012,8 @@
% The input and output components get expanded to straight line code.
% Some of the raw_code components we generate for nondet pragma C codes
% invoke succeed(), which definitely does branch away.
+ % Also the raw_code components for semidet pragma C codes can
+ % branch to a label on failure.
% User-written C code cannot branch away because users do not know
% how to do that. (They can call other functions, but those functions
% will return, so control will still go to the instruction following
@@ -1021,7 +1023,8 @@
opt_util__can_component_branch_away(pragma_c_inputs(_), no).
opt_util__can_component_branch_away(pragma_c_outputs(_), no).
-opt_util__can_component_branch_away(pragma_c_raw_code(_), yes).
+opt_util__can_component_branch_away(pragma_c_raw_code(Code), CanBranchAway) :-
+ ( Code = "" -> CanBranchAway = yes ; CanBranchAway = no ).
opt_util__can_component_branch_away(pragma_c_user_code(_, _), no).
opt_util__can_instr_fall_through(comment(_), yes).
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
-----End of forwarded message-----
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list