[Vm-dev] VM Maker: VMMaker.oscog-nice.1980.mcz
commits at source.squeak.org
commits at source.squeak.org
Sun Nov 6 08:41:25 UTC 2016
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1980.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1980
Author: nice
Time: 6 November 2016, 9:39:52.658038 am
UUID: eeec5e65-ce2b-4698-930d-209077139d02
Ancestors: VMMaker.oscog-nice.1979
Fix shifting in ffiCreateIntegralResultOop:ofAtomicType:in: like already applied in primitiveFFIIntegerAt/Put
Properly count the parameters passed by register for X64 Win64: there are only 4 of them, either floating point or integer or any mix, but not 4 floating point and 4 integers.
Fix passing structure by value in X64 Win64: size must be a power of 2, and it's not possible to pass a 16bytes structure into two registers.
=============== Diff against VMMaker.oscog-nice.1979 ===============
Item was removed:
- ----- Method: ThreadedFFICalloutStateForX64>>floatRegisterIndex: (in category 'accessing') -----
- floatRegisterIndex: anObject
-
- ^floatRegisterIndex := anObject!
Item was removed:
- ----- Method: ThreadedFFICalloutStateForX64>>floatRegisters: (in category 'accessing') -----
- floatRegisters: anObject
-
- ^floatRegisters := anObject!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64>>incrementFloatRegisterIndex (in category 'accessing') -----
+ incrementFloatRegisterIndex
+ ^floatRegisterIndex := floatRegisterIndex + 1!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64>>incrementIntegerRegisterIndex (in category 'accessing') -----
+ incrementIntegerRegisterIndex
+ ^integerRegisterIndex := integerRegisterIndex + 1!
Item was removed:
- ----- Method: ThreadedFFICalloutStateForX64>>integerRegisterIndex: (in category 'accessing') -----
- integerRegisterIndex: anObject
-
- ^integerRegisterIndex := anObject!
Item was removed:
- ----- Method: ThreadedFFICalloutStateForX64>>integerRegisters: (in category 'accessing') -----
- integerRegisters: anObject
-
- ^integerRegisters := anObject!
Item was changed:
ThreadedFFICalloutStateForX64 subclass: #ThreadedFFICalloutStateForX64Win64
+ instanceVariableNames: 'floatRegisterSignature'
- instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'VMMaker-Plugins-FFI'!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64Win64 class>>instVarNamesAndTypesForTranslationDo: (in category 'translation') -----
+ instVarNamesAndTypesForTranslationDo: aBinaryBlock
+ "enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a ThreadedFFICalloutState struct."
+
+ ThreadedFFICalloutStateForX64 instVarNamesAndTypesForTranslationDo: aBinaryBlock.
+ ThreadedFFICalloutStateForX64Win64 instVarNames do:
+ [:ivn|
+ aBinaryBlock
+ value: ivn
+ value: (ivn caseOf: {
+ ['floatRegisterSignature'] -> [#int] }
+ otherwise:
+ [#sqInt])]!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64Win64>>floatRegisterSignature (in category 'accessing') -----
+ floatRegisterSignature
+ ^floatRegisterSignature!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64Win64>>incrementFloatRegisterIndex (in category 'accessing') -----
+ incrementFloatRegisterIndex
+ "There are only 4 args passed by register int or float.
+ So we can't distinguish the float index from the integer index.
+ So we have to increment both.
+
+ Consequently, floatRegisterIndex cannot be used anymore to detect presence of float parameter.
+ However, we set a signature bitmap indicating which register position is used to pass a float.
+
+ IMPLEMENTATION NOTES:
+ There are code generator hacks that bypass the accessors.
+ So we cannot just redefine the method floatRegisterIndex as ^integerRegisterIndex.
+ Instead we must maintain the two indices"
+
+ floatRegisterSignature := floatRegisterSignature + (1 << floatRegisterIndex).
+ ^integerRegisterIndex := floatRegisterIndex := floatRegisterIndex + 1!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64Win64>>incrementIntegerRegisterIndex (in category 'accessing') -----
+ incrementIntegerRegisterIndex
+ "There are only 4 args passed by register int or float.
+ So we can't distinguish the float index from the integer index.
+ So we have to increment both.
+
+ IMPLEMENTATION NOTES:
+ There are code generator hacks that bypass the accessors.
+ So we cannot just redefine the method floatRegisterIndex as ^integerRegisterIndex.
+ Instead we must maintain the two indices"
+
+ ^floatRegisterIndex := integerRegisterIndex := integerRegisterIndex + 1!
Item was added:
+ ----- Method: ThreadedFFICalloutStateForX64Win64>>initialize (in category 'initialize-release') -----
+ initialize
+ super initialize.
+ floatRegisterSignature := 0.!
Item was changed:
----- Method: ThreadedFFIPlugin>>ffiCreateIntegralResultOop:ofAtomicType:in: (in category 'callout support') -----
ffiCreateIntegralResultOop: retVal ofAtomicType: atomicType in: calloutState
<inline: true>
<var: #calloutState type: #'CalloutState *'>
<var: #retVal type: #usqLong>
"Callout support. Return the appropriate oop for the given atomic type"
| shift value mask byteSize |
<var: 'value' type: #usqLong>
<var: 'mask' type: #usqLong>
self assert: atomicType < FFITypeSingleFloat.
atomicType = FFITypeBool ifTrue:
["Make sure bool honors the byte size requested"
byteSize := calloutState ffiRetHeader bitAnd: FFIStructSizeMask.
value := byteSize = (self sizeof: retVal)
ifTrue:[retVal]
+ ifFalse:[retVal bitAnd: 1 asUnsignedLongLong << (byteSize * 8) - 1].
- ifFalse:[retVal bitAnd: 1 << (byteSize * 8) - 1].
^value = 0
ifTrue:[interpreterProxy falseObject]
ifFalse:[interpreterProxy trueObject]].
atomicType <= FFITypeSignedInt ifTrue:
["these are all generall integer returns"
atomicType <= (BytesPerWord = 8 ifTrue: [FFITypeSignedInt] ifFalse: [FFITypeSignedShort]) ifTrue:
["byte/short. first extract partial word, then sign extend"
shift := (BytesPerWord = 8 and: [atomicType >= FFITypeUnsignedInt])
ifTrue: [32]
ifFalse: [(atomicType >> 1) * 8]. "# of significant bits"
+ value := retVal bitAnd: (1 asUnsignedLongLong << shift - 1).
- value := retVal bitAnd: (1 asUnsignedLong << shift - 1).
(atomicType anyMask: 1) ifTrue:
["make the guy signed"
+ mask := 1 asUnsignedLongLong << (shift-1).
- mask := 1 asUnsignedLong << (shift-1).
value := (value bitAnd: mask-1) - (value bitAnd: mask)].
^interpreterProxy integerObjectOf: value].
"Word sized integer return"
^(atomicType anyMask: 1)
ifTrue:[interpreterProxy signedMachineIntegerFor: retVal] "signed return"
ifFalse:[interpreterProxy positiveMachineIntegerFor: retVal]]. "unsigned return"
"longlong, char"
^(atomicType >> 1) = (FFITypeSignedLongLong >> 1)
ifTrue:
[(atomicType anyMask: 1)
ifTrue:[interpreterProxy signed64BitIntegerFor: retVal] "signed return"
ifFalse:[interpreterProxy positive64BitIntegerFor: retVal]]
ifFalse:
[interpreterProxy characterObjectOf: (retVal bitAnd: 16rFF)]!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushDoubleFloat:in: (in category 'marshalling') -----
ffiPushDoubleFloat: value in: calloutState
<var: #value type: #double>
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState floatRegisterIndex < NumFloatRegArgs
ifTrue:
[calloutState floatRegisters at: calloutState floatRegisterIndex put: value.
+ calloutState incrementFloatRegisterIndex]
- calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy storeFloatAtPointer: calloutState currentArg from: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushPointer:in: (in category 'marshalling') -----
ffiPushPointer: pointer in: calloutState
<var: #pointer type: #'void *'>
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: pointer asInteger.
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: pointer.
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSignedByte:in: (in category 'marshalling') -----
ffiPushSignedByte: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed char').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed char').
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSignedChar:in: (in category 'marshalling') -----
ffiPushSignedChar: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed char').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed char').
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSignedInt:in: (in category 'marshalling') -----
ffiPushSignedInt: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: value.
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0
!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSignedLongLong:in: (in category 'marshalling') -----
ffiPushSignedLongLong: value in: calloutState
<var: #value type: #sqLong>
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #usqInt).
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSignedShort:in: (in category 'marshalling') -----
ffiPushSignedShort: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed short').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed short').
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushSingleFloat:in: (in category 'marshalling') -----
ffiPushSingleFloat: value in: calloutState
<var: #value type: #float>
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState floatRegisterIndex < NumFloatRegArgs
ifTrue:
[(self cCoerce: calloutState floatRegisters + calloutState floatRegisterIndex to: #'float *') at: 0 put: value.
+ calloutState incrementFloatRegisterIndex]
- calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy storeFloatAtPointer: calloutState currentArg from: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushUnsignedByte:in: (in category 'marshalling') -----
ffiPushUnsignedByte: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned char').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned char').
calloutState currentArg: calloutState currentArg + WordSize].
^0
!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushUnsignedChar:in: (in category 'marshalling') -----
ffiPushUnsignedChar: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned char').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned char').
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushUnsignedInt:in: (in category 'marshalling') -----
ffiPushUnsignedInt: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: value.
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0
!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushUnsignedLongLong:in: (in category 'marshalling') -----
ffiPushUnsignedLongLong: value in: calloutState
<var: #value type: #usqLong>
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: value.
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: value.
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
----- Method: ThreadedX64FFIPlugin>>ffiPushUnsignedShort:in: (in category 'marshalling') -----
ffiPushUnsignedShort: value in: calloutState
<var: #calloutState type: #'CalloutState *'>
<inline: true>
calloutState integerRegisterIndex < NumIntRegArgs
ifTrue:
[calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned short').
+ calloutState incrementIntegerRegisterIndex]
- calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]
ifFalse:
[calloutState currentArg + WordSize > calloutState limit ifTrue:
[^FFIErrorCallFrameTooBig].
interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned short').
calloutState currentArg: calloutState currentArg + WordSize].
^0!
Item was changed:
ThreadedX64FFIPlugin subclass: #ThreadedX64Win64FFIPlugin
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'VMMaker-Plugins-FFI'!
+ !ThreadedX64Win64FFIPlugin commentStamp: 'nice 8/10/2016 19:23' prior: 0!
+ This subclass is for the Win64 x86-64 ABI. The Win64 ABI uses 4 integer registers or 4 double-precision floating-point registers or a mix of the two. See w.g. https://msdn.microsoft.com/en-us/library/ms235286.aspx, or google for "Overview of x64 Calling Conventions - MSDN - Microsoft".
- !ThreadedX64Win64FFIPlugin commentStamp: 'eem 2/16/2016 19:39' prior: 0!
- This subclass is for the Win64 x86-64 ABI. The System V ABI uses 4 integer registers and 4 double-precision floating-point registers. See w.g. https://msdn.microsoft.com/en-us/library/ms235286.aspx, or google for "Overview of x64 Calling Conventions - MSDN - Microsoft".
Note that unlike the System V x86-64 ABI, the Win64 ABI does /not/ decompose structs passed by value across available parameter registers.!
Item was added:
+ ----- Method: ThreadedX64Win64FFIPlugin class>>calloutStateClass (in category 'translation') -----
+ calloutStateClass
+ ^ThreadedFFICalloutStateForX64Win64!
Item was changed:
----- Method: ThreadedX64Win64FFIPlugin>>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)'>
"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 loadFloatRegs oop |
<var: #floatRet type: #double>
<var: #intRet type: #usqLong>
<inline: true>
self cCode: '' inSmalltalk: [loadFloatRegs := #used. loadFloatRegs class].
self cppIf: COGMTVM ifTrue:
[(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:
[myThreadIndex := interpreterProxy disownVM: 0]].
self registerArgsSlop + self cStackAlignment > 0 ifTrue:
[self setsp: calloutState argVector].
+ calloutState floatRegisterSignature > 0 ifTrue:
- calloutState floatRegisterIndex > 0 ifTrue:
[self
load: (calloutState floatRegisters at: 0)
Flo: (calloutState floatRegisters at: 1)
at: (calloutState floatRegisters at: 2)
Re: (calloutState floatRegisters at: 3)
gs: (calloutState floatRegisters at: 4)].
atomicType := self atomicTypeOf: calloutState ffiRetHeader.
(atomicType >> 1) = (FFITypeSingleFloat >> 1)
ifTrue:
[atomicType = FFITypeSingleFloat
ifTrue:
[floatRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)]
ifFalse: "atomicType = FFITypeDoubleFloat"
[floatRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)]]
ifFalse:
[intRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'usqLong (*)(long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)].
"undo any callee argument pops because it may confuse stack management with the alloca."
(self isCalleePopsConvention: calloutState callFlags) ifTrue:
[self setsp: calloutState argVector].
self cppIf: COGMTVM ifTrue:
[(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:
[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:
[oop := self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]
ifFalse:
[oop := self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState].
^oop].
(atomicType >> 1) = (FFITypeSingleFloat >> 1)
ifTrue:
[oop := interpreterProxy floatObjectOf: floatRet]
ifFalse:
[oop := self ffiCreateIntegralResultOop: intRet
ofAtomicType: atomicType
in: calloutState].
^interpreterProxy methodReturnValue: oop!
Item was changed:
----- Method: ThreadedX64Win64FFIPlugin>>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 *'>
+ <var: #arg type: #usqLong>
<inline: true>
structSize <= 0 ifTrue:
[^FFIErrorStructSize].
+ (structSize <= WordSize
- (structSize <= 16
and: [(structSize bitAnd: structSize - 1) = 0 "a.k.a. structSize isPowerOfTwo"]) ifTrue:
+ [| arg |
+ self mem: (self addressOf: arg) cp: pointer y: structSize.
+ ^self ffiPushUnsignedLongLong: arg in: calloutState].
- [^self ffiPushUnsignedLongLong: (self cCoerceSimple: pointer to: #usqLong) in: calloutState].
"For now just push the pointer; we should copy the struct to the outgoing stack frame!!!!"
self flag: 'quick hack'.
^self ffiPushPointer: pointer in: calloutState!
Item was changed:
----- Method: ThreadedX64Win64FFIPlugin>>returnStructInRegisters: (in category 'marshalling') -----
returnStructInRegisters: returnStructSize
"Answer if a struct result of a given size is returned in memory or not."
+ ^returnStructSize <= WordSize and: ["returnStructSize isPowerOfTwo" (returnStructSize bitAnd: returnStructSize-1) = 0]!
- ^returnStructSize <= WordSize!
More information about the Vm-dev
mailing list