for review: bug fix for semidet pragma c_code
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Jan 15 12:18:34 AEDT 1998
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.
More information about the developers
mailing list