<div dir="ltr">Original commit message at:<br><a href="http://smalltalkhub.com/?_escaped_fragment_=/%7Enice/NiceVMExperiments/commits#%21/%7Enice/NiceVMExperiments/commits" target="_blank">http://smalltalkhub.com/?_<wbr>escaped_fragment_=/~nice/<wbr>NiceVMExperiments/commits#!/~<wbr>nice/NiceVMExperiments/commits</a><br><br><div class="gmail-description">VMMaker.oscogLLP64-nice.1924<span><p>Work on the X64-WIN64 ABI
references:
msdn X64 return values <a href="https://msdn.microsoft.com/en-us/library/7572ztz4.aspx">https://msdn.microsoft.com/en-us/library/7572ztz4.aspx</a>
msdn X64 parameter passing <a href="https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx">https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx</a></p>

<p>There are only 4 params passed by register, whatever int (or pointer) or float
So we cannot distinguish float register index and integer resgister index.</p>

<p>Correct parameter passing of struct:
- 8 bytes max are allowed for passing by value not 16
- pass a copy of contents, not of pointer</p>

<p>Correct return value of struct: don't forget that the byte length must be a power of two for returning by register</p>

<p>Correct (fake) passing of float registers: there are only 4 registers at most, not 5.</p></span></div><br></div><div class="gmail_extra"><br><div class="gmail_quote">2016-11-06 9:41 GMT+01:00  <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1980.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/<wbr>VMMaker/VMMaker.oscog-nice.<wbr>1980.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-nice.1980<br>
Author: nice<br>
Time: 6 November 2016, 9:39:52.658038 am<br>
UUID: eeec5e65-ce2b-4698-930d-<wbr>209077139d02<br>
Ancestors: VMMaker.oscog-nice.1979<br>
<br>
Fix shifting in ffiCreateIntegralResultOop:<wbr>ofAtomicType:in: like already applied in primitiveFFIIntegerAt/Put<br>
<br>
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.<br>
<br>
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.<br>
<br>
=============== Diff against VMMaker.oscog-nice.1979 ===============<br>
<br>
Item was removed:<br>
- ----- Method: ThreadedFFICalloutStateForX64><wbr>>floatRegisterIndex: (in category 'accessing') -----<br>
- floatRegisterIndex: anObject<br>
-<br>
-       ^floatRegisterIndex := anObject!<br>
<br>
Item was removed:<br>
- ----- Method: ThreadedFFICalloutStateForX64><wbr>>floatRegisters: (in category 'accessing') -----<br>
- floatRegisters: anObject<br>
-<br>
-       ^floatRegisters := anObject!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64><wbr>>incrementFloatRegisterIndex (in category 'accessing') -----<br>
+ incrementFloatRegisterIndex<br>
+       ^floatRegisterIndex := floatRegisterIndex + 1!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64><wbr>>incrementIntegerRegisterIndex (in category 'accessing') -----<br>
+ incrementIntegerRegisterIndex<br>
+       ^integerRegisterIndex := integerRegisterIndex + 1!<br>
<br>
Item was removed:<br>
- ----- Method: ThreadedFFICalloutStateForX64><wbr>>integerRegisterIndex: (in category 'accessing') -----<br>
- integerRegisterIndex: anObject<br>
-<br>
-       ^integerRegisterIndex := anObject!<br>
<br>
Item was removed:<br>
- ----- Method: ThreadedFFICalloutStateForX64><wbr>>integerRegisters: (in category 'accessing') -----<br>
- integerRegisters: anObject<br>
-<br>
-       ^integerRegisters := anObject!<br>
<br>
Item was changed:<br>
  ThreadedFFICalloutStateForX64 subclass: #<wbr>ThreadedFFICalloutStateForX64W<wbr>in64<br>
+       instanceVariableNames: 'floatRegisterSignature'<br>
-       instanceVariableNames: ''<br>
        classVariableNames: ''<br>
        poolDictionaries: ''<br>
        category: 'VMMaker-Plugins-FFI'!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64W<wbr>in64 class>><wbr>instVarNamesAndTypesForTransla<wbr>tionDo: (in category 'translation') -----<br>
+ instVarNamesAndTypesForTransla<wbr>tionDo: aBinaryBlock<br>
+       "enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a ThreadedFFICalloutState struct."<br>
+<br>
+       ThreadedFFICalloutStateForX64 instVarNamesAndTypesForTransla<wbr>tionDo: aBinaryBlock.<br>
+       ThreadedFFICalloutStateForX64W<wbr>in64 instVarNames do:<br>
+               [:ivn|<br>
+               aBinaryBlock<br>
+                       value: ivn<br>
+                       value: (ivn caseOf: {<br>
+                                               ['floatRegisterSignature']      -> [#int] }<br>
+                                       otherwise:<br>
+                                               [#sqInt])]!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64W<wbr>in64>>floatRegisterSignature (in category 'accessing') -----<br>
+ floatRegisterSignature<br>
+       ^floatRegisterSignature!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64W<wbr>in64>><wbr>incrementFloatRegisterIndex (in category 'accessing') -----<br>
+ incrementFloatRegisterIndex<br>
+       "There are only 4 args passed by register int or float.<br>
+       So we can't distinguish the float index from the integer index.<br>
+       So we have to increment both.<br>
+<br>
+       Consequently, floatRegisterIndex cannot be used anymore to detect presence of float parameter.<br>
+       However, we set a signature bitmap indicating which register position is used to pass a float.<br>
+<br>
+       IMPLEMENTATION NOTES:<br>
+       There are code generator hacks that bypass the accessors.<br>
+       So we cannot just redefine the method floatRegisterIndex as ^integerRegisterIndex.<br>
+       Instead we must maintain the two indices"<br>
+<br>
+       floatRegisterSignature := floatRegisterSignature + (1 << floatRegisterIndex).<br>
+       ^integerRegisterIndex := floatRegisterIndex := floatRegisterIndex + 1!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64W<wbr>in64>><wbr>incrementIntegerRegisterIndex (in category 'accessing') -----<br>
+ incrementIntegerRegisterIndex<br>
+       "There are only 4 args passed by register int or float.<br>
+       So we can't distinguish the float index from the integer index.<br>
+       So we have to increment both.<br>
+<br>
+       IMPLEMENTATION NOTES:<br>
+       There are code generator hacks that bypass the accessors.<br>
+       So we cannot just redefine the method floatRegisterIndex as ^integerRegisterIndex.<br>
+       Instead we must maintain the two indices"<br>
+<br>
+       ^floatRegisterIndex := integerRegisterIndex := integerRegisterIndex + 1!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForX64W<wbr>in64>>initialize (in category 'initialize-release') -----<br>
+ initialize<br>
+       super initialize.<br>
+       floatRegisterSignature := 0.!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedFFIPlugin>><wbr>ffiCreateIntegralResultOop:<wbr>ofAtomicType:in: (in category 'callout support') -----<br>
  ffiCreateIntegralResultOop: retVal ofAtomicType: atomicType in: calloutState<br>
        <inline: true><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <var: #retVal type: #usqLong><br>
        "Callout support. Return the appropriate oop for the given atomic type"<br>
        | shift value mask byteSize |<br>
        <var: 'value' type: #usqLong><br>
        <var: 'mask' type: #usqLong><br>
        self assert: atomicType < FFITypeSingleFloat.<br>
<br>
        atomicType = FFITypeBool ifTrue:<br>
                ["Make sure bool honors the byte size requested"<br>
                 byteSize := calloutState ffiRetHeader bitAnd: FFIStructSizeMask.<br>
                 value := byteSize = (self sizeof: retVal)<br>
                                        ifTrue:[retVal]<br>
+                                       ifFalse:[retVal bitAnd: 1 asUnsignedLongLong << (byteSize * 8) - 1].<br>
-                                       ifFalse:[retVal bitAnd: 1 << (byteSize * 8) - 1].<br>
                 ^value = 0<br>
                        ifTrue:[interpreterProxy falseObject]<br>
                        ifFalse:[interpreterProxy trueObject]].<br>
        atomicType <= FFITypeSignedInt ifTrue:<br>
                ["these are all generall integer returns"<br>
                atomicType <= (BytesPerWord = 8 ifTrue: [FFITypeSignedInt] ifFalse: [FFITypeSignedShort]) ifTrue:<br>
                        ["byte/short. first extract partial word, then sign extend"<br>
                        shift := (BytesPerWord = 8 and: [atomicType >= FFITypeUnsignedInt])<br>
                                                ifTrue: [32]<br>
                                                ifFalse: [(atomicType >> 1) * 8]. "# of significant bits"<br>
+                       value := retVal bitAnd: (1 asUnsignedLongLong << shift - 1).<br>
-                       value := retVal bitAnd: (1 asUnsignedLong << shift - 1).<br>
                        (atomicType anyMask: 1) ifTrue:<br>
                                ["make the guy signed"<br>
+                               mask := 1 asUnsignedLongLong << (shift-1).<br>
-                               mask := 1 asUnsignedLong << (shift-1).<br>
                                value := (value bitAnd: mask-1) - (value bitAnd: mask)].<br>
                        ^interpreterProxy integerObjectOf: value].<br>
                "Word sized integer return"<br>
                ^(atomicType anyMask: 1)<br>
                        ifTrue:[interpreterProxy signedMachineIntegerFor: retVal] "signed return"<br>
                        ifFalse:[interpreterProxy positiveMachineIntegerFor: retVal]]. "unsigned return"<br>
<br>
        "longlong, char"<br>
        ^(atomicType >> 1) = (FFITypeSignedLongLong >> 1)<br>
                ifTrue:<br>
                        [(atomicType anyMask: 1)<br>
                                ifTrue:[interpreterProxy signed64BitIntegerFor: retVal] "signed return"<br>
                                ifFalse:[interpreterProxy positive64BitIntegerFor: retVal]]<br>
                ifFalse:<br>
                        [interpreterProxy characterObjectOf: (retVal bitAnd: 16rFF)]!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushDoubleFloat:in: (in category 'marshalling') -----<br>
  ffiPushDoubleFloat: value in: calloutState<br>
        <var: #value type: #double><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
<br>
        calloutState floatRegisterIndex < NumFloatRegArgs<br>
                ifTrue:<br>
                        [calloutState floatRegisters at: calloutState floatRegisterIndex put: value.<br>
+                        calloutState incrementFloatRegisterIndex]<br>
-                        calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy storeFloatAtPointer: calloutState currentArg from: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushPointer:in: (in category 'marshalling') -----<br>
  ffiPushPointer: pointer in: calloutState<br>
        <var: #pointer type: #'void *'><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: pointer asInteger.<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: pointer.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSignedByte:in: (in category 'marshalling') -----<br>
  ffiPushSignedByte: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed char').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed char').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSignedChar:in: (in category 'marshalling') -----<br>
  ffiPushSignedChar: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed char').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed char').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSignedInt:in: (in category 'marshalling') -----<br>
  ffiPushSignedInt: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: value.<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSignedLongLong:in: (in category 'marshalling') -----<br>
  ffiPushSignedLongLong: value in: calloutState<br>
        <var: #value type: #sqLong><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #usqInt).<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSignedShort:in: (in category 'marshalling') -----<br>
  ffiPushSignedShort: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'signed short').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'signed short').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushSingleFloat:in: (in category 'marshalling') -----<br>
  ffiPushSingleFloat: value in: calloutState<br>
        <var: #value type: #float><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
<br>
        calloutState floatRegisterIndex < NumFloatRegArgs<br>
                ifTrue:<br>
                        [(self cCoerce: calloutState floatRegisters + calloutState floatRegisterIndex to: #'float *') at: 0 put: value.<br>
+                        calloutState incrementFloatRegisterIndex]<br>
-                        calloutState floatRegisterIndex: calloutState floatRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy storeFloatAtPointer: calloutState currentArg from: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushUnsignedByte:in: (in category 'marshalling') -----<br>
  ffiPushUnsignedByte: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned char').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned char').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushUnsignedChar:in: (in category 'marshalling') -----<br>
  ffiPushUnsignedChar: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned char').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned char').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushUnsignedInt:in: (in category 'marshalling') -----<br>
  ffiPushUnsignedInt: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: value.<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0<br>
<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushUnsignedLongLong:in: (in category 'marshalling') -----<br>
  ffiPushUnsignedLongLong: value in: calloutState<br>
        <var: #value type: #usqLong><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: value.<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: value.<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64FFIPlugin>><wbr>ffiPushUnsignedShort:in: (in category 'marshalling') -----<br>
  ffiPushUnsignedShort: value in: calloutState<br>
        <var: #calloutState type: #'CalloutState *'><br>
        <inline: true><br>
        calloutState integerRegisterIndex < NumIntRegArgs<br>
                ifTrue:<br>
                        [calloutState integerRegisters at: calloutState integerRegisterIndex put: (self cCoerceSimple: value to: #'unsigned short').<br>
+                        calloutState incrementIntegerRegisterIndex]<br>
-                        calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
                ifFalse:<br>
                        [calloutState currentArg + WordSize > calloutState limit ifTrue:<br>
                                [^FFIErrorCallFrameTooBig].<br>
                         interpreterProxy longAt: calloutState currentArg put: (self cCoerceSimple: value to: #'unsigned short').<br>
                         calloutState currentArg: calloutState currentArg + WordSize].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ThreadedX64FFIPlugin subclass: #ThreadedX64Win64FFIPlugin<br>
        instanceVariableNames: ''<br>
        classVariableNames: ''<br>
        poolDictionaries: ''<br>
        category: 'VMMaker-Plugins-FFI'!<br>
<br>
+ !ThreadedX64Win64FFIPlugin commentStamp: 'nice 8/10/2016 19:23' prior: 0!<br>
+ 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. <a href="https://msdn.microsoft.com/en-us/library/ms235286.aspx" rel="noreferrer" target="_blank">https://msdn.microsoft.com/en-<wbr>us/library/ms235286.aspx</a>, or google for "Overview of x64 Calling Conventions - MSDN - Microsoft".<br>
- !ThreadedX64Win64FFIPlugin commentStamp: 'eem 2/16/2016 19:39' prior: 0!<br>
- 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. <a href="https://msdn.microsoft.com/en-us/library/ms235286.aspx" rel="noreferrer" target="_blank">https://msdn.microsoft.com/en-<wbr>us/library/ms235286.aspx</a>, or google for "Overview of x64 Calling Conventions - MSDN - Microsoft".<br>
<br>
  Note that unlike the System V x86-64 ABI, the Win64 ABI does /not/ decompose structs passed by value across available parameter registers.!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedX64Win64FFIPlugin class>>calloutStateClass (in category 'translation') -----<br>
+ calloutStateClass<br>
+       ^<wbr>ThreadedFFICalloutStateForX64W<wbr>in64!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64Win64FFIPlugin>><wbr>ffiCalloutTo:SpecOnStack:in: (in category 'callout support') -----<br>
  ffiCalloutTo: procAddr SpecOnStack: specOnStack in: calloutState<br>
        <var: #procAddr type: #'void *'><br>
        <var: #calloutState type: #'CalloutState *'><br>
        <var: #loadFloatRegs declareC: 'extern void loadFloatRegs(double, double, double, double)'><br>
        "Go out, call this guy and create the return value.  This *must* be inlined because of<br>
         the alloca of the outgoing stack frame in ffiCall:WithFlags:NumArgs:<wbr>Args:AndTypes:"<br>
        | myThreadIndex atomicType floatRet intRet loadFloatRegs oop |<br>
        <var: #floatRet type: #double><br>
        <var: #intRet type: #usqLong><br>
        <inline: true><br>
        self cCode: '' inSmalltalk: [loadFloatRegs := #used. loadFloatRegs class].<br>
        self cppIf: COGMTVM ifTrue:<br>
        [(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:<br>
                [myThreadIndex := interpreterProxy disownVM: 0]].<br>
<br>
        self registerArgsSlop + self cStackAlignment > 0 ifTrue:<br>
                [self setsp: calloutState argVector].<br>
<br>
+       calloutState floatRegisterSignature > 0 ifTrue:<br>
-       calloutState floatRegisterIndex > 0 ifTrue:<br>
                [self<br>
                        load: (calloutState floatRegisters at: 0)<br>
                        Flo: (calloutState floatRegisters at: 1)<br>
                        at: (calloutState floatRegisters at: 2)<br>
                        Re: (calloutState floatRegisters at: 3)<br>
                        gs: (calloutState floatRegisters at: 4)].<br>
<br>
        atomicType := self atomicTypeOf: calloutState ffiRetHeader.<br>
        (atomicType >> 1) = (FFITypeSingleFloat >> 1)<br>
                ifTrue:<br>
                        [atomicType = FFITypeSingleFloat<br>
                                ifTrue:<br>
                                        [floatRet := self<br>
                                                dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(long, long, long, long)')<br>
                                                with: (calloutState integerRegisters at: 0)<br>
                                                with: (calloutState integerRegisters at: 1)<br>
                                                with: (calloutState integerRegisters at: 2)<br>
                                                with: (calloutState integerRegisters at: 3)]<br>
                                ifFalse: "atomicType = FFITypeDoubleFloat"<br>
                                        [floatRet := self<br>
                                                dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(long, long, long, long)')<br>
                                                with: (calloutState integerRegisters at: 0)<br>
                                                with: (calloutState integerRegisters at: 1)<br>
                                                with: (calloutState integerRegisters at: 2)<br>
                                                with: (calloutState integerRegisters at: 3)]]<br>
                ifFalse:<br>
                        [intRet := self<br>
                                dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'usqLong (*)(long, long, long, long)')<br>
                                with: (calloutState integerRegisters at: 0)<br>
                                with: (calloutState integerRegisters at: 1)<br>
                                with: (calloutState integerRegisters at: 2)<br>
                                with: (calloutState integerRegisters at: 3)].<br>
        "undo any callee argument pops because it may confuse stack management with the alloca."<br>
        (self isCalleePopsConvention: calloutState callFlags) ifTrue:<br>
                [self setsp: calloutState argVector].<br>
<br>
        self cppIf: COGMTVM ifTrue:<br>
        [(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:<br>
                [interpreterProxy ownVM: myThreadIndex]].<br>
<br>
        (calloutState ffiRetHeader anyMask: FFIFlagPointer+<wbr>FFIFlagStructure) ifTrue:<br>
                ["Note: Order is important here since FFIFlagPointer + FFIFlagStructure is used to represent<br>
                 'typedef void* VoidPointer' and VoidPointer must be returned as pointer *not* as struct."<br>
                 (calloutState ffiRetHeader anyMask: FFIFlagPointer)<br>
                        ifTrue:<br>
                                [oop := self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]<br>
                        ifFalse:<br>
                                [oop := self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState].<br>
                 ^oop].<br>
<br>
        (atomicType >> 1) = (FFITypeSingleFloat >> 1)<br>
                ifTrue:<br>
                        [oop := interpreterProxy floatObjectOf: floatRet]<br>
                ifFalse:<br>
                        [oop := self ffiCreateIntegralResultOop: intRet<br>
                                                ofAtomicType: atomicType<br>
                                                in: calloutState].<br>
        ^interpreterProxy methodReturnValue: oop!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64Win64FFIPlugin>><wbr>ffiPushStructure:ofSize:<wbr>typeSpec:ofLength:in: (in category 'marshalling') -----<br>
  ffiPushStructure: pointer ofSize: structSize typeSpec: argSpec ofLength: argSpecSize in: calloutState<br>
        <var: #pointer type: #'void *'><br>
        <var: #argSpec type: #'sqInt *'><br>
        <var: #calloutState type: #'CalloutState *'><br>
+       <var: #arg type: #usqLong><br>
        <inline: true><br>
        structSize <= 0 ifTrue:<br>
                [^FFIErrorStructSize].<br>
+       (structSize <= WordSize<br>
-       (structSize <= 16<br>
         and: [(structSize bitAnd: structSize - 1) = 0 "a.k.a. structSize isPowerOfTwo"]) ifTrue:<br>
+               [| arg |<br>
+               self mem: (self addressOf: arg) cp: pointer y: structSize.<br>
+               ^self ffiPushUnsignedLongLong: arg in: calloutState].<br>
-               [^self ffiPushUnsignedLongLong: (self cCoerceSimple: pointer to: #usqLong) in: calloutState].<br>
<br>
        "For now just push the pointer; we should copy the struct to the outgoing stack frame!!!!"<br>
        self flag: 'quick hack'.<br>
        ^self ffiPushPointer: pointer in: calloutState!<br>
<br>
Item was changed:<br>
  ----- Method: ThreadedX64Win64FFIPlugin>><wbr>returnStructInRegisters: (in category 'marshalling') -----<br>
  returnStructInRegisters: returnStructSize<br>
        "Answer if a struct result of a given size is returned in memory or not."<br>
+       ^returnStructSize <= WordSize and: ["returnStructSize isPowerOfTwo" (returnStructSize bitAnd: returnStructSize-1) = 0]!<br>
-       ^returnStructSize <= WordSize!<br>
<br>
</blockquote></div><br></div>