Douglas McPherson uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-djm.682.mcz
==================== Summary ====================
Name: VMMaker.oscog-djm.682 Author: djm Time: 19 April 2014, 5:59:52.572 pm UUID: e7def840-4cc1-464d-a20e-29498ae5a99a Ancestors: VMMaker.oscog-eem.681
ThreadedARMFFIPlugin - make progress on passing and returning structs but there are still outstanding bugs - 22/23 existing FFI tests pass, but there are many new tests yet to include to stress combined register and stack usage for parameter passing
=============== Diff against VMMaker.oscog-eem.681 ===============
Item was changed: ----- Method: ThreadedARMFFIPlugin>>dispatchFunctionPointer:with:with:with:with: (in category 'callout support') ----- dispatchFunctionPointer: aFunctionPointer with: int1 with: int2 with: int3 with: int4 "In C aFunctionPointer is void (*aFunctionPointer)(int, int, int, int)" <cmacro: '(aFunctionPointer, int1, int2, int3, int4) (aFunctionPointer)(int1, int2, int3, int4)'> + ^self + perform: aFunctionPointer + with: int1 + with: int2 + with: int3 + with: int4! - ^self perform: aFunctionPointer!
Item was changed: ----- Method: ThreadedARMFFIPlugin>>ffiCalloutTo:SpecOnStack:in: (in category 'callout support') ----- ffiCalloutTo: procAddr SpecOnStack: specOnStack in: calloutState <var: #procAddr type: #'void *'> <var: #calloutState type: #'CalloutState *'> "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 | <var: #floatRet type: #double> <var: #intRet type: #usqLong> <inline: true> self cppIf: COGMTVM ifTrue: [(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue: [myThreadIndex := interpreterProxy disownVM: 0]].
- self msg: 'calling out to C function'. - self registerArgsSlop + self cStackAlignment > 0 ifTrue: [self setsp: calloutState argVector].
calloutState floatRegisterIndex > 0 ifTrue: [self dummyFloatFunction: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 0)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 2)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 4)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 6)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 8)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 10)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 12)) to: 'double *') at: 0) with: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 14)) to: 'double *') at: 0) ].
atomicType := self atomicTypeOf: calloutState ffiRetHeader. atomicType = FFITypeSingleFloat ifTrue: [floatRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(int, int, int, int)') with: (calloutState integerRegisters at: 0) with: (calloutState integerRegisters at: 1) with: (calloutState integerRegisters at: 2) with: (calloutState integerRegisters at: 3)]. atomicType = FFITypeDoubleFloat ifTrue: [floatRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(int, int, int, int)') 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 (*)(int, int, int, int)') 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]].
"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: [^self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState].
(calloutState ffiRetHeader anyMask: FFIFlagStructure) ifTrue: [^self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]. (atomicType = FFITypeSingleFloat or: [atomicType = FFITypeDoubleFloat]) ifTrue: [^interpreterProxy methodReturnValue: (interpreterProxy floatObjectOf: floatRet)].
^interpreterProxy methodReturnValue: (self ffiCreateIntegralResultOop: intRet ofAtomicType: atomicType in: calloutState)!
Item was changed: ----- Method: ThreadedARMFFIPlugin>>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> + | availableRegisterSpace stackPartSize roundedSize | + + availableRegisterSpace := (NumIntRegArgs - calloutState integerRegisterIndex) * 4. + stackPartSize := structSize. + availableRegisterSpace > 0 + ifTrue: + [structSize <= availableRegisterSpace + ifTrue: + ["all in registers" + stackPartSize = 0. + self + mem: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') + cp: pointer + y: structSize. + calloutState integerRegisterIndex: calloutState integerRegisterIndex + (structSize + 3 bitShift: -2) ] + ifFalse: + ["some in registers rest on stack" + stackPartSize := structSize - availableRegisterSpace. + self + mem: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') + cp: pointer + y: availableRegisterSpace. + calloutState integerRegisterIndex: NumIntRegArgs]]. + + stackPartSize > 0 + ifTrue: + [roundedSize := stackPartSize + 3 bitClear: 3. + calloutState currentArg + roundedSize > calloutState limit ifTrue: + [^FFIErrorCallFrameTooBig]. + self mem: calloutState currentArg cp: (self addressOf: ((self cCoerceSimple: pointer to: 'char *') at: availableRegisterSpace)) y: stackPartSize. + calloutState currentArg: calloutState currentArg + roundedSize]. + - self shouldBeImplemented. ^0!
Item was removed: - ----- Method: ThreadedARMFFIPlugin>>ffiPushUnsignedLong:in: (in category 'marshalling') ----- - ffiPushUnsignedLong: value in: calloutState - <var: #calloutState type: #'CalloutState *'> - <inline: true> - self shouldBeImplemented. - ^0!
Item was changed: ----- Method: ThreadedARMFFIPlugin>>returnStructInRegisters: (in category 'marshalling') ----- returnStructInRegisters: returnStructSize "Answer if a struct result of a given size is returned in memory or not." + ^returnStructSize <= 4! - ^false!
vm-dev@lists.squeakfoundation.org