[Vm-dev] VM Maker: VMMaker.oscog-nice.1838.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Apr 24 11:49:17 UTC 2016


Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1838.mcz

==================== Summary ====================

Name: VMMaker.oscog-nice.1838
Author: nice
Time: 24 April 2016, 1:47:02.874 pm
UUID: 73cf9fda-4e5a-4e0c-a1b9-92ace5f8f3c9
Ancestors: VMMaker.oscog-nice.1837

Use a type inference that better fits C rules (C99 standard section 6.3):
- in (float op int), int is promoted to double not float
- in (unsigned short op short) both operands are promoted to #int due to int promotion rules.

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.

=============== Diff against VMMaker.oscog-nice.1837 ===============

Item was changed:
  ----- Method: CCodeGenerator>>computeKernelReturnTypes (in category 'public') -----
  computeKernelReturnTypes
  	| dictionary |
  	dictionary := Dictionary newFromPairs:
  		#(oopAt: #sqInt oopAt:put: #sqInt
  			oopAtPointer: #sqInt oopAtPointer:put: #sqInt
  		 byteAt: #sqInt byteAt:put: #sqInt
  			byteAtPointer: #sqInt byteAtPointer:put: #sqInt
  		 shortAt: #sqInt shortAt:put: #sqInt
  			shortAtPointer: #sqInt shortAtPointer:put: #sqInt
  		 intAt: #sqInt intAt:put: #sqInt
  			intAtPointer: #sqInt intAtPointer:put: #sqInt
  		 longAt: #sqInt longAt:put: #sqInt
  			longAtPointer: #sqInt longAtPointer:put: #sqInt
+ 				long32At: #int long32At:put: #int
- 				long32At: #sqInt long32At:put: #sqInt
  					unalignedLongAt: #sqInt unalignedLongAt:put: #sqInt
+ 						unalignedLong32At: #int unalignedLong32At:put: #int
- 						unalignedLong32At: #sqInt unalignedLong32At:put: #sqInt
  
  		 long64At: #sqLong long64At:put: #sqLong
  		
  		 fetchFloatAt:into: #void storeFloatAt:from: #void
  			fetchFloatAtPointer:into: #void storeFloatAtPointer:from: #void
  		 fetchSingleFloatAt:into: #void storeSingleFloatAt:from: #void
  			fetchSingleFloatAtPointer:into: #void storeSingleFloatAtPointer:from: #void
  
  		 pointerForOop: #'char *' oopForPointer: #sqInt).
- 	BytesPerWord = 8 ifTrue:
- 		[#(long32At: long32At:put: unalignedLong32At: unalignedLong32At:put:) do:
- 			[:accessor|
- 			dictionary at: accessor put: #int]].
  	^dictionary!

Item was changed:
  ----- Method: CCodeGenerator>>promoteArithmeticTypes:and: (in category 'type inference') -----
  promoteArithmeticTypes: firstType and: secondType
  	"Answer the return type for an arithmetic send.  This is so that the inliner can still inline
+ 	 simple expressions.  Deal with pointer arithmetic, floating point arithmetic and promotion.
+ 	 It is important to choose deterministically to get stable source generation.
+ 	 Also, the behaviour of inlined and non inlined code should be unchanged."
- 	 simple expressions.  Deal with pointer arithmetic, floating point arithmetic and promotion."
- 	| firstSize secondSize |
  	((#(#double float) includes: firstType)
  	 or: [#(#double float) includes: secondType]) ifTrue:
+ 		[^(firstType = #double or: [secondType = #double])
+ 			ifTrue: [#double]
+ 			ifFalse: [#float] "in C99 6.3.1.8, float+int, int is converted as a float"].
- 		[^(firstType = #float and: [secondType = #float])
- 			ifTrue: [#float]
- 			ifFalse: [#double]].
  	"deal with unknowns, answering nil."
  	(firstType isNil or: [secondType isNil]) ifTrue:
  		[^nil].
+ 	"Deal with integer promotion and arithmetic conversion"
+ 	^self promoteIntegerArithmeticTypes: firstType and: secondType!
- 	"Deal with promotion; answer the longest type, defaulting to the recever if they're the same.
- 	 See e.g. section 6.3.1.8 Usual arithmetic conversions, from the C99 standard:
- 		Otherwise, the integer promotions are performed on both operands
- 		Then the following rules are applied to the promoted operands:
- 
- 			If both operands have the same type, then no further conversion is needed.
- 
- 			Otherwise, if both operands have signed integer types or both have unsigned integer
- 			types, the operand with the type of lesser integer conversion rank is converted to the
- 			type of the operand with greater rank.
- 
- 			Otherwise, if the operand that has unsigned integer type has rank greater or equal to
- 			the rank of the type of the other operand, then the operand with signed integer type
- 			is converted to the type of the operand with unsigned integer type.
- 
- 			Otherwise, if the type of the operand with signed integer type can represent all of the
- 			values of the type of the operand with unsigned integer type, then the operand with
- 			unsigned integer type is converted to the type of the operand with signed integer type.
- 
- 			Otherwise, both operands are converted to the unsigned integer type corresponding to
- 			the type of the operand with signed integer type.
- 
- 	It is important to choose deterministically to get stable source generation.  So if the types have
- 	the same size but differ in signedness we choose the unsigned type, which is in partial agreement
- 	with the above"
- 	^(firstSize := self sizeOfIntegralCType: firstType) = (secondSize := self sizeOfIntegralCType: secondType)
- 		ifTrue:
- 			[(firstType first = $u)
- 				ifTrue: [firstType]
- 				ifFalse: [(secondType first = $u) ifTrue: [secondType] ifFalse: [firstType]]]
- 		ifFalse:
- 			[firstSize > secondSize ifTrue: [firstType] ifFalse: [secondType]]!

Item was added:
+ ----- Method: CCodeGenerator>>promoteIntegerArithmeticTypes:and: (in category 'type inference') -----
+ promoteIntegerArithmeticTypes: firstType and: secondType
+ 	"Answer the return type for an arithmetic send.
+ 	Deal with integer promotion rules of C99.
+ 	See section 6.3 Conversions of the standard.
+ 	
+ 	6.3.1.1 ...snip...
+ 		If an int can represent all values of the original type, the value is converted to an int;
+ 		otherwise, it is converted to an unsigned int. These are called the integer promotions.
+ 		All other types are unchanged by the inte ger promotions
+ 
+ 	6.3.1.8 ...snip...
+ 		Otherwise, the integer promotions are performed on both operands
+ 		Then the following rules are applied to the promoted operands:
+ 
+ 			If both operands have the same type, then no further conversion is needed.
+ 
+ 			Otherwise, if both operands have signed integer types or both have unsigned integer
+ 			types, the operand with the type of lesser integer conversion rank is converted to the
+ 			type of the operand with greater rank.
+ 
+ 			Otherwise, if the operand that has unsigned integer type has rank greater or equal to
+ 			the rank of the type of the other operand, then the operand with signed integer type
+ 			is converted to the type of the operand with unsigned integer type.
+ 
+ 			Otherwise, if the type of the operand with signed integer type can represent all of the
+ 			values of the type of the operand with unsigned integer type, then the operand with
+ 			unsigned integer type is converted to the type of the operand with signed integer type.
+ 
+ 			Otherwise, both operands are converted to the unsigned integer type corresponding to
+ 			the type of the operand with signed integer type.
+ 
+ 	This is so that the generated code behaviour is unsensitive to inlining."
+ 	| length1 length2 intSize |
+ 	length1 := self sizeOfIntegralCType: firstType.
+ 	length2 := self sizeOfIntegralCType: secondType.
+ 	intSize := self sizeOfIntegralCType: #int.
+ 	(length1 < intSize and: [length2 < intSize]) ifTrue: [^#int].	"Integer promotion"
+ 	length1 > length2 ifTrue: [^firstType].
+ 	length2 > length1 ifTrue: [^secondType].
+ 	firstType first = $u ifTrue: [^firstType].
+ 	secondType first = $u ifTrue: [^secondType].
+ 	^firstType!



More information about the Vm-dev mailing list