[Vm-dev] bitten by & and |

Andreas Raab andreas.raab at gmx.de
Tue Jan 11 20:15:30 UTC 2011


I would vote for option

d) Disallow it altogether since it's completely ambiguous and *require* 
the use of #or:/bitOr: or #and:/bitAnd:. I.e.,

CCodeGenerator>>generateAmbigousOr: msgNode on: aStream indent: level

	self error: 'Usage of | is ambiguous - use #or: or #bitOr: instead'.

There are only a handful of uses that need to be fixed and the above 
would find them very quickly.

Cheers,
   - Andreas


On 1/11/2011 12:00 PM, Eliot Miranda wrote:
>
>
>
>
> 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


More information about the Vm-dev mailing list