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

commits at source.squeak.org commits at source.squeak.org
Sat Jan 25 07:57:44 UTC 2020


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

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

Name: VMMaker.oscog-nice.2677
Author: nice
Time: 25 January 2020, 1:00:54.275459 am
UUID: 9cde398a-8dfa-4935-b84f-b1b114be3cb0
Ancestors: VMMaker.oscog-eem.2676

Correct the floatType and doubleType check for passing struct by value on X64 SysV ABI

Note: this algorithm is still too simplisitic nd won't work universally.
It might by that a single float is passed in xmm0 or xmm1

for example if struct has alignment gap:
struct {float f; double d}

or if struct ends with a single float aligned on 8 byte:
struct {int a; int b; float c;}

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

Item was removed:
- ----- Method: ThreadedX64FFIPlugin>>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: #'sqInt *'>
- 	<var: #calloutState type: #'CalloutState *'>
- 	<inline: true>
- 	self subclassResponsibility!

Item was removed:
- ----- Method: ThreadedX64FFIPlugin>>returnStructInRegisters: (in category 'marshalling') -----
- returnStructInRegisters: returnStructSize
- 	"Answer if a struct result of a given size is returned in memory or not."
- 	self subclassResponsibility!

Item was changed:
  ----- Method: ThreadedX64SysVFFIPlugin>>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: #'sqInt *'>
  	<var: #calloutState type: #'CalloutState *'>
  	<inline: true>
  	| roundedSize doubleType floatType numDoubleRegisters numIntegerRegisters passField0InXmmReg passField1InXmmReg |
  	structSize <= 16 ifTrue:
  		["See sec 3.2.3 of http://people.freebsd.org/~obrien/amd64-elf-abi.pdf. (dravft version 0.90).
  		  All of the folowing are passed in registers:
  			typedef struct { long a; } s0;
  			typedef struct { double a; } s1;
  			typedef struct { long a; double b; } s2;
  			typedef struct { int a; int b; double c; } s2a;
  			typedef struct { short a; short b; short c; short d; double e; } s2b;
  			typedef struct { long a; float b; } s2f;
  			typedef struct { long a; float b; float c; } s2g;
  		  but not ones like this:
  			typedef struct { int a; float b; int c; float d; } s2h;"
+ 		 doubleType := FFITypeDoubleFloat << FFIAtomicTypeShift + FFIFlagAtomic + 8.
+ 		 floatType := FFITypeSingleFloat << FFIAtomicTypeShift + FFIFlagAtomic + 4.
- 		 doubleType := FFITypeDoubleFloat << FFIAtomicTypeShift + FFITypeDoubleFloat.
- 		 floatType := FFITypeDoubleFloat << FFIAtomicTypeShift + FFITypeSingleFloat.
  		 passField0InXmmReg := doubleType = ((self cCoerce: argSpec to: #'int *') at: 1) "0th field is struct type and size"
  								or: [floatType = ((self cCoerce: argSpec to: #'int *') at: 1)
  									and: [floatType = ((self cCoerce: argSpec to: #'int *') at: 2)]].
  		 structSize <= 8
  			ifTrue:
  				[numDoubleRegisters := passField0InXmmReg ifTrue: [1] ifFalse: [0].
  				 numIntegerRegisters := 1 - numDoubleRegisters]
  			ifFalse:
  				[passField1InXmmReg := doubleType = ((self cCoerce: argSpec to: #'int *') at: argSpecSize - 1) "Nth field is last field of struct"
  										or: [floatType = ((self cCoerce: argSpec to: #'int *') at: argSpecSize - 2)
  											and: [floatType = ((self cCoerce: argSpec to: #'int *') at: argSpecSize - 1)]].
  				 numDoubleRegisters := (passField0InXmmReg ifTrue: [1] ifFalse: [0]) + (passField1InXmmReg ifTrue: [1] ifFalse: [0]).
  				 numIntegerRegisters := 2 - numDoubleRegisters].
  		 (calloutState floatRegisterIndex + numDoubleRegisters <= NumFloatRegArgs
  		  and: [calloutState integerRegisterIndex + numIntegerRegisters <= NumIntRegArgs]) ifTrue:
  			[passField0InXmmReg
  				ifTrue: [self ffiPushDoubleFloat: ((self cCoerceSimple: pointer to: #'double *') at: 0) in: calloutState]
  				ifFalse: [self ffiPushSignedLongLong: ((self cCoerceSimple: pointer to: #'long long *') at: 0) in: calloutState].
  			 structSize > 8 ifTrue:
  				[passField1InXmmReg
  					ifTrue: [self ffiPushDoubleFloat: ((self cCoerceSimple: pointer to: #'double *') at: 1) in: calloutState]
  					ifFalse: [self ffiPushSignedLongLong: ((self cCoerceSimple: pointer to: #'long long *') at: 1) in: calloutState]].
  			 ^0]].
  
  	roundedSize := structSize + 7 bitClear: 7.
  	calloutState currentArg + roundedSize > calloutState limit ifTrue:
  		 [^FFIErrorCallFrameTooBig].
  	self memcpy: calloutState currentArg _: (self cCoerceSimple: pointer to: 'char *') _: structSize.
  	calloutState currentArg: calloutState currentArg + roundedSize.
  	^0!



More information about the Vm-dev mailing list