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! |
Free forum by Nabble | Edit this page |