[Vm-dev] VM Maker: VMMaker.oscog-mt.3182.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Apr 14 13:13:45 UTC 2022


Marcel Taeumel uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-mt.3182.mcz

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

Name: VMMaker.oscog-mt.3182
Author: mt
Time: 14 April 2022, 3:13:29.844637 pm
UUID: 42239309-89d2-1742-a787-54dbce98bfdd
Ancestors: VMMaker.oscog-mt.3181

In FFI callouts following ARM64 abi, document an issue with pushing structs that are larger than 16 bytes as argument. That is, called functions will always read x0 register as pointer to fetch argument. This currently results in a segmentation fault.

Thanks to Tobias (topa) for figuring out this issue!

=============== Diff against VMMaker.oscog-mt.3181 ===============

Item was changed:
  ----- Method: ThreadedARM64AppleFFIPlugin>>ffiPushStructure:ofSize:typeSpec:ofLength:in: (in category 'marshalling') -----
  ffiPushStructure: pointer ofSize: structSize typeSpec: argSpec ofLength: argSpecSize in: calloutState
  	<var: #pointer type: #'void *'>
  	<var: #argSpec type: #'unsigned int *'>
  	<var: #calloutState type: #'CalloutState *'>
  	<inline: #always>
  	| availableRegisterSpace stackPartSize roundedSize |
+ 	"Stage B, step B.4 -- composite type larger than 16 bytes copied to caller-allocated memory and replaced by pointer"
+ 	self flag: #todo.
+ 
  	"See IHI0055B_aapcs64.pdf sections 4.3.5 & 5.4.2 Stage C; we don't yet support HVA's"
  	(self structIsHomogenousFloatArrayOfSize: structSize typeSpec: argSpec ofLength: argSpecSize)
  		ifTrue:
  			[availableRegisterSpace := (NumFloatRegArgs - calloutState floatRegisterIndex) * self wordSize.
  			 structSize <= availableRegisterSpace ifTrue: "Stage C, step C.2, all in floating-point registers (!!!!)"
  				[self 
  					memcpy: (self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: calloutState floatRegisterIndex)) to: #'void *') 
  					_: pointer 
  					_: structSize.
  					"Round structSize up and divide by 8 ( NB: _not_ 4 !!)"
  				 calloutState floatRegisterIndex: calloutState floatRegisterIndex + (structSize + 7 bitShift: -3).
  				 ^0].
  			 "Stage C, step C.3"
  			 availableRegisterSpace := 0.
  			 calloutState floatRegisterIndex: 8]
  
  		ifFalse:
  			[availableRegisterSpace := (NumIntRegArgs - calloutState integerRegisterIndex) * self wordSize].
  	stackPartSize := structSize.
  	availableRegisterSpace > 0 ifTrue: 
  		[structSize <= availableRegisterSpace ifTrue:"all in integer registers"
  			[self 
  				memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: #'void *') 
  				_: pointer 
  				_: structSize.
  				"Round structSize up and divide by 8 ( NB: _not_ 4 !!)"
  			 calloutState integerRegisterIndex: calloutState integerRegisterIndex + (structSize + 7 bitShift: -3).
  			 ^0].
  		 "If no previous co-processor candidate arg has already been pushed on the stack, then split the struct between registers and stack.
  		  Otherwise push entire struct on stack."
  		 calloutState currentArg = calloutState argVector
  			ifTrue: 
  		 		[stackPartSize := structSize - availableRegisterSpace.
  		 		self 
  					memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') 
  					_: pointer 
  					_: availableRegisterSpace]
  			ifFalse:
  				[availableRegisterSpace := 0].
  		"Stage C, step C.11"
  		calloutState integerRegisterIndex: NumIntRegArgs].
  
  	stackPartSize > 0 ifTrue: 
  		[roundedSize := stackPartSize + 3 bitClear: 3.
  		 calloutState currentArg + roundedSize > calloutState limit ifTrue:
  			 [^FFIErrorCallFrameTooBig].
  		 self alignCurrentArgOf: calloutState to: 8.
  		 self memcpy: calloutState currentArg _: (self addressOf: ((self cCoerceSimple: pointer to: #'char *') at: availableRegisterSpace)) _: stackPartSize.
  		 calloutState currentArg: calloutState currentArg + roundedSize].
  	^0!

Item was changed:
  ----- Method: ThreadedARM64FFIPlugin>>ffiPushStructure:ofSize:typeSpec:ofLength:in: (in category 'marshalling') -----
  ffiPushStructure: pointer ofSize: structSize typeSpec: argSpec ofLength: argSpecSize in: calloutState
  	<var: #pointer type: #'void *'>
  	<var: #argSpec type: #'unsigned int *'>
  	<var: #calloutState type: #'CalloutState *'>
  	<inline: #always>
  	| availableRegisterSpace stackPartSize roundedSize |
+ 	"Stage B, step B.4 -- composite type larger than 16 bytes copied to caller-allocated memory and replaced by pointer"
+ 	self flag: #todo.
+ 
  	"See IHI0055B_aapcs64.pdf sections 4.3.5 & 5.4.2 Stage C; we don't yet support HVA's"
  	(self structIsHomogenousFloatArrayOfSize: structSize typeSpec: argSpec ofLength: argSpecSize)
  		ifTrue:
  			[availableRegisterSpace := (NumFloatRegArgs - calloutState floatRegisterIndex) * self wordSize.
  			 structSize <= availableRegisterSpace ifTrue: "Stage C, step C.2, all in floating-point registers (!!!!)"
  				[self 
  					memcpy: (self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: calloutState floatRegisterIndex)) to: #'void *') 
  					_: pointer 
  					_: structSize.
  					"Round structSize up and divide by 8 ( NB: _not_ 4 !!)"
  				 calloutState floatRegisterIndex: calloutState floatRegisterIndex + (structSize + 7 bitShift: -3).
  				 ^0].
  			 "Stage C, step C.3"
  			 availableRegisterSpace := 0.
  			 calloutState floatRegisterIndex: 8]
  
  		ifFalse:
  			[availableRegisterSpace := (NumIntRegArgs - calloutState integerRegisterIndex) * self wordSize].
  	stackPartSize := structSize.
  	availableRegisterSpace > 0 ifTrue: 
  		[structSize <= availableRegisterSpace ifTrue:"all in integer registers"
  			[self 
  				memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: #'void *') 
  				_: pointer 
  				_: structSize.
  				"Round structSize up and divide by 8 ( NB: _not_ 4 !!)"
  			 calloutState integerRegisterIndex: calloutState integerRegisterIndex + (structSize + 7 bitShift: -3).
  			 ^0].
  		 "If no previous co-processor candidate arg has already been pushed on the stack, then split the struct between registers and stack.
  		  Otherwise push entire struct on stack."
  		 calloutState currentArg = calloutState argVector
  			ifTrue: 
  		 		[stackPartSize := structSize - availableRegisterSpace.
  		 		self 
  					memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') 
  					_: pointer 
  					_: availableRegisterSpace]
  			ifFalse:
  				[availableRegisterSpace := 0].
  		"Stage C, step C.11"
  		calloutState integerRegisterIndex: NumIntRegArgs].
  
  	stackPartSize > 0 ifTrue: 
  		[roundedSize := stackPartSize + 3 bitClear: 3.
  		 calloutState currentArg + roundedSize > calloutState limit ifTrue:
  			 [^FFIErrorCallFrameTooBig].
  		 self memcpy: calloutState currentArg _: (self addressOf: ((self cCoerceSimple: pointer to: #'char *') at: availableRegisterSpace)) _: stackPartSize.
  		 calloutState currentArg: calloutState currentArg + roundedSize].
  	^0!



More information about the Vm-dev mailing list