[Vm-dev] bitten by & and |

Igor Stasenko siguctua at gmail.com
Tue Jan 11 20:48:11 UTC 2011


On 11 January 2011 21:15, Andreas Raab <andreas.raab at gmx.de> wrote:
>
> 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.
>

+1

rather than trying to find less painful workaround, it is better to
simply bark at each use of it,
and don't generate code until all uses of it will be examined and
replaced with aproppriate or/bitOr/and/bitAnd

Also, for clarity i would even introduce

#define bitAnd(x,y)  ((x) & (y))
#define and(x,y)  ((x) && (y))
#define or(x,y)  ((x) || (y))
#define bitOr(x,y)  ((x) | (y))

and let generate to use these macros instead of &&/&/|/|| . So,in this
way, C code could be more readable :)


> 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
>



-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Vm-dev mailing list