[Vm-dev] VM Maker: VMMaker.oscog-eem.1071.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Feb 19 03:27:29 UTC 2015


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1071.mcz

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

Name: VMMaker.oscog-eem.1071
Author: eem
Time: 18 February 2015, 7:25:44.963 pm
UUID: 6b4dfa33-242b-4b9b-8b1a-0aee9139cf6c
Ancestors: VMMaker.oscog-eem.1070

Fix several bugs in the new type inferrence code,
resulting in a functional VM again (phew!).

Do a much better job at typeForArithmetic:in:;
answering the longest type for integral types.

In inferTypesForImplicitlyTypedVariablesIn:, observe
assignments from both sends and typed vars.
Comment the method better so that 
alreadyExplicitlyTyped's usage is clear(er).

On type compatibility of inlined expressions,
insist on signed compatibility or accept an untyped
actual.

Provide a return type for asFloat (so inlining in
primitiveAsFloat still occurs)

Provide an exception in unsignedTypeForBitwiseSend:in:
for currentBytecode to preserve the nice constant
inlining of currentBytecode & N in the bytecode cases.

This time I feel that the Slang Sensei has hit me
over the head and some enlightenment has ensued.
That's a first ;-).

=============== Diff against VMMaker.oscog-eem.1070 ===============

Item was changed:
  ----- Method: CCodeGenerator>>isActualType:compatibleWithFormalType: (in category 'inlining') -----
  isActualType: actualTypeOrNil compatibleWithFormalType: formalTypeOrNil 
  	| actualType formalType |
  	actualType := actualTypeOrNil ifNil: [#sqInt].
  	formalType := formalTypeOrNil ifNil: [#sqInt].
  	((self isIntegralCType: actualType)
  	 and: [self isIntegralCType: formalType]) ifFalse:
  		[^actualType = formalType
  		 or: [formalType = 'double' and: [actualType = 'float']]].
  	"For now, insist that the signedness agrees."
  	^(actualType first = $u) = (formalType first = $u)
+ 	  or: [actualTypeOrNil isNil] "a nil formal defaults to #sqInt"!
- 	 or: [actualTypeOrNil isNil or: [formalTypeOrNil isNil]]!

Item was changed:
  ----- Method: CCodeGenerator>>returnTypeForSend:in: (in category 'type inference') -----
  returnTypeForSend: sendNode in: aTMethod
  	"Answer the return type for a send.  Absent sends default to #sqInt.
  	 The bitwise operators answer unsigned versions of their argument types, at least in gcc
  	 although this author can't find that in the C99 spec.  If you can find this, please let me know."
  	| sel |
  	^(self anyMethodNamed: (sel := sendNode selector))
  		ifNil: [kernelReturnTypes
  				at: sel
  				ifAbsent:
  					[^sel
  						caseOf: {
  						[#+]					->	[self typeForArithmetic: sendNode in: aTMethod].
  						[#-]						->	[self typeForArithmetic: sendNode in: aTMethod].
  						[#*]					->	[self typeForArithmetic: sendNode in: aTMethod].
  						[#/]						->	[self typeForArithmetic: sendNode in: aTMethod].
  						[#addressOf:]			->	[(self typeFor: sendNode receiver in: aTMethod)
  														ifNil: [#sqInt]
  														ifNotNil: [:type| type, (type last isLetter ifTrue: [' *'] ifFalse: ['*'])]].
  						[#at:]					->	[self typeForDereference: sendNode in: aTMethod].
  						[#bitAnd:]				->	[self unsignedTypeForBitwiseSend: sendNode in: aTMethod].
  						[#bitOr:]				->	[self unsignedTypeForBitwiseSend: sendNode in: aTMethod].
  						[#bitXor:]				->	[self unsignedTypeForBitwiseSend: sendNode in: aTMethod].
+ 						[#asFloat]				->	[#double].
- 						[#asVoidPointer]		->	[#'void *'].
- 						[#asVoidPointer]		->	[#'void *'].
- 						[#asUnsignedInteger]	->	[#usqInt].
  						[#asLong]				->	[#long].
+ 						[#asUnsignedInteger]	->	[#usqInt].
  						[#asUnsignedLong]		->	[#'unsigned long'].
+ 						[#asVoidPointer]		->	[#'void *'].
  						[#signedIntToLong]		->	[#usqInt]. "c.f. generateSignedIntToLong:on:indent:"
  						[#signedIntToShort]	->	[#usqInt]. "c.f. generateSignedIntToShort:on:indent:"
  						[#cCoerce:to:]			->	[sendNode args last value].
  						[#cCoerceSimple:to:]	->	[sendNode args last value] }
  						otherwise: [#sqInt]]]
  		ifNotNil:
  			[:m|
  			 m returnType ifNotNil:
  				[:type|
  				 self baseTypeForType: type]]!

Item was changed:
  ----- Method: CCodeGenerator>>typeForArithmetic:in: (in category 'type inference') -----
  typeForArithmetic: sendNode in: aTMethod
  	"Answer the return type for an arithmetic sendThis is so that the inliner can still
+ 	 inline simple expressions.  Deal with pointer arithmetic, floating point arithmetic
+ 	 and promotion."
- 	 inline simple expressions.  Deal with pointer arithmetic and floating point arithmetic"
  	| rcvrType argType |
  	argType := self typeFor: sendNode args first in: aTMethod.
  	argType = #double ifTrue:
  		[^#double].
  	rcvrType := self typeFor: sendNode receiver in: aTMethod.
+ 	"deal with unknowns, answering nil."
+ 	(rcvrType isNil or: [argType isNil]) ifTrue:
+ 		[^nil].
+ 	"deal with pointer arithmetic"
+ 	(rcvrType last = $* or: [argType last = $*]) ifTrue:
+ 		[(sendNode selector == #-
+ 		  and: [rcvrType last = $* and: [argType last = $*]]) ifTrue:
+ 			[^#int].
+ 		 ^rcvrType last = $
+ 			ifTrue: [rcvrType]
+ 			ifFalse: [argType]].
+ 	"deal with promotion; answer the longest type, defaulting to the recever if they're the same"
+ 	^(self sizeOfIntegralCType: rcvrType) >= (self sizeOfIntegralCType: argType)
+ 		ifTrue: [rcvrType]
+ 		ifFalse: [argType]!
- 	(sendNode selector == #-
- 	 and: [rcvrType notNil and: [rcvrType last = $*
- 	 and: [argType notNil and: [argType last = $*]]]]) ifTrue:
- 		[^#int].
- 	^rcvrType!

Item was changed:
  ----- Method: CCodeGenerator>>unsignedTypeForBitwiseSend:in: (in category 'type inference') -----
  unsignedTypeForBitwiseSend: aTSendNode in: aTMethod
+ 	"The result of the bitwise operators in C is unsigned.
+ 	 We make an exception for currentBytecode bitAnd: N to allow better inlining in cases."
- 	"The result of the bitwise operators in C is unsigned."
  	| t1 t2 type |
+ 	(aTSendNode receiver isVariable
+ 	and: [aTSendNode receiver name = 'currentBytecode'
+ 	and: [aTSendNode selector == #bitAnd:]]) ifTrue:
+ 		[^#sqInt].
  	t1 := (self typeFor: aTSendNode receiver in: aTMethod) ifNil: [^nil].
  	t2 := (self typeFor: aTSendNode args first in: aTMethod) ifNil: [^nil].
  	type := (self sizeOfIntegralCType: t1) >= (self sizeOfIntegralCType: t1)
  				ifTrue: [t1]
  				ifFalse: [t2].
  	^type first = $u
  		ifTrue: [type]
  		ifFalse:
  			[(type beginsWith: 'sq')
  				ifTrue: ['u', type]
  				ifFalse: ['unsigned ', type]]!

Item was changed:
  ----- Method: TMethod>>inferTypesForImplicitlyTypedVariablesIn: (in category 'type inference') -----
  inferTypesForImplicitlyTypedVariablesIn: aCodeGen
  	"infer types for untyped variables from assignments and arithmetic uses.
  	 For debugging answer a Dictionary from var to the nodes that determined types
  	 This for debugging:
  		(self copy inferTypesForImplicitlyTypedVariablesIn: aCodeGen)"
+ 	| alreadyExplicitlyTyped effectiveNodes |
+ 	"selector = #blockDispatchTargetsFor:perform:arg: ifTrue:
+ 		[self halt]."
+ 	alreadyExplicitlyTyped := declarations keys asSet.
- 	| explicitlyTyped effectiveNodes |
- 	explicitlyTyped := declarations keys asSet.
  	effectiveNodes := Dictionary new. "this for debugging"
  	parseTree nodesDo:
  		[:node| | type var |
  		"If there is something of the form i >= 0, then i should be signed, not unsigned."
  		(node isSend
  		 and: [(locals includes: (var := node receiver variableNameOrNil))
+ 		 and: [(alreadyExplicitlyTyped includes: var) not "don't be fooled by inferred unsigned types"
- 		 and: [(explicitlyTyped includes: var) not
  		 and: [(#(<= < >= >) includes: node selector)
  		 and: [node args first isConstant
  		 and: [node args first value = 0
  		 and: [(type := self typeFor: var in: aCodeGen) notNil
  		 and: [type first == $u]]]]]]]) ifTrue:
  			[declarations at: var put: (aCodeGen signedTypeForIntegralType: type), ' ', var.
  			 effectiveNodes at: var put: { declarations at: var. node }].
+ 		"if an assignment to an untyped local of a known type, set the local's type to that type.
+ 		 Only observe known sends (methods in the current set) and typed local variables."
- 		"if an assignment to an untyped local of a known type, set the local's type to that type."
  		(node isAssignment
  		 and: [(locals includes: (var := node variable name))
  		 and: [(declarations includesKey: var) not
+ 		 and: [(type := node expression isSend
+ 						ifTrue: [aCodeGen returnTypeForSend: node expression in: self]
+ 						ifFalse: [self typeFor: node expression in: aCodeGen]) notNil
- 		 and: [(type := self typeFor: node expression in: aCodeGen) notNil
  		 and: [type ~= #void]]]]) ifTrue:
  			[declarations at: var put: type, ' ', var.
  			 effectiveNodes at: var put: { declarations at: var. node }]].
  	^effectiveNodes!



More information about the Vm-dev mailing list