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
|
On 11.01.2011, at 21:00, Eliot Miranda wrote: Hi All, & and | are not implemented by integers in Squeak. Use bitOr: and bitAnd:. - Bert - |
In reply to this post by Eliot Miranda-2
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 |
On 11 January 2011 21:15, Andreas Raab <[hidden email]> 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. |
2011/1/11 Igor Stasenko <[hidden email]>: > > On 11 January 2011 21:15, Andreas Raab <[hidden email]> 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 :) > With differences in signed/unsigned promotion to a longer int, I don't think you'll ever get a readable C ;). Nicolas > >> 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. > |
Free forum by Nabble | Edit this page |