[Vm-dev] bitten by & and |
Eliot Miranda
eliot.miranda at gmail.com
Tue Jan 11 20:00:55 UTC 2011
Hi All,
I just got bittenhard (not for the first time) by & and | (implemented
both by integers and booleans) being translated into && (== and:) and || (==
or:). So the following in constant folding in the
StackToRegisterMappingCogit
(argIsInt and: [rcvrIsInt]) ifTrue:
[rcvrInt := objectMemory integerValueOf: rcvrInt.
argInt := objectMemory integerValueOf: argInt.
primDescriptor opcode caseOf: {
[AddRR] -> [result := rcvrInt + argInt].
[SubRR] -> [result := rcvrInt - argInt].
[AndRR] -> [result := rcvrInt &: argInt].
[OrRR] -> [result := rcvrInt | argInt] }.
(objectMemory isIntegerValue: result) ifTrue:
["Must annotate the bytecode for correct pc mapping."
self annotateBytecode: self Label.
^self ssPop: 2; ssPushConstant: (objectMemory integerObjectOf: result)].
^self genSpecialSelectorSend].
produced valid results in the simulator, but was translated to
if (argIsInt
&& (rcvrIsInt)) {
rcvrInt = (rcvrInt >> 1);
argInt = (argInt >> 1);
switch ((primDescriptor->opcode)) {
case AddRR:
result = rcvrInt + argInt;
break;
case SubRR:
result = rcvrInt - argInt;
break;
case AndRR:
result = rcvrInt && argInt;
break;
case OrRR:
result = rcvrInt || argInt;
break;
default:
error("Case not found and no otherwise clause");
}
if (isIntegerValue(result)) {
annotateBytecode(gLabel());
return ssPop(2),ssPushConstant(((result << 1) | 1));
}
return genSpecialSelectorSend();
}
and so e.g. 16r4000 bitOr: 16r8000 evaluated to 1, not 49152.
Three approaches come to mind,
a) emit a warning when & and | are used with variables and/or literals as
opposed to message sends, e.g. warn for 1 | 2, var | var et al, but not for
(a > b) | (b > c) et al
b) translate | to | and & to &
c) translate expr | expr to expr || expr and expr & expr to expr && expr,
but translate varOrLiteral | anything to varOrLiteral | anything and
varOrLiteral & anything to varOrLiteral & anything, and vice verse.
I'm for b) since a relational expression such as a > 1 is defined in C to be
either 1 or 0, and so in C (oneOrZero | oneOrZero) == (oneOrZero
|| oneOrZero) and (oneOrZero & oneOrZero) == (oneOrZero && oneOrZero).
Thoughts, opinions?
best (hurting),
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20110111/465b153f/attachment.htm
More information about the Vm-dev
mailing list