<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2016-04-24 13:48 GMT+02:00 <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1838.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1838.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-nice.1838<br>
Author: nice<br>
Time: 24 April 2016, 1:47:02.874 pm<br>
UUID: 73cf9fda-4e5a-4e0c-a1b9-92ace5f8f3c9<br>
Ancestors: VMMaker.oscog-nice.1837<br>
<br>
Use a type inference that better fits C rules (C99 standard section 6.3):<br>
- in (float op int), int is promoted to double not float<br>
- in (unsigned short op short) both operands are promoted to #int due to int promotion rules.<br>
<br>
The idea behind this is that behaviour of generated code for inlined and non inlined code should be the same. We can guaranty such property only if we adhere to C rules.<br>
<br>
=============== Diff against VMMaker.oscog-nice.1837 ===============<br>
<br>
Item was changed:<br>
----- Method: CCodeGenerator>>computeKernelReturnTypes (in category 'public') -----<br>
computeKernelReturnTypes<br>
| dictionary |<br>
dictionary := Dictionary newFromPairs:<br>
#(oopAt: #sqInt oopAt:put: #sqInt<br>
oopAtPointer: #sqInt oopAtPointer:put: #sqInt<br>
byteAt: #sqInt byteAt:put: #sqInt<br>
byteAtPointer: #sqInt byteAtPointer:put: #sqInt<br>
shortAt: #sqInt shortAt:put: #sqInt<br>
shortAtPointer: #sqInt shortAtPointer:put: #sqInt<br>
intAt: #sqInt intAt:put: #sqInt<br>
intAtPointer: #sqInt intAtPointer:put: #sqInt<br>
longAt: #sqInt longAt:put: #sqInt<br>
longAtPointer: #sqInt longAtPointer:put: #sqInt<br>
+ long32At: #int long32At:put: #int<br>
- long32At: #sqInt long32At:put: #sqInt<br>
unalignedLongAt: #sqInt unalignedLongAt:put: #sqInt<br>
+ unalignedLong32At: #int unalignedLong32At:put: #int<br>
- unalignedLong32At: #sqInt unalignedLong32At:put: #sqInt<br>
<br></blockquote><div><br></div><div>Ah, I forgot to comment the purpose of #computeKernelReturnTypes change:<br></div><div>the idea is that we use a type inference that works both for 32 and 64 bits VM.<br><br></div><div>Why? Because we generate single source code for both 32 and 64 bits plugins.<br></div><div>So we should have type inference as much independent of BytesPerWord as possible.<br></div><div><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
long64At: #sqLong long64At:put: #sqLong<br>
<br>
fetchFloatAt:into: #void storeFloatAt:from: #void<br>
fetchFloatAtPointer:into: #void storeFloatAtPointer:from: #void<br>
fetchSingleFloatAt:into: #void storeSingleFloatAt:from: #void<br>
fetchSingleFloatAtPointer:into: #void storeSingleFloatAtPointer:from: #void<br>
<br>
pointerForOop: #'char *' oopForPointer: #sqInt).<br>
- BytesPerWord = 8 ifTrue:<br>
- [#(long32At: long32At:put: unalignedLong32At: unalignedLong32At:put:) do:<br>
- [:accessor|<br>
- dictionary at: accessor put: #int]].<br>
^dictionary!<br>
<br>
Item was changed:<br>
----- Method: CCodeGenerator>>promoteArithmeticTypes:and: (in category 'type inference') -----<br>
promoteArithmeticTypes: firstType and: secondType<br>
"Answer the return type for an arithmetic send. This is so that the inliner can still inline<br>
+ simple expressions. Deal with pointer arithmetic, floating point arithmetic and promotion.<br>
+ It is important to choose deterministically to get stable source generation.<br>
+ Also, the behaviour of inlined and non inlined code should be unchanged."<br>
- simple expressions. Deal with pointer arithmetic, floating point arithmetic and promotion."<br>
- | firstSize secondSize |<br>
((#(#double float) includes: firstType)<br>
or: [#(#double float) includes: secondType]) ifTrue:<br>
+ [^(firstType = #double or: [secondType = #double])<br>
+ ifTrue: [#double]<br>
+ ifFalse: [#float] "in C99 6.3.1.8, float+int, int is converted as a float"].<br>
- [^(firstType = #float and: [secondType = #float])<br>
- ifTrue: [#float]<br>
- ifFalse: [#double]].<br>
"deal with unknowns, answering nil."<br>
(firstType isNil or: [secondType isNil]) ifTrue:<br>
[^nil].<br>
+ "Deal with integer promotion and arithmetic conversion"<br>
+ ^self promoteIntegerArithmeticTypes: firstType and: secondType!<br>
- "Deal with promotion; answer the longest type, defaulting to the recever if they're the same.<br>
- See e.g. section 6.3.1.8 Usual arithmetic conversions, from the C99 standard:<br>
- Otherwise, the integer promotions are performed on both operands<br>
- Then the following rules are applied to the promoted operands:<br>
-<br>
- If both operands have the same type, then no further conversion is needed.<br>
-<br>
- Otherwise, if both operands have signed integer types or both have unsigned integer<br>
- types, the operand with the type of lesser integer conversion rank is converted to the<br>
- type of the operand with greater rank.<br>
-<br>
- Otherwise, if the operand that has unsigned integer type has rank greater or equal to<br>
- the rank of the type of the other operand, then the operand with signed integer type<br>
- is converted to the type of the operand with unsigned integer type.<br>
-<br>
- Otherwise, if the type of the operand with signed integer type can represent all of the<br>
- values of the type of the operand with unsigned integer type, then the operand with<br>
- unsigned integer type is converted to the type of the operand with signed integer type.<br>
-<br>
- Otherwise, both operands are converted to the unsigned integer type corresponding to<br>
- the type of the operand with signed integer type.<br>
-<br>
- It is important to choose deterministically to get stable source generation. So if the types have<br>
- the same size but differ in signedness we choose the unsigned type, which is in partial agreement<br>
- with the above"<br>
- ^(firstSize := self sizeOfIntegralCType: firstType) = (secondSize := self sizeOfIntegralCType: secondType)<br>
- ifTrue:<br>
- [(firstType first = $u)<br>
- ifTrue: [firstType]<br>
- ifFalse: [(secondType first = $u) ifTrue: [secondType] ifFalse: [firstType]]]<br>
- ifFalse:<br>
- [firstSize > secondSize ifTrue: [firstType] ifFalse: [secondType]]!<br>
<br>
Item was added:<br>
+ ----- Method: CCodeGenerator>>promoteIntegerArithmeticTypes:and: (in category 'type inference') -----<br>
+ promoteIntegerArithmeticTypes: firstType and: secondType<br>
+ "Answer the return type for an arithmetic send.<br>
+ Deal with integer promotion rules of C99.<br>
+ See section 6.3 Conversions of the standard.<br>
+<br>
+ 6.3.1.1 ...snip...<br>
+ If an int can represent all values of the original type, the value is converted to an int;<br>
+ otherwise, it is converted to an unsigned int. These are called the integer promotions.<br>
+ All other types are unchanged by the inte ger promotions<br>
+<br>
+ 6.3.1.8 ...snip...<br>
+ Otherwise, the integer promotions are performed on both operands<br>
+ Then the following rules are applied to the promoted operands:<br>
+<br>
+ If both operands have the same type, then no further conversion is needed.<br>
+<br>
+ Otherwise, if both operands have signed integer types or both have unsigned integer<br>
+ types, the operand with the type of lesser integer conversion rank is converted to the<br>
+ type of the operand with greater rank.<br>
+<br>
+ Otherwise, if the operand that has unsigned integer type has rank greater or equal to<br>
+ the rank of the type of the other operand, then the operand with signed integer type<br>
+ is converted to the type of the operand with unsigned integer type.<br>
+<br>
+ Otherwise, if the type of the operand with signed integer type can represent all of the<br>
+ values of the type of the operand with unsigned integer type, then the operand with<br>
+ unsigned integer type is converted to the type of the operand with signed integer type.<br>
+<br>
+ Otherwise, both operands are converted to the unsigned integer type corresponding to<br>
+ the type of the operand with signed integer type.<br>
+<br>
+ This is so that the generated code behaviour is unsensitive to inlining."<br>
+ | length1 length2 intSize |<br>
+ length1 := self sizeOfIntegralCType: firstType.<br>
+ length2 := self sizeOfIntegralCType: secondType.<br>
+ intSize := self sizeOfIntegralCType: #int.<br>
+ (length1 < intSize and: [length2 < intSize]) ifTrue: [^#int]. "Integer promotion"<br>
+ length1 > length2 ifTrue: [^firstType].<br>
+ length2 > length1 ifTrue: [^secondType].<br>
+ firstType first = $u ifTrue: [^firstType].<br>
+ secondType first = $u ifTrue: [^secondType].<br>
+ ^firstType!<br>
<br>
</blockquote></div><br></div></div>