<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>