<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2016-04-24 13:48 GMT+02:00  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</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&gt;&gt;computeKernelReturnTypes (in category &#39;public&#39;) -----<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: #&#39;char *&#39; 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&gt;&gt;promoteArithmeticTypes:and: (in category &#39;type inference&#39;) -----<br>
  promoteArithmeticTypes: firstType and: secondType<br>
        &quot;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.&quot;<br>
-        simple expressions.  Deal with pointer arithmetic, floating point arithmetic and promotion.&quot;<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] &quot;in C99 6.3.1.8, float+int, int is converted as a float&quot;].<br>
-               [^(firstType = #float and: [secondType = #float])<br>
-                       ifTrue: [#float]<br>
-                       ifFalse: [#double]].<br>
        &quot;deal with unknowns, answering nil.&quot;<br>
        (firstType isNil or: [secondType isNil]) ifTrue:<br>
                [^nil].<br>
+       &quot;Deal with integer promotion and arithmetic conversion&quot;<br>
+       ^self promoteIntegerArithmeticTypes: firstType and: secondType!<br>
-       &quot;Deal with promotion; answer the longest type, defaulting to the recever if they&#39;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&quot;<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 &gt; secondSize ifTrue: [firstType] ifFalse: [secondType]]!<br>
<br>
Item was added:<br>
+ ----- Method: CCodeGenerator&gt;&gt;promoteIntegerArithmeticTypes:and: (in category &#39;type inference&#39;) -----<br>
+ promoteIntegerArithmeticTypes: firstType and: secondType<br>
+       &quot;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.&quot;<br>
+       | length1 length2 intSize |<br>
+       length1 := self sizeOfIntegralCType: firstType.<br>
+       length2 := self sizeOfIntegralCType: secondType.<br>
+       intSize := self sizeOfIntegralCType: #int.<br>
+       (length1 &lt; intSize and: [length2 &lt; intSize]) ifTrue: [^#int].   &quot;Integer promotion&quot;<br>
+       length1 &gt; length2 ifTrue: [^firstType].<br>
+       length2 &gt; length1 ifTrue: [^secondType].<br>
+       firstType first = $u ifTrue: [^firstType].<br>
+       secondType first = $u ifTrue: [^secondType].<br>
+       ^firstType!<br>
<br>
</blockquote></div><br></div></div>