Discussion:
[m-dev.] questions about null vs 0 in argument packing
Zoltan Somogyi
2018-03-04 05:06:12 UTC
Permalink
I have questions about the behavior of argument packing
with respect to NULL pointers. It seems to me that the MLDS
code generator is transforming mlconst_nulls into mlconst_int(0)s
almost randomly, and wondering why this is not a problem
on the C# and Java backends. (I don't expect this to be a problem
for C, since in C, NULL is just a 0 with a cast.)

The problematic chain of calls is this.

- pack_args (in arg_pack.m) is given a list of rvals, which may
include mlconst_nulls.

- If all the rvals are full words, then the arguments, including any
mlconst_nulls, are left alone.

- If some are *not* full words, then pack_args calls do_pack_args,
which invokes ShiftCombine on every rval, even when that rval
is not being packed.

- The caller of arg_pack in ml_unify_gen.m will specify
ml_shift_combine_rval or ml_shift_combine_rval_type
as ShiftCombine. Both of those predicates apply ml_lshift
to every rval, even the ones not being packed together
with anything else.

- ml_lshift replaces mlconst_nulls with mlconst_int(0)s,
presumably because this is the right thing to do for values being
packed, but I don't know whether a value being packed
(which at the moment is always an enum) can ever be mlconst_null.

All of this means that whether a full word mlconst_null in a cell
being constructed is replaced with mlconst_int(0) depends on the
"random" answer to the question: is there another word in the cell
that contains two or more packed arguments?

My questions are:

1 Was this semi-random conversion behavior designed or did it
just happen? If it was designed, what is the reason for it?

2 Has this semi-random conversion led to any problems
in programs using the C# or Java backends?

3 If not, why not? My understanding is that in C# and Java,
a null is NOT the same as 0.

4 Would anyone object if I changed things so that mlconst_nulls
that are not being packed were left alone? This *would* generate
different C# and Java code than before, whose validity I cannot check.

5 Would anyone object if I changed things so that mlconst_nulls
that *are* being packed aborted the compiler, so we could check
whether such things actually occur? I would commit this only
if it passed bootcheck in hlc.gc, obviously, but I can't bootcheck it
in C# or Java.

Zoltan.
Peter Wang
2018-03-05 00:05:02 UTC
Permalink
Hi Zoltan,
Post by Zoltan Somogyi
I have questions about the behavior of argument packing
with respect to NULL pointers. It seems to me that the MLDS
code generator is transforming mlconst_nulls into mlconst_int(0)s
almost randomly, and wondering why this is not a problem
on the C# and Java backends. (I don't expect this to be a problem
for C, since in C, NULL is just a 0 with a cast.)
The problematic chain of calls is this.
- pack_args (in arg_pack.m) is given a list of rvals, which may
include mlconst_nulls.
- If all the rvals are full words, then the arguments, including any
mlconst_nulls, are left alone.
- If some are *not* full words, then pack_args calls do_pack_args,
which invokes ShiftCombine on every rval, even when that rval
is not being packed.
- The caller of arg_pack in ml_unify_gen.m will specify
ml_shift_combine_rval or ml_shift_combine_rval_type
as ShiftCombine. Both of those predicates apply ml_lshift
to every rval, even the ones not being packed together
with anything else.
- ml_lshift replaces mlconst_nulls with mlconst_int(0)s,
presumably because this is the right thing to do for values being
packed, but I don't know whether a value being packed
(which at the moment is always an enum) can ever be mlconst_null.
All of this means that whether a full word mlconst_null in a cell
being constructed is replaced with mlconst_int(0) depends on the
"random" answer to the question: is there another word in the cell
that contains two or more packed arguments?
1 Was this semi-random conversion behavior designed or did it
just happen? If it was designed, what is the reason for it?
The replacing of nulls with zeroes is given by this comment ml_lshift:

% We may get nulls from unfilled fields. Replace them with zeroes
% so we don't get type errors from the C compiler.

Any other (unpacked) null getting replaced with zero should be
accidental, I would think.
Post by Zoltan Somogyi
2 Has this semi-random conversion led to any problems
in programs using the C# or Java backends?
No, as explained by this comment in handle_options.m:

% Argument packing only works on C back-ends with low-level data.
Post by Zoltan Somogyi
3 If not, why not? My understanding is that in C# and Java,
a null is NOT the same as 0.
That's right.
Post by Zoltan Somogyi
4 Would anyone object if I changed things so that mlconst_nulls
that are not being packed were left alone? This *would* generate
different C# and Java code than before, whose validity I cannot check.
Go ahead.
Post by Zoltan Somogyi
5 Would anyone object if I changed things so that mlconst_nulls
that *are* being packed aborted the compiler, so we could check
whether such things actually occur? I would commit this only
if it passed bootcheck in hlc.gc, obviously, but I can't bootcheck it
in C# or Java.
As long as we have a test case that tries to pack fields with unfilled
fields, if there is not one already.

Peter
Zoltan Somogyi
2018-03-05 02:38:26 UTC
Permalink
Post by Peter Wang
Hi Zoltan,
Post by Zoltan Somogyi
1 Was this semi-random conversion behavior designed or did it
just happen? If it was designed, what is the reason for it?
% We may get nulls from unfilled fields. Replace them with zeroes
% so we don't get type errors from the C compiler.
Any other (unpacked) null getting replaced with zero should be
accidental, I would think.
Yes, I read that comment, but I didn't know what it is trying to say.
Specifically, I didn't know why an unfilled enum would be represented
by a null, instead of a 0. But I see now that we represent *every*
unfilled value with a null, without testing its type.
Post by Peter Wang
Post by Zoltan Somogyi
2 Has this semi-random conversion led to any problems
in programs using the C# or Java backends?
% Argument packing only works on C back-ends with low-level data.
We restrict the creation of type representations that put two or more
fields into the same word to the C backend with low-level data.
However, the argument packing code is executed for *every* backend.
I see now that test in pack_args for "are there any sub-word arguments"
was, in a roundabout way, effectively testing for low-level data as well.
Post by Peter Wang
Post by Zoltan Somogyi
5 Would anyone object if I changed things so that mlconst_nulls
that *are* being packed aborted the compiler, so we could check
whether such things actually occur? I would commit this only
if it passed bootcheck in hlc.gc, obviously, but I can't bootcheck it
in C# or Java.
As long as we have a test case that tries to pack fields with unfilled
fields, if there is not one already.
It seems there are a couple of test cases with unfilled fields for
direct args, but I see none for packing. I will add some.

Thanks for your help.

Zoltan.

Loading...