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

commits at source.squeak.org commits at source.squeak.org
Sun Jul 24 02:19:52 UTC 2022


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

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

Name: VMMaker.oscog-eem.3218
Author: eem
Time: 23 July 2022, 7:19:39.045502 pm
UUID: 7674c9a8-b612-4cd3-b49c-96fc53f0f0c6
Ancestors: VMMaker.oscog-eem.3217

Merge VMMaker.oscog-KenD.3218.
Implement what I think Ken wants for ThreadedRiscV64FFIPlugin>>ffiCalloutTo:SpecOnStack:in:, i.e. to treat float & double differently from the array of float/double.

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

Item was added:
+ ----- Method: ThreadedRiscV64FFIPlugin>>ffiCalloutTo:SpecOnStack:in: (in category 'callout support') -----
+ ffiCalloutTo: procAddr SpecOnStack: specOnStack in: calloutState
+ 	<var: #procAddr type: #'void *'>
+ 	<var: #calloutState type: #'CalloutState *'>
+ 	<var: #loadFloatRegs declareC: 'extern void loadFloatRegs(double, double, double, double, double, double, double, double)'>
+ 	"Go out, call this guy and create the return value.  This *must* be inlined because of
+ 	 the alloca of the outgoing stack frame in ffiCall:WithFlags:NumArgs:Args:AndTypes:"
+ 	| myThreadIndex atomicType floatRet intRet structRet specSize |
+ 	<var: #doubleRet type: #double>
+ 	<var: #floatRet type: 'union { struct { float floats[8]; } f; struct dprr { double doubles[4]; } d; }'>
+ 	<var: #structRet type: #SixteenByteReturnII>
+ 	<var: #intRet type: #usqLong>
+ 	<inline: #always>
+ 	self cCode: [] inSmalltalk: [floatRet := ByteArray new: 32]. "Just a hack to placate the Smalltalk compiler; these should be proper struct types..."
+ 	myThreadIndex := interpreterProxy disownVM: (self disownFlagsFor: calloutState).
+ 	
+ 	calloutState floatRegisterIndex > 0 ifTrue:
+ 		[self loadFloatRegs:
+ 			   (calloutState floatRegisters at: 0)
+ 			_: (calloutState floatRegisters at: 1)
+ 			_: (calloutState floatRegisters at: 2)
+ 			_: (calloutState floatRegisters at: 3)
+ 			_: (calloutState floatRegisters at: 4)
+ 			_: (calloutState floatRegisters at: 5)
+ 			_: (calloutState floatRegisters at: 6)
+ 			_: (calloutState floatRegisters at: 7)].
+ 
+ 	(self allocaLiesSoSetSpBeforeCall or: [self mustAlignStack]) ifTrue:
+ 		[self setsp: calloutState argVector].
+ 
+ 	"float or double returns"
+ 	atomicType := self atomicTypeOf: calloutState ffiRetHeader.
+ 	(atomicType >> 1) = (FFITypeSingleFloat >> 1) ifTrue:
+ 		[| doubleRet |
+ 		atomicType = FFITypeDoubleFloat ifTrue:
+ 			[doubleRet := (self 
+ 									dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)')
+ 									with: (calloutState integerRegisters at: 0)
+ 									with: (calloutState integerRegisters at: 1)
+ 									with: (calloutState integerRegisters at: 2)
+ 									with: (calloutState integerRegisters at: 3)
+ 									with: (calloutState integerRegisters at: 4)
+ 									with: (calloutState integerRegisters at: 5)
+ 									with: (calloutState integerRegisters at: 6)
+ 									with: (calloutState integerRegisters at: 7))]
+ 			ifFalse:
+ 				[doubleRet := (self 
+ 									dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)')
+ 									with: (calloutState integerRegisters at: 0)
+ 									with: (calloutState integerRegisters at: 1)
+ 									with: (calloutState integerRegisters at: 2)
+ 									with: (calloutState integerRegisters at: 3)
+ 									with: (calloutState integerRegisters at: 4)
+ 									with: (calloutState integerRegisters at: 5)
+ 									with: (calloutState integerRegisters at: 6)
+ 									with: (calloutState integerRegisters at: 7))].
+ 			 "undo any callee argument pops because it may confuse stack management with the alloca."
+ 			 (self isCalleePopsConvention: calloutState callFlags) ifTrue:
+ 				[self setsp: calloutState argVector].
+ 			 interpreterProxy ownVM: myThreadIndex.
+ 			^self floatObjectOf: doubleRet].
+ 
+ 	"homogenous array of float/double returns"
+ 	((calloutState ffiRetHeader bitAnd: FFIFlagPointer+FFIFlagStructure) = FFIFlagStructure
+ 	 and: [self structIsHomogenousFloatArrayOfSize: (calloutState ffiRetHeader bitAnd: FFIStructSizeMask)
+ 				typeSpec: (self cCoerce: (interpreterProxy firstIndexableField: calloutState ffiRetSpec) to: #'unsigned int *')
+ 				ofLength: (specSize := interpreterProxy byteSizeOf: calloutState ffiRetSpec) / (self sizeof: #'unsigned int')]) ifTrue:
+ 					[floatRet d: (self 
+ 								dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'struct dprr (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)')
+ 								with: (calloutState integerRegisters at: 0)
+ 								with: (calloutState integerRegisters at: 1)
+ 								with: (calloutState integerRegisters at: 2)
+ 								with: (calloutState integerRegisters at: 3)
+ 								with: (calloutState integerRegisters at: 4)
+ 								with: (calloutState integerRegisters at: 5)
+ 								with: (calloutState integerRegisters at: 6)
+ 								with: (calloutState integerRegisters at: 7)).
+ 
+ 		 "undo any callee argument pops because it may confuse stack management with the alloca."
+ 		 (self isCalleePopsConvention: calloutState callFlags) ifTrue:
+ 			[self setsp: calloutState argVector].
+ 		 interpreterProxy ownVM: myThreadIndex.
+ 
+ 		"If the struct is a vector of floats then move float[2] to float[1], float[4] to float[2] and float[6] to float[3],
+ 		 to pack the float data in the double fields.  We can tell if the struct is composed of floats if its size is less
+ 		 than the spec size, since the spec size is (1 + n fields) * 4 bytes, and the struct size is n fields * 4 bytes
+ 		 for floats and n fields * 8 bytes for doubles.  We can't access the spec post call because it may have moved."
+ 		specSize > calloutState structReturnSize ifTrue:
+ 			[floatRet f floats at: 1 put: (floatRet f floats at: 2).
+ 			 floatRet f floats at: 2 put: (floatRet f floats at: 4).
+ 			 floatRet f floats at: 3 put: (floatRet f floats at: 6)].
+ 		^self ffiReturnStruct: (self addressOf: floatRet) ofType: (self ffiReturnType: specOnStack) in: calloutState].
+ 
+ 	"Integer and Structure returns..."
+ 	(self mustReturnStructOnStack: calloutState structReturnSize) 
+ 		ifTrue:
+ 			[intRet := 0.
+ 			self setReturnRegister: (self cCoerceSimple: calloutState limit to: #sqLong) "stack alloca'd struct"
+ 				 andCall: (self cCoerceSimple: procAddr to: #sqLong)
+ 				 withArgsArray: (self cCoerceSimple: (self addressOf: calloutState integerRegisters) to: #sqLong)]
+ 		ifFalse:
+ 			[structRet := self 
+ 					dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'SixteenByteReturnII (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)')
+ 					with: (calloutState integerRegisters at: 0)
+ 					with: (calloutState integerRegisters at: 1)
+ 					with: (calloutState integerRegisters at: 2)
+ 					with: (calloutState integerRegisters at: 3)
+ 					with: (calloutState integerRegisters at: 4)
+ 					with: (calloutState integerRegisters at: 5)
+ 					with: (calloutState integerRegisters at: 6)
+ 					with: (calloutState integerRegisters at: 7).
+ 			intRet := structRet a]. "X1"
+ 
+ 	"undo any callee argument pops because it may confuse stack management with the alloca."
+ 	(self isCalleePopsConvention: calloutState callFlags) ifTrue:
+ 		[self setsp: calloutState argVector].
+ 	interpreterProxy ownVM: myThreadIndex.
+ 
+ 	(calloutState ffiRetHeader anyMask: FFIFlagPointer+FFIFlagStructure) ifTrue:
+ 		["Note: Order is important here since FFIFlagPointer + FFIFlagStructure is used to represent
+ 		 'typedef void* VoidPointer' and VoidPointer must be returned as pointer *not* as struct."
+ 		 (calloutState ffiRetHeader anyMask: FFIFlagPointer) ifTrue:
+ 			[^self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState].
+ 		 ^self ffiReturnStruct: (((self returnStructInRegisters: calloutState)
+ 								ifTrue: [self cCoerceSimple: (self addressOf: structRet) to: #'char *']
+ 								ifFalse: [calloutState limit]))
+ 				ofType: (self ffiReturnType: specOnStack)
+ 				in: calloutState].
+ 	
+ 	^self ffiCreateIntegralResultOop: intRet ofAtomicType: atomicType in: calloutState!

Item was changed:
  ----- Method: ThreadedRiscV64FFIPlugin>>ffiPushFloat32:in: (in category 'marshalling') -----
  ffiPushFloat32: value in: calloutState
  	<var: #value type: #float>
  	<var: #calloutState type: #'CalloutState *'>
  	<inline: #always>
  	"N.B. the RISCV ABI states that unused part should be -1,
  	 [RISC-V Instruction Set Manual - Volume I: User Level ISA,
  	 12.2 NaN Boxing of Narrower Value"
  	calloutState floatRegisterIndex < NumFloatRegArgs
  		ifTrue: "Note: this is a 'memcopy', so size is preserved. Casting to #double changes the size"
  			[(self cCoerceSimple: 
  				(self addressOf: (calloutState floatRegisters at: calloutState floatRegisterIndex)) 
  					 to: #'long *')
  				at: 0
  				put: -1.
  			(self cCoerceSimple: 
  				(self addressOf: (calloutState floatRegisters at: calloutState floatRegisterIndex)) 
  					 to: #'float *')
  				at: 0
  				put: value.
+ 			 calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1
+ 		]
+ 		ifFalse: "Use integer register if available"
+ 		[ (calloutState integerRegisterIndex < NumIntRegArgs)
+ 			ifTrue:
+ 			[calloutState integerRegisters 
+ 				at: calloutState integerRegisterIndex 
+ 				put: -1.
+ 			 self storeSingleFloatAtPointer: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex))
+ 			       from: value.
+ 			 calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1
+ 			]
+ 		      ifFalse:
+ 			[calloutState currentArg + self wordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].
+ 			   interpreterProxy longAt: calloutState currentArg put: value.
+ 			   calloutState currentArg: calloutState currentArg + self wordSize
+ 			].
+ 		].
- 			 calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1]
- 		ifFalse:
- 			[calloutState currentArg + self wordSize > calloutState limit ifTrue:
- 				[^FFIErrorCallFrameTooBig].
- 			 interpreterProxy
- 				longAt: calloutState currentArg put: -1;
- 				storeSingleFloatAtPointer: calloutState currentArg from: value.
- 			 calloutState currentArg: calloutState currentArg + self wordSize].
  	^0!

Item was added:
+ ----- Method: ThreadedRiscV64FFIPlugin>>ffiPushFloat64:in: (in category 'marshalling') -----
+ ffiPushFloat64: value in: calloutState
+ 	<var: #value type: #double>
+ 	<var: #calloutState type: #'CalloutState *'>
+ 	<inline: #always>
+ 
+ 	calloutState floatRegisterIndex < NumFloatRegArgs
+ 		ifTrue:
+ 		[calloutState floatRegisters
+ 				at: calloutState floatRegisterIndex
+ 				put: value.
+ 		 calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1
+ 		]
+ 		ifFalse: "Use integer register if available"
+ 		[(calloutState integerRegisterIndex < NumIntRegArgs)
+ 		 ifTrue: [
+ 			 self storeFloatAtPointer: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex))
+ 			       from: value.
+ 			calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1
+ 			]
+ 		 ifFalse: [
+ 			calloutState currentArg + self wordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].
+ 			   interpreterProxy longAt: calloutState currentArg put: value.
+ 			   calloutState currentArg: calloutState currentArg + self wordSize
+ 		 	]
+ 		].
+ 	^0!



More information about the Vm-dev mailing list