From e1f63d78f437b25df2490c5d9f5eea1b6f5656fc Mon Sep 17 00:00:00 2001 From: Eliot Miranda Date: Sat, 11 Mar 2023 18:04:33 -0800 Subject: [PATCH] CogVM source as per VMMaker.oscog-eem.3310 ThreadedFFIPlugin. Fix ThreadedFFIPlugin>>ffiCall:ArgArrayOrNil:NumArgs:'s use of ffiCheckReturn:With:in: so ffiCheckReturn:With:in: can be inlined. ThreadedARM64FFIPlugin. pass structures as defined by the ARM Procedure Call Standard for the ARM 64-bit Architecture, IHI0055B_aapcs64.pdf, 22nd May 2013. Fixes the crashes guarded for by FFIPluginTests>>#arm64Check. --- src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c | 390 +++++++---- .../SqueakFFIPrims/ARM64AppleFFIPlugin.c | 658 ++++++++++++------ src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c | 600 ++++++++++------ src/plugins/SqueakFFIPrims/IA32FFIPlugin.c | 390 +++++++---- src/plugins/SqueakFFIPrims/RiscV64FFIPlugin.c | 592 ++++++++++------ src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c | 451 +++++++----- .../SqueakFFIPrims/X64Win64FFIPlugin.c | 403 ++++++----- 7 files changed, 2212 insertions(+), 1272 deletions(-) diff --git a/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c b/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c index bc21a9294e..3f8d13b31b 100644 --- a/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedARM32FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedARM32FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedARM32FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedARM32FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedARM32FFIPlugin VMMaker.oscog-eem.3268 uuid: #define MaxNumArgs 15 #define NumFloatRegArgs 16 #define NumIntRegArgs 4 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" typedef struct { char *argVector; @@ -229,7 +229,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -531,7 +530,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "ARM32FFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "ARM32FFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -2242,37 +2241,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = ((calloutState->structReturnSize)) <= BytesPerWord); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -3140,12 +3108,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3184,7 +3152,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3192,13 +3160,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3206,7 +3174,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3214,7 +3182,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3224,10 +3192,39 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= BytesPerWord); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3262,11 +3259,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -3283,11 +3280,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3334,7 +3331,7 @@ primitiveCallout(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l8; + goto l9; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3381,7 +3378,7 @@ primitiveCallout(void) retOop = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l8; + goto l9; } #if SPURVM @@ -3403,7 +3400,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3428,7 +3425,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr = (&intRet); @@ -3447,7 +3444,7 @@ primitiveCallout(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3461,7 +3458,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -3480,18 +3477,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed32BitIntegerFor(intRet) : positive32BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3512,14 +3509,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3530,12 +3527,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3544,13 +3541,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -3560,20 +3557,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -3581,13 +3578,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -3595,7 +3592,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3603,7 +3600,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3613,10 +3610,39 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= BytesPerWord); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3636,13 +3662,13 @@ primitiveCallout(void) else { if ((((calloutState1->currentArg)) + BytesPerWord) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l12; + goto l15; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + BytesPerWord); } err1 = 0; - l12: /* end ffiPushPointer:in: */; + l15: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -3650,11 +3676,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs1; i2 += 1) { @@ -3670,11 +3696,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -3721,7 +3747,7 @@ primitiveCallout(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l14; + goto l17; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3753,7 +3779,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -3766,9 +3792,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l14; + goto l17; } #if SPURVM @@ -3790,7 +3816,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3815,7 +3841,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = (&intRet1); @@ -3834,7 +3860,7 @@ primitiveCallout(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -3848,7 +3874,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -3867,18 +3893,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed32BitIntegerFor(intRet1) : positive32BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -3899,13 +3925,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4039,12 +4065,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -4083,7 +4109,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -4091,13 +4117,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -4105,7 +4131,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4115,7 +4141,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4125,10 +4151,39 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= BytesPerWord); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4163,11 +4218,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -4186,11 +4241,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -4237,7 +4292,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l8; + goto l9; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -4286,7 +4341,7 @@ primitiveCalloutWithArgs(void) retOop = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l8; + goto l9; } #if SPURVM @@ -4308,7 +4363,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4333,7 +4388,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr = (&intRet); @@ -4352,7 +4407,7 @@ primitiveCalloutWithArgs(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4366,7 +4421,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -4385,18 +4440,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed32BitIntegerFor(intRet) : positive32BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4417,14 +4472,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4441,12 +4496,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -4455,13 +4510,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -4471,20 +4526,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -4492,13 +4547,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -4506,7 +4561,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4516,7 +4571,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4526,10 +4581,39 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= BytesPerWord); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4549,13 +4633,13 @@ primitiveCalloutWithArgs(void) else { if ((((calloutState1->currentArg)) + BytesPerWord) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l12; + goto l15; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + BytesPerWord); } err1 = 0; - l12: /* end ffiPushPointer:in: */; + l15: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -4563,11 +4647,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs; i2 += 1) { @@ -4585,11 +4669,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -4636,7 +4720,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l14; + goto l17; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -4670,7 +4754,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4683,9 +4767,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l14; + goto l17; } #if SPURVM @@ -4707,7 +4791,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4732,7 +4816,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = (&intRet1); @@ -4751,7 +4835,7 @@ primitiveCalloutWithArgs(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4765,7 +4849,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4784,18 +4868,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed32BitIntegerFor(intRet1) : positive32BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4816,13 +4900,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } diff --git a/src/plugins/SqueakFFIPrims/ARM64AppleFFIPlugin.c b/src/plugins/SqueakFFIPrims/ARM64AppleFFIPlugin.c index 0a110ad2a2..b6ecd4be85 100644 --- a/src/plugins/SqueakFFIPrims/ARM64AppleFFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/ARM64AppleFFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedARM64AppleFFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedARM64AppleFFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedARM64AppleFFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedARM64AppleFFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedARM64AppleFFIPlugin VMMaker.oscog-eem.3268 #define MaxNumArgs 15 #define NumFloatRegArgs 8 #define NumIntRegArgs 8 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" typedef struct { char *argVector; @@ -248,7 +248,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -309,6 +308,7 @@ static sqInt setReturnRegisterandCallwithArgsArray(sqLong structAddr, sqLong pro static sqInt sizeField(sqInt alienOop); static sqInt startOfData(sqInt alienOop); static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); +static sqInt structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); /*** Variables ***/ @@ -552,7 +552,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "ARM64AppleFFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "ARM64AppleFFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -1392,6 +1392,7 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c sqInt misAlignedBytes11; sqInt misAlignedBytes110; sqInt misAlignedBytes111; + sqInt misAlignedBytes112; sqInt misAlignedBytes12; sqInt misAlignedBytes13; sqInt misAlignedBytes14; @@ -1408,6 +1409,7 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c sqInt misAlignedBytes24; sqInt misAlignedBytes3; sqInt misAlignedBytes31; + sqInt misAlignedBytes32; sqInt misAlignedBytes4; sqInt misAlignedBytes41; sqInt misAlignedBytes5; @@ -1434,8 +1436,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c sqInt spec; sqInt specOop; sqInt specType; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; sqInt typeSpec; @@ -1527,8 +1527,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec2, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -1536,27 +1537,36 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); + } + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); + if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; } - else { - availableRegisterSpace = 0; + /* begin alignCurrentArgOf:to: */ + misAlignedBytes22 = (((sqInt)((calloutState->currentArg)))) & (7); + if (misAlignedBytes22 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes22)); } - (calloutState->integerRegisterIndex = NumIntRegArgs); + memcpy((calloutState->currentArg), ptrAddress, structSize); + (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); - if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes110 = (((sqInt)((calloutState->currentArg)))) & (7); + misAlignedBytes110 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); if (misAlignedBytes110 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes110)); + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes110)); } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); - (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); } return 0; } @@ -1596,8 +1606,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -1605,28 +1616,37 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes21 = (((sqInt)((calloutState->currentArg)))) & (7); - if (misAlignedBytes21 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes21)); + misAlignedBytes31 = (((sqInt)((calloutState->currentArg)))) & (7); + if (misAlignedBytes31 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes31)); } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + /* begin alignCurrentArgOf:to: */ + misAlignedBytes111 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); + if (misAlignedBytes111 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes111)); + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -1646,9 +1666,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes22 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); - if (misAlignedBytes22 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes22)); + misAlignedBytes21 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); + if (misAlignedBytes21 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes21)); } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); @@ -1837,9 +1857,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes111 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); - if (misAlignedBytes111 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes111)); + misAlignedBytes112 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); + if (misAlignedBytes112 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes112)); } longAtput((calloutState->currentArg), pointer1); (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); @@ -1881,9 +1901,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes31 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); - if (misAlignedBytes31 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes31)); + misAlignedBytes32 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); + if (misAlignedBytes32 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes32)); } longAtput((calloutState->currentArg), pointer3); (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); @@ -2545,37 +2565,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -2910,13 +2899,13 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) sqInt availableRegisterSpace1; sqInt misAlignedBytes; sqInt misAlignedBytes1; + sqInt misAlignedBytes11; sqInt misAlignedBytes2; + sqInt misAlignedBytes3; void *ptrAddress; sqInt ptrClass; sqInt roundedSize; sqInt roundedSize1; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; @@ -2950,8 +2939,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -2959,27 +2949,36 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); + } + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); + if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; } - else { - availableRegisterSpace = 0; + /* begin alignCurrentArgOf:to: */ + misAlignedBytes2 = (((sqInt)((calloutState->currentArg)))) & (7); + if (misAlignedBytes2 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes2)); } - (calloutState->integerRegisterIndex = NumIntRegArgs); + memcpy((calloutState->currentArg), ptrAddress, structSize); + (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); - if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes1 = (((sqInt)((calloutState->currentArg)))) & (7); + misAlignedBytes1 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); if (misAlignedBytes1 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes1)); + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes1)); } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); - (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); } return 0; } @@ -3019,8 +3018,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -3028,28 +3028,37 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } /* begin alignCurrentArgOf:to: */ - misAlignedBytes2 = (((sqInt)((calloutState->currentArg)))) & (7); - if (misAlignedBytes2 != 0) { - (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes2)); + misAlignedBytes3 = (((sqInt)((calloutState->currentArg)))) & (7); + if (misAlignedBytes3 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (8 - misAlignedBytes3)); } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + /* begin alignCurrentArgOf:to: */ + misAlignedBytes11 = (((sqInt)((calloutState->currentArg)))) & (BytesPerWord - 1); + if (misAlignedBytes11 != 0) { + (calloutState->currentArg = ((calloutState->currentArg)) + (BytesPerWord - misAlignedBytes11)); + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -3525,12 +3534,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3569,7 +3578,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3577,13 +3586,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3591,7 +3600,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3599,7 +3608,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3609,10 +3618,39 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3635,11 +3673,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3682,11 +3720,11 @@ primitiveCallout(void) ownVM(myThreadIndex); if (atomicType == FFITypeDoubleFloat) { result1 = floatObjectOf(((((floatRet.d)).doubles))[0]); - goto l8; + goto l9; } if (atomicType == FFITypeSingleFloat) { result1 = floatObjectOf(((((floatRet.f)).floats))[0]); - goto l8; + goto l9; } if (specSize > ((calloutState->structReturnSize))) { ((((floatRet.f)).floats))[1] = (((((floatRet.f)).floats))[2]); @@ -3711,7 +3749,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -3766,7 +3804,7 @@ primitiveCallout(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -3788,7 +3826,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3813,7 +3851,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -3832,7 +3870,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3846,7 +3884,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -3867,18 +3905,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3899,14 +3937,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3917,12 +3955,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3931,13 +3969,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -3947,20 +3985,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -3968,13 +4006,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -3982,7 +4020,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3990,7 +4028,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4000,10 +4038,39 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4025,11 +4092,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -4072,11 +4139,11 @@ primitiveCallout(void) ownVM(myThreadIndex1); if (atomicType2 == FFITypeDoubleFloat) { result2 = floatObjectOf(((((floatRet1.d)).doubles))[0]); - goto l14; + goto l17; } if (atomicType2 == FFITypeSingleFloat) { result2 = floatObjectOf(((((floatRet1.f)).floats))[0]); - goto l14; + goto l17; } if (specSize1 > ((calloutState1->structReturnSize))) { ((((floatRet1.f)).floats))[1] = (((((floatRet1.f)).floats))[2]); @@ -4101,7 +4168,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -4141,7 +4208,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4154,9 +4221,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -4178,7 +4245,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4203,7 +4270,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -4222,7 +4289,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4236,7 +4303,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4257,18 +4324,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4289,13 +4356,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4450,12 +4517,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -4494,7 +4561,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -4502,13 +4569,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -4516,7 +4583,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4526,7 +4593,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4536,10 +4603,39 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4564,11 +4660,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -4611,11 +4707,11 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex); if (atomicType == FFITypeDoubleFloat) { result1 = floatObjectOf(((((floatRet.d)).doubles))[0]); - goto l8; + goto l9; } if (atomicType == FFITypeSingleFloat) { result1 = floatObjectOf(((((floatRet.f)).floats))[0]); - goto l8; + goto l9; } if (specSize > ((calloutState->structReturnSize))) { ((((floatRet.f)).floats))[1] = (((((floatRet.f)).floats))[2]); @@ -4642,7 +4738,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -4699,7 +4795,7 @@ primitiveCalloutWithArgs(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -4721,7 +4817,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4746,7 +4842,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -4765,7 +4861,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4779,7 +4875,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -4800,18 +4896,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4832,14 +4928,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4856,12 +4952,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -4870,13 +4966,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -4886,20 +4982,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -4907,13 +5003,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -4921,7 +5017,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4931,7 +5027,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4941,10 +5037,39 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4968,11 +5093,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -5015,11 +5140,11 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex1); if (atomicType2 == FFITypeDoubleFloat) { result2 = floatObjectOf(((((floatRet1.d)).doubles))[0]); - goto l14; + goto l17; } if (atomicType2 == FFITypeSingleFloat) { result2 = floatObjectOf(((((floatRet1.f)).floats))[0]); - goto l14; + goto l17; } if (specSize1 > ((calloutState1->structReturnSize))) { ((((floatRet1.f)).floats))[1] = (((((floatRet1.f)).floats))[2]); @@ -5046,7 +5171,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -5088,7 +5213,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -5101,9 +5226,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -5125,7 +5250,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -5150,7 +5275,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -5169,7 +5294,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -5183,7 +5308,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -5204,18 +5329,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -5236,13 +5361,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -6734,6 +6859,14 @@ startOfData(sqInt alienOop) : longAt((alienOop + BaseHeaderSize) + BytesPerOop)); } + +/* See IHI0055B_aapcs64.pdf + 4.3.5.1 Homogeneous Floating-point Aggregates (HFA) + An Homogeneous Floating-point Aggregate (HFA) is an Homogeneous Aggregate + with a + Fundamental Data Type that is a Floating-Point type and at most four + uniquely addressable members. */ + /* ThreadedARM64FFIPlugin>>#structIsHomogenousFloatArrayOfSize:typeSpec:ofLength: */ static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) @@ -6765,6 +6898,83 @@ structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned in } +/* See IHI0055B_aapcs64.pdf + 4.1.2 Short Vectors + A short vector is a machine type that is composed of repeated instances of + one fundamental integral + or floating- point type. It may be 8 or 16 bytes in total size. A short + vector has a base type that is the + fundamental integral or floating-point type from which it is composed, but + its alignment is always the + same as its total size. The number of elements in the short vector is + always such that the type is fully + packed. For example, an 8-byte short vector may contain 8 unsigned byte + elements, 4 unsigned half-word + elements, 2 single-precision floating-point elements, or any other + combination where the product of + the number of elements and the size of an individual element is equal to + 8. Similarly, for 16-byte short + vectors the product of the number of elements and the size of the + individual elements must be 16. + + Elements in a short vector are numbered such that the lowest numbered + element (element 0) occupies + the lowest numbered bit (bit zero) in the vector and successive elements + take on progressively + increasing bit positions in the vector. When a short vector transferred + between registers and memory + it is treated as an opaque object. That is a short vector is stored in + memory as if it were stored with + a single STR of the entire register; a short vector is loaded from memory + using the corresponding LDR + instruction. On a little-endian system this means that element 0 will + always contain the lowest + addressed element of a short vector; on a big-endian system element 0 will + contain the highest-addressed + element of a short vector. + + A language binding may define extended types that map directly onto short + vectors. Short vectors + are not otherwise created spontaneously (for example because a user has + declared an aggregate + consisting of eight consecutive byte-sized objects). */ + + /* ThreadedARM64FFIPlugin>>#structIsHomogenousIntegerArrayOfSize:typeSpec:ofLength: */ +static sqInt +structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) +{ + unsigned int firstField; + sqInt idx; + sqInt sizeOfType; + sqInt typeOfFirstField; + sqInt typeSpec; + + if (!(structSize <= (4 * (sizeof(long))))) { + return 0; + } + /* begin atomicTypeOf: */ + typeSpec = (firstField = argSpec[1]); + typeOfFirstField = ((usqInt)((typeSpec & FFIAtomicTypeMask))) >> FFIAtomicTypeShift; + if (!(((typeOfFirstField >= FFITypeUnsignedInt8) && (typeOfFirstField <= FFITypeSignedInt64)))) { + return 0; + } + + /* { FFITypeUnsignedInt8. FFITypeUnsignedInt16. FFITypeUnsignedInt32. FFITypeUnsignedInt64. + FFITypeSignedInt8. FFITypeSignedInt16. FFITypeSignedInt32. FFITypeSignedInt64} collect: + [:typeOfFirstField| 1 << (typeOfFirstField >> 1 - 1)] */ + sizeOfType = 1U << ((((usqInt)(typeOfFirstField)) >> 1) - 1); + if ((sizeOfType * argSpecSize) > (4 * (sizeof(long)))) { + return 0; + } + for (idx = 2; idx < argSpecSize; idx += 1) { + if (firstField != (argSpec[idx])) { + return 0; + } + } + return 1; +} + + #ifdef SQUEAK_BUILTIN_PLUGIN static char _m[] = "SqueakFFIPrims"; diff --git a/src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c b/src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c index afefd36272..317a722205 100644 --- a/src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedARM64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedARM64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedARM64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedARM64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedARM64FFIPlugin VMMaker.oscog-eem.3268 uuid: #define MaxNumArgs 15 #define NumFloatRegArgs 8 #define NumIntRegArgs 8 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" typedef struct { char *argVector; @@ -248,7 +248,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -309,6 +308,7 @@ static sqInt setReturnRegisterandCallwithArgsArray(sqLong structAddr, sqLong pro static sqInt sizeField(sqInt alienOop); static sqInt startOfData(sqInt alienOop); static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); +static sqInt structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); /*** Variables ***/ @@ -552,7 +552,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "ARM64FFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "ARM64FFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -1283,8 +1283,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c sqInt spec; sqInt specOop; sqInt specType; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; sqInt typeSpec; @@ -1376,8 +1374,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec2, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -1385,23 +1384,28 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); - } - else { - availableRegisterSpace = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (ptrClass == (classByteArray())) { @@ -1440,8 +1444,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -1449,23 +1454,28 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -2239,37 +2249,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -2588,8 +2567,6 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) sqInt ptrClass; sqInt roundedSize; sqInt roundedSize1; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; @@ -2623,8 +2600,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -2632,23 +2610,28 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); - } - else { - availableRegisterSpace = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (ptrClass == (classByteArray())) { @@ -2687,8 +2670,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -2696,23 +2680,28 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -3183,12 +3172,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3227,7 +3216,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3235,13 +3224,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3249,7 +3238,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3257,7 +3246,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3267,10 +3256,39 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3293,11 +3311,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3340,11 +3358,11 @@ primitiveCallout(void) ownVM(myThreadIndex); if (atomicType == FFITypeDoubleFloat) { result1 = floatObjectOf(((((floatRet.d)).doubles))[0]); - goto l8; + goto l9; } if (atomicType == FFITypeSingleFloat) { result1 = floatObjectOf(((((floatRet.f)).floats))[0]); - goto l8; + goto l9; } if (specSize > ((calloutState->structReturnSize))) { ((((floatRet.f)).floats))[1] = (((((floatRet.f)).floats))[2]); @@ -3369,7 +3387,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -3424,7 +3442,7 @@ primitiveCallout(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -3446,7 +3464,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3471,7 +3489,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -3490,7 +3508,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3504,7 +3522,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -3525,18 +3543,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3557,14 +3575,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3575,12 +3593,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3589,13 +3607,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -3605,20 +3623,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -3626,13 +3644,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -3640,7 +3658,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3648,7 +3666,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3658,10 +3676,39 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3683,11 +3730,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -3730,11 +3777,11 @@ primitiveCallout(void) ownVM(myThreadIndex1); if (atomicType2 == FFITypeDoubleFloat) { result2 = floatObjectOf(((((floatRet1.d)).doubles))[0]); - goto l14; + goto l17; } if (atomicType2 == FFITypeSingleFloat) { result2 = floatObjectOf(((((floatRet1.f)).floats))[0]); - goto l14; + goto l17; } if (specSize1 > ((calloutState1->structReturnSize))) { ((((floatRet1.f)).floats))[1] = (((((floatRet1.f)).floats))[2]); @@ -3759,7 +3806,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -3799,7 +3846,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -3812,9 +3859,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -3836,7 +3883,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3861,7 +3908,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -3880,7 +3927,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -3894,7 +3941,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -3915,18 +3962,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -3947,13 +3994,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4108,12 +4155,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -4152,7 +4199,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -4160,13 +4207,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -4174,7 +4221,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4184,7 +4231,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4194,10 +4241,39 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4222,11 +4298,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -4269,11 +4345,11 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex); if (atomicType == FFITypeDoubleFloat) { result1 = floatObjectOf(((((floatRet.d)).doubles))[0]); - goto l8; + goto l9; } if (atomicType == FFITypeSingleFloat) { result1 = floatObjectOf(((((floatRet.f)).floats))[0]); - goto l8; + goto l9; } if (specSize > ((calloutState->structReturnSize))) { ((((floatRet.f)).floats))[1] = (((((floatRet.f)).floats))[2]); @@ -4300,7 +4376,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -4357,7 +4433,7 @@ primitiveCalloutWithArgs(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -4379,7 +4455,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4404,7 +4480,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -4423,7 +4499,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4437,7 +4513,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -4458,18 +4534,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4490,14 +4566,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4514,12 +4590,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -4528,13 +4604,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -4544,20 +4620,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -4565,13 +4641,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -4579,7 +4655,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4589,7 +4665,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4599,10 +4675,39 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4626,11 +4731,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -4673,11 +4778,11 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex1); if (atomicType2 == FFITypeDoubleFloat) { result2 = floatObjectOf(((((floatRet1.d)).doubles))[0]); - goto l14; + goto l17; } if (atomicType2 == FFITypeSingleFloat) { result2 = floatObjectOf(((((floatRet1.f)).floats))[0]); - goto l14; + goto l17; } if (specSize1 > ((calloutState1->structReturnSize))) { ((((floatRet1.f)).floats))[1] = (((((floatRet1.f)).floats))[2]); @@ -4704,7 +4809,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -4746,7 +4851,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4759,9 +4864,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -4783,7 +4888,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4808,7 +4913,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -4827,7 +4932,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4841,7 +4946,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4862,18 +4967,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4894,13 +4999,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -6392,6 +6497,14 @@ startOfData(sqInt alienOop) : longAt((alienOop + BaseHeaderSize) + BytesPerOop)); } + +/* See IHI0055B_aapcs64.pdf + 4.3.5.1 Homogeneous Floating-point Aggregates (HFA) + An Homogeneous Floating-point Aggregate (HFA) is an Homogeneous Aggregate + with a + Fundamental Data Type that is a Floating-Point type and at most four + uniquely addressable members. */ + /* ThreadedARM64FFIPlugin>>#structIsHomogenousFloatArrayOfSize:typeSpec:ofLength: */ static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) @@ -6423,6 +6536,83 @@ structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned in } +/* See IHI0055B_aapcs64.pdf + 4.1.2 Short Vectors + A short vector is a machine type that is composed of repeated instances of + one fundamental integral + or floating- point type. It may be 8 or 16 bytes in total size. A short + vector has a base type that is the + fundamental integral or floating-point type from which it is composed, but + its alignment is always the + same as its total size. The number of elements in the short vector is + always such that the type is fully + packed. For example, an 8-byte short vector may contain 8 unsigned byte + elements, 4 unsigned half-word + elements, 2 single-precision floating-point elements, or any other + combination where the product of + the number of elements and the size of an individual element is equal to + 8. Similarly, for 16-byte short + vectors the product of the number of elements and the size of the + individual elements must be 16. + + Elements in a short vector are numbered such that the lowest numbered + element (element 0) occupies + the lowest numbered bit (bit zero) in the vector and successive elements + take on progressively + increasing bit positions in the vector. When a short vector transferred + between registers and memory + it is treated as an opaque object. That is a short vector is stored in + memory as if it were stored with + a single STR of the entire register; a short vector is loaded from memory + using the corresponding LDR + instruction. On a little-endian system this means that element 0 will + always contain the lowest + addressed element of a short vector; on a big-endian system element 0 will + contain the highest-addressed + element of a short vector. + + A language binding may define extended types that map directly onto short + vectors. Short vectors + are not otherwise created spontaneously (for example because a user has + declared an aggregate + consisting of eight consecutive byte-sized objects). */ + + /* ThreadedARM64FFIPlugin>>#structIsHomogenousIntegerArrayOfSize:typeSpec:ofLength: */ +static sqInt +structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) +{ + unsigned int firstField; + sqInt idx; + sqInt sizeOfType; + sqInt typeOfFirstField; + sqInt typeSpec; + + if (!(structSize <= (4 * (sizeof(long))))) { + return 0; + } + /* begin atomicTypeOf: */ + typeSpec = (firstField = argSpec[1]); + typeOfFirstField = ((usqInt)((typeSpec & FFIAtomicTypeMask))) >> FFIAtomicTypeShift; + if (!(((typeOfFirstField >= FFITypeUnsignedInt8) && (typeOfFirstField <= FFITypeSignedInt64)))) { + return 0; + } + + /* { FFITypeUnsignedInt8. FFITypeUnsignedInt16. FFITypeUnsignedInt32. FFITypeUnsignedInt64. + FFITypeSignedInt8. FFITypeSignedInt16. FFITypeSignedInt32. FFITypeSignedInt64} collect: + [:typeOfFirstField| 1 << (typeOfFirstField >> 1 - 1)] */ + sizeOfType = 1U << ((((usqInt)(typeOfFirstField)) >> 1) - 1); + if ((sizeOfType * argSpecSize) > (4 * (sizeof(long)))) { + return 0; + } + for (idx = 2; idx < argSpecSize; idx += 1) { + if (firstField != (argSpec[idx])) { + return 0; + } + } + return 1; +} + + #ifdef SQUEAK_BUILTIN_PLUGIN static char _m[] = "SqueakFFIPrims"; diff --git a/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c b/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c index 2c7beb6b27..367e987897 100644 --- a/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedIA32FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedIA32FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedIA32FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedIA32FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -175,7 +175,7 @@ static char __buildInfo[] = "ThreadedIA32FFIPlugin VMMaker.oscog-eem.3268 uuid: #define FFITypeUnsignedInt8 2 #define FFITypeVoid 0 #define MaxNumArgs 15 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" typedef struct { char *argVector; @@ -221,7 +221,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -523,7 +522,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "IA32FFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "IA32FFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -1737,37 +1736,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = canReturnInRegistersStructOfSize((calloutState->structReturnSize))); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -2554,12 +2522,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -2598,7 +2566,7 @@ primitiveCallout(void) l3: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -2606,13 +2574,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -2620,7 +2588,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -2628,7 +2596,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -2638,10 +2606,39 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = canReturnInRegistersStructOfSize((calloutState->structReturnSize))); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -2670,11 +2667,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -2691,11 +2688,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -2734,7 +2731,7 @@ primitiveCallout(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l8; + goto l9; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -2781,7 +2778,7 @@ primitiveCallout(void) retOop = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l8; + goto l9; } #if SPURVM @@ -2803,7 +2800,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -2828,7 +2825,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr = (&intRet); @@ -2847,7 +2844,7 @@ primitiveCallout(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -2861,7 +2858,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -2880,18 +2877,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed32BitIntegerFor(intRet) : positive32BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -2912,14 +2909,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -2930,12 +2927,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -2944,13 +2941,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l17; + goto l12; } address11 = fetchPointerofObject(0, addressPtr1); - l17: /* end ffiContentsOfHandle:errCode: */; + l12: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l12; + goto l15; } if (address11 == 0) { @@ -2960,20 +2957,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l12; + goto l15; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l12; + goto l15; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l12: /* end ffiLoadCalloutAddress: */; + l15: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -2981,13 +2978,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -2995,7 +2992,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3003,7 +3000,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3013,10 +3010,39 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = canReturnInRegistersStructOfSize((calloutState1->structReturnSize))); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3031,12 +3057,12 @@ primitiveCallout(void) pointer1 = (calloutState1->limit); if ((((calloutState1->currentArg)) + 4) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l13; + goto l18; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + 4); err1 = 0; - l13: /* end ffiPushPointer:in: */; + l18: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -3044,11 +3070,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs1; i2 += 1) { @@ -3064,11 +3090,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -3107,7 +3133,7 @@ primitiveCallout(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l14; + goto l17; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3139,7 +3165,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -3152,9 +3178,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l14; + goto l17; } #if SPURVM @@ -3176,7 +3202,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3201,7 +3227,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = (&intRet1); @@ -3220,7 +3246,7 @@ primitiveCallout(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -3234,7 +3260,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -3253,18 +3279,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed32BitIntegerFor(intRet1) : positive32BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -3285,13 +3311,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -3424,12 +3450,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3468,7 +3494,7 @@ primitiveCalloutWithArgs(void) l3: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3476,13 +3502,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3490,7 +3516,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3500,7 +3526,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3510,10 +3536,39 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = canReturnInRegistersStructOfSize((calloutState->structReturnSize))); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3542,11 +3597,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -3565,11 +3620,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3608,7 +3663,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l8; + goto l9; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3657,7 +3712,7 @@ primitiveCalloutWithArgs(void) retOop = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l8; + goto l9; } #if SPURVM @@ -3679,7 +3734,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3704,7 +3759,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr = (&intRet); @@ -3723,7 +3778,7 @@ primitiveCalloutWithArgs(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3737,7 +3792,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -3756,18 +3811,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed32BitIntegerFor(intRet) : positive32BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3788,14 +3843,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3812,12 +3867,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3826,13 +3881,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l17; + goto l12; } address11 = fetchPointerofObject(0, addressPtr1); - l17: /* end ffiContentsOfHandle:errCode: */; + l12: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l12; + goto l15; } if (address11 == 0) { @@ -3842,20 +3897,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l12; + goto l15; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l12; + goto l15; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l12: /* end ffiLoadCalloutAddress: */; + l15: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -3863,13 +3918,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -3877,7 +3932,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3887,7 +3942,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3897,10 +3952,39 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = canReturnInRegistersStructOfSize((calloutState1->structReturnSize))); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3915,12 +3999,12 @@ primitiveCalloutWithArgs(void) pointer1 = (calloutState1->limit); if ((((calloutState1->currentArg)) + 4) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l13; + goto l18; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + 4); err1 = 0; - l13: /* end ffiPushPointer:in: */; + l18: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -3928,11 +4012,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs; i2 += 1) { @@ -3950,11 +4034,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -3993,7 +4077,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l14; + goto l17; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -4027,7 +4111,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4040,9 +4124,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l14; + goto l17; } #if SPURVM @@ -4064,7 +4148,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4089,7 +4173,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = (&intRet1); @@ -4108,7 +4192,7 @@ primitiveCalloutWithArgs(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4122,7 +4206,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4141,18 +4225,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed32BitIntegerFor(intRet1) : positive32BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4173,13 +4257,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } diff --git a/src/plugins/SqueakFFIPrims/RiscV64FFIPlugin.c b/src/plugins/SqueakFFIPrims/RiscV64FFIPlugin.c index 6f70d4cf4f..e73a12f6d3 100644 --- a/src/plugins/SqueakFFIPrims/RiscV64FFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/RiscV64FFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedRiscV64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedRiscV64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedRiscV64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedRiscV64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedRiscV64FFIPlugin VMMaker.oscog-eem.3268 uui #define MaxNumArgs 15 #define NumFloatRegArgs 8 #define NumIntRegArgs 8 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" typedef struct { char *argVector; @@ -249,7 +249,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -310,6 +309,7 @@ static sqInt setReturnRegisterandCallwithArgsArray(sqLong structAddr, sqLong pro static sqInt sizeField(sqInt alienOop); static sqInt startOfData(sqInt alienOop); static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); +static sqInt structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize); /*** Variables ***/ @@ -551,7 +551,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "RiscV64FFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "RiscV64FFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -1299,8 +1299,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c sqInt spec; sqInt specOop; sqInt specType; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; sqInt typeSpec; @@ -1392,8 +1390,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec2, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -1401,23 +1400,28 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); - } - else { - availableRegisterSpace = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (ptrClass == (classByteArray())) { @@ -1456,8 +1460,9 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -1465,23 +1470,28 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -2272,37 +2282,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -2621,8 +2600,6 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) sqInt ptrClass; sqInt roundedSize; sqInt roundedSize1; - sqInt stackPartSize; - sqInt stackPartSize1; sqInt structSize; sqInt structSize1; @@ -2656,8 +2633,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize = structSize; - if (availableRegisterSpace > 0) { + if ((structSize <= availableRegisterSpace) + && ((structSize <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize, argSpec, argSpecSize)))) { if (structSize <= availableRegisterSpace) { /* all in integer registers */ @@ -2665,23 +2643,28 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize = structSize - availableRegisterSpace; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace); - } - else { - availableRegisterSpace = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize > 0) { - roundedSize = (((stackPartSize + 3) | 3) - 3); + if (structSize <= 16) { + roundedSize = (((structSize + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace])), stackPartSize); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (ptrClass == (classByteArray())) { @@ -2720,8 +2703,9 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) else { availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * BytesPerWord; } - stackPartSize1 = structSize1; - if (availableRegisterSpace1 > 0) { + if ((structSize1 <= availableRegisterSpace1) + && ((structSize1 <= 16) + || (structIsHomogenousIntegerArrayOfSizetypeSpecofLength(structSize1, argSpec1, argSpecSize1)))) { if (structSize1 <= availableRegisterSpace1) { /* all in integer registers */ @@ -2729,23 +2713,28 @@ ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + ((((usqInt)((structSize1 + 7))) >> 3))); return 0; } - if (((calloutState->currentArg)) == ((calloutState->argVector))) { - stackPartSize1 = structSize1 - availableRegisterSpace1; - memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ptrAddress, availableRegisterSpace1); - } - else { - availableRegisterSpace1 = 0; - } - (calloutState->integerRegisterIndex = NumIntRegArgs); } - if (stackPartSize1 > 0) { - roundedSize1 = (((stackPartSize1 + 3) | 3) - 3); + if (structSize1 <= 16) { + roundedSize1 = (((structSize1 + 7) | 7) - 7); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } - memcpy((calloutState->currentArg), (&((((char *) ptrAddress))[availableRegisterSpace1])), stackPartSize1); + alignCurrentArgOfto(calloutState, 8); + memcpy((calloutState->currentArg), ptrAddress, structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); } + /* begin ffiPushPointer:in: */ + if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) { + ((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = (((sqInt)ptrAddress)); + (calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1); + } + else { + if ((((calloutState->currentArg)) + BytesPerWord) > ((calloutState->limit))) { + return FFIErrorCallFrameTooBig; + } + longAtput((calloutState->currentArg), ptrAddress); + (calloutState->currentArg = ((calloutState->currentArg)) + BytesPerWord); + } return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == BytesPerWord)) { @@ -3218,12 +3207,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3262,7 +3251,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3270,13 +3259,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3284,7 +3273,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3292,7 +3281,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3302,10 +3291,39 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3328,11 +3346,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3377,7 +3395,7 @@ primitiveCallout(void) } ownVM(myThreadIndex); result1 = floatObjectOf(doubleRet); - goto l8; + goto l9; } if (((((calloutState->ffiRetHeader)) & (FFIFlagPointer + FFIFlagStructure)) == FFIFlagStructure) && (structIsHomogenousFloatArrayOfSizetypeSpecofLength(((calloutState->ffiRetHeader)) & FFIStructSizeMask, ((unsigned int *) (firstIndexableField((calloutState->ffiRetSpec)))), ((specSize = byteSizeOf((calloutState->ffiRetSpec)))) / (sizeof(unsigned int))))) { @@ -3409,7 +3427,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -3464,7 +3482,7 @@ primitiveCallout(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -3486,7 +3504,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3511,7 +3529,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -3530,7 +3548,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3544,7 +3562,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -3565,18 +3583,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3597,14 +3615,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3615,12 +3633,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3629,13 +3647,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -3645,20 +3663,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -3666,13 +3684,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -3680,7 +3698,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3688,7 +3706,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3698,10 +3716,39 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3723,11 +3770,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -3772,7 +3819,7 @@ primitiveCallout(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(doubleRet1); - goto l14; + goto l17; } if (((((calloutState1->ffiRetHeader)) & (FFIFlagPointer + FFIFlagStructure)) == FFIFlagStructure) && (structIsHomogenousFloatArrayOfSizetypeSpecofLength(((calloutState1->ffiRetHeader)) & FFIStructSizeMask, ((unsigned int *) (firstIndexableField((calloutState1->ffiRetSpec)))), ((specSize1 = byteSizeOf((calloutState1->ffiRetSpec)))) / (sizeof(unsigned int))))) { @@ -3804,7 +3851,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -3844,7 +3891,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -3857,9 +3904,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -3881,7 +3928,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3906,7 +3953,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -3925,7 +3972,7 @@ primitiveCallout(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -3939,7 +3986,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -3960,18 +4007,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -3992,13 +4039,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4155,12 +4202,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -4199,7 +4246,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -4207,13 +4254,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -4221,7 +4268,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4231,7 +4278,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4241,10 +4288,39 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l4; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l4; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l4; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = ((calloutState->structReturnSize)) <= (2 * BytesPerWord)); + } + err = 0; + l4: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4269,11 +4345,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -4318,7 +4394,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex); result1 = floatObjectOf(doubleRet); - goto l8; + goto l9; } if (((((calloutState->ffiRetHeader)) & (FFIFlagPointer + FFIFlagStructure)) == FFIFlagStructure) && (structIsHomogenousFloatArrayOfSizetypeSpecofLength(((calloutState->ffiRetHeader)) & FFIStructSizeMask, ((unsigned int *) (firstIndexableField((calloutState->ffiRetSpec)))), ((specSize = byteSizeOf((calloutState->ffiRetSpec)))) / (sizeof(unsigned int))))) { @@ -4352,7 +4428,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop3), longLongRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop, oop3); result1 = retOop; - goto l8; + goto l9; } if (((calloutState->structReturnSize)) > (2 * BytesPerWord)) { intRet = 0; @@ -4409,7 +4485,7 @@ primitiveCalloutWithArgs(void) retOop1 = strOop; l5: /* end ffiReturnCStringFrom: */; result1 = retOop1; - goto l8; + goto l9; } #if SPURVM @@ -4431,7 +4507,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop1, returnType); result1 = retOop1; - goto l8; + goto l9; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4456,7 +4532,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l8; + goto l9; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr1 = ((calloutState->structReturnType) @@ -4475,7 +4551,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop2), longLongRetPtr1, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop2, oop2); result1 = retOop2; - goto l8; + goto l9; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4489,7 +4565,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l8; + goto l9; } if (atomicType <= FFITypeSignedInt32) { @@ -4510,18 +4586,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l8; + goto l9; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l8; + goto l9; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4542,14 +4618,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l8: /* end ffiCalloutTo:SpecOnStack:in: */; + l9: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4566,12 +4642,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -4580,13 +4656,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -4596,20 +4672,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -4617,13 +4693,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -4631,7 +4707,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4641,7 +4717,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4651,10 +4727,39 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l19; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l19; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = ((calloutState1->structReturnSize)) <= (2 * BytesPerWord)); + } + err1 = 0; + l19: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4678,11 +4783,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -4727,7 +4832,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(doubleRet1); - goto l14; + goto l17; } if (((((calloutState1->ffiRetHeader)) & (FFIFlagPointer + FFIFlagStructure)) == FFIFlagStructure) && (structIsHomogenousFloatArrayOfSizetypeSpecofLength(((calloutState1->ffiRetHeader)) & FFIStructSizeMask, ((unsigned int *) (firstIndexableField((calloutState1->ffiRetSpec)))), ((specSize1 = byteSizeOf((calloutState1->ffiRetSpec)))) / (sizeof(unsigned int))))) { @@ -4761,7 +4866,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop31), longLongRetPtr2, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop3, oop31); result2 = retOop3; - goto l14; + goto l17; } if (((calloutState1->structReturnSize)) > (2 * BytesPerWord)) { intRet1 = 0; @@ -4803,7 +4908,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop11 = nilObject(); - goto l11; + goto l13; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4816,9 +4921,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop11 = strOop1; - l11: /* end ffiReturnCStringFrom: */; + l13: /* end ffiReturnCStringFrom: */; result2 = retOop11; - goto l14; + goto l17; } #if SPURVM @@ -4840,7 +4945,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop11, returnType1); result2 = retOop11; - goto l14; + goto l17; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4865,7 +4970,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l14; + goto l17; } /* begin ffiReturnStruct:ofType:in: */ longLongRetPtr11 = ((calloutState1->structReturnType) @@ -4884,7 +4989,7 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop21), longLongRetPtr11, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop21, oop21); result2 = retOop21; - goto l14; + goto l17; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4898,7 +5003,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l14; + goto l17; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4919,18 +5024,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l14; + goto l17; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l14; + goto l17; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4951,13 +5056,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l14: /* end ffiCalloutTo:SpecOnStack:in: */; + l17: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -6448,6 +6553,14 @@ startOfData(sqInt alienOop) : longAt((alienOop + BaseHeaderSize) + BytesPerOop)); } + +/* See IHI0055B_aapcs64.pdf + 4.3.5.1 Homogeneous Floating-point Aggregates (HFA) + An Homogeneous Floating-point Aggregate (HFA) is an Homogeneous Aggregate + with a + Fundamental Data Type that is a Floating-Point type and at most four + uniquely addressable members. */ + /* ThreadedARM64FFIPlugin>>#structIsHomogenousFloatArrayOfSize:typeSpec:ofLength: */ static sqInt structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) @@ -6479,6 +6592,83 @@ structIsHomogenousFloatArrayOfSizetypeSpecofLength(sqInt structSize, unsigned in } +/* See IHI0055B_aapcs64.pdf + 4.1.2 Short Vectors + A short vector is a machine type that is composed of repeated instances of + one fundamental integral + or floating- point type. It may be 8 or 16 bytes in total size. A short + vector has a base type that is the + fundamental integral or floating-point type from which it is composed, but + its alignment is always the + same as its total size. The number of elements in the short vector is + always such that the type is fully + packed. For example, an 8-byte short vector may contain 8 unsigned byte + elements, 4 unsigned half-word + elements, 2 single-precision floating-point elements, or any other + combination where the product of + the number of elements and the size of an individual element is equal to + 8. Similarly, for 16-byte short + vectors the product of the number of elements and the size of the + individual elements must be 16. + + Elements in a short vector are numbered such that the lowest numbered + element (element 0) occupies + the lowest numbered bit (bit zero) in the vector and successive elements + take on progressively + increasing bit positions in the vector. When a short vector transferred + between registers and memory + it is treated as an opaque object. That is a short vector is stored in + memory as if it were stored with + a single STR of the entire register; a short vector is loaded from memory + using the corresponding LDR + instruction. On a little-endian system this means that element 0 will + always contain the lowest + addressed element of a short vector; on a big-endian system element 0 will + contain the highest-addressed + element of a short vector. + + A language binding may define extended types that map directly onto short + vectors. Short vectors + are not otherwise created spontaneously (for example because a user has + declared an aggregate + consisting of eight consecutive byte-sized objects). */ + + /* ThreadedARM64FFIPlugin>>#structIsHomogenousIntegerArrayOfSize:typeSpec:ofLength: */ +static sqInt +structIsHomogenousIntegerArrayOfSizetypeSpecofLength(sqInt structSize, unsigned int *argSpec, sqInt argSpecSize) +{ + unsigned int firstField; + sqInt idx; + sqInt sizeOfType; + sqInt typeOfFirstField; + sqInt typeSpec; + + if (!(structSize <= (4 * (sizeof(long))))) { + return 0; + } + /* begin atomicTypeOf: */ + typeSpec = (firstField = argSpec[1]); + typeOfFirstField = ((usqInt)((typeSpec & FFIAtomicTypeMask))) >> FFIAtomicTypeShift; + if (!(((typeOfFirstField >= FFITypeUnsignedInt8) && (typeOfFirstField <= FFITypeSignedInt64)))) { + return 0; + } + + /* { FFITypeUnsignedInt8. FFITypeUnsignedInt16. FFITypeUnsignedInt32. FFITypeUnsignedInt64. + FFITypeSignedInt8. FFITypeSignedInt16. FFITypeSignedInt32. FFITypeSignedInt64} collect: + [:typeOfFirstField| 1 << (typeOfFirstField >> 1 - 1)] */ + sizeOfType = 1U << ((((usqInt)(typeOfFirstField)) >> 1) - 1); + if ((sizeOfType * argSpecSize) > (4 * (sizeof(long)))) { + return 0; + } + for (idx = 2; idx < argSpecSize; idx += 1) { + if (firstField != (argSpec[idx])) { + return 0; + } + } + return 1; +} + + #ifdef SQUEAK_BUILTIN_PLUGIN static char _m[] = "SqueakFFIPrims"; diff --git a/src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c b/src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c index 7e6b861bb2..584a1b3a00 100644 --- a/src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedX64SysVFFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedX64SysVFFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedX64SysVFFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedX64SysVFFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedX64SysVFFIPlugin VMMaker.oscog-eem.3268 uui #define MaxNumArgs 15 #define NumFloatRegArgs 8 #define NumIntRegArgs 6 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" #define WordSize 8 typedef struct { @@ -266,7 +266,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -571,7 +570,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "X64SysVFFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "X64SysVFFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -2453,42 +2452,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - sqInt registerType; - - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - registerType = (((calloutState->structReturnSize)) <= (WordSize * 2) - ? registerTypeForStructSpecsOfLength(firstIndexableField((calloutState->ffiRetSpec)), slotSizeOf((calloutState->ffiRetSpec))) - : 6); - (calloutState->structReturnType = registerType); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -3471,6 +3434,8 @@ primitiveCallout(void) sqIntptr_t *ptr2; sqInt registerType; sqInt registerType1; + sqInt registerType11; + sqInt registerType2; sqInt requiredStackSize; sqInt requiredStackSize1; sqInt result; @@ -3536,12 +3501,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -3580,7 +3545,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -3588,13 +3553,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -3602,7 +3567,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3610,7 +3575,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3620,10 +3585,42 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l3; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l3; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l3; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + registerType = (((calloutState->structReturnSize)) <= (WordSize * 2) + ? registerTypeForStructSpecsOfLength(firstIndexableField((calloutState->ffiRetSpec)), slotSizeOf((calloutState->ffiRetSpec))) + : 6); + (calloutState->structReturnType = registerType); + } + err = 0; + l3: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3644,13 +3641,13 @@ primitiveCallout(void) else { if ((((calloutState->currentArg)) + WordSize) > ((calloutState->limit))) { err = FFIErrorCallFrameTooBig; - goto l8; + goto l9; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + WordSize); } err = 0; - l8: /* end ffiPushPointer:in: */; + l9: /* end ffiPushPointer:in: */; if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { @@ -3659,11 +3656,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -3680,11 +3677,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -3729,7 +3726,7 @@ primitiveCallout(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l6; + goto l7; } if (!returnStructByValue) { intRet = dispatchFunctionPointerwithwithwithwithwithwith(((sqInt (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address))), ((calloutState->integerRegisters))[0], ((calloutState->integerRegisters))[1], ((calloutState->integerRegisters))[2], ((calloutState->integerRegisters))[3], ((calloutState->integerRegisters))[4], ((calloutState->integerRegisters))[5]); @@ -3752,7 +3749,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet))) { retOop = nilObject(); - goto l3; + goto l6; } cString = ((char *) (((usqInt) intRet))); strLen = 0; @@ -3765,9 +3762,9 @@ primitiveCallout(void) strPtr[i1] = (cString[i1]); } retOop = strOop; - l3: /* end ffiReturnCStringFrom: */; + l6: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l6; + goto l7; } #if SPURVM @@ -3789,7 +3786,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, retType); result1 = retOop; - goto l6; + goto l7; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3814,7 +3811,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l6; + goto l7; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3828,7 +3825,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l6; + goto l7; } if (atomicType <= FFITypeSignedInt32) { @@ -3849,18 +3846,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l6; + goto l7; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l6; + goto l7; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l6; + goto l7; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3881,10 +3878,10 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - goto l6; + goto l7; } - registerType = (calloutState->structReturnType); - switch (registerType) { + registerType1 = (calloutState->structReturnType); + switch (registerType1) { case 0: sddRet = dispatchFunctionPointerwithwithwithwithwithwith(((SixteenByteReturnDD (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address))), ((calloutState->integerRegisters))[0], ((calloutState->integerRegisters))[1], ((calloutState->integerRegisters))[2], ((calloutState->integerRegisters))[3], ((calloutState->integerRegisters))[4], ((calloutState->integerRegisters))[5]); sRetPtr = ((void *)((&sddRet))); @@ -3921,7 +3918,7 @@ primitiveCallout(void) ownVM(myThreadIndex); ffiFail(FFIErrorWrongType); result1 = null; - goto l6; + goto l7; } ownVM(myThreadIndex); @@ -3942,14 +3939,14 @@ primitiveCallout(void) memcpy(firstIndexableField(oop1), sRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - l6: /* end ffiCalloutTo:SpecOnStack:in: */; + l7: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3960,12 +3957,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -3974,13 +3971,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -3990,20 +3987,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -4011,13 +4008,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -4025,7 +4022,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4033,7 +4030,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4043,10 +4040,42 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l15; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l15; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l15; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + registerType2 = (((calloutState1->structReturnSize)) <= (WordSize * 2) + ? registerTypeForStructSpecsOfLength(firstIndexableField((calloutState1->ffiRetSpec)), slotSizeOf((calloutState1->ffiRetSpec))) + : 6); + (calloutState1->structReturnType = registerType2); + } + err1 = 0; + l15: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4067,13 +4096,13 @@ primitiveCallout(void) else { if ((((calloutState1->currentArg)) + WordSize) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l14; + goto l17; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + WordSize); } err1 = 0; - l14: /* end ffiPushPointer:in: */; + l17: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -4081,11 +4110,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs1; i2 += 1) { @@ -4101,11 +4130,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -4150,7 +4179,7 @@ primitiveCallout(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l15; + goto l11; } if (!returnStructByValue1) { intRet1 = dispatchFunctionPointerwithwithwithwithwithwith(((sqInt (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address2))), ((calloutState1->integerRegisters))[0], ((calloutState1->integerRegisters))[1], ((calloutState1->integerRegisters))[2], ((calloutState1->integerRegisters))[3], ((calloutState1->integerRegisters))[4], ((calloutState1->integerRegisters))[5]); @@ -4173,7 +4202,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l12; + goto l16; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4186,9 +4215,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l12: /* end ffiReturnCStringFrom: */; + l16: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l15; + goto l11; } #if SPURVM @@ -4210,7 +4239,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, retType1); result2 = retOop2; - goto l15; + goto l11; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4235,7 +4264,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l15; + goto l11; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4249,7 +4278,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l15; + goto l11; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4270,18 +4299,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l15; + goto l11; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l15; + goto l11; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l15; + goto l11; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4302,10 +4331,10 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - goto l15; + goto l11; } - registerType1 = (calloutState1->structReturnType); - switch (registerType1) { + registerType11 = (calloutState1->structReturnType); + switch (registerType11) { case 0: sddRet1 = dispatchFunctionPointerwithwithwithwithwithwith(((SixteenByteReturnDD (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address2))), ((calloutState1->integerRegisters))[0], ((calloutState1->integerRegisters))[1], ((calloutState1->integerRegisters))[2], ((calloutState1->integerRegisters))[3], ((calloutState1->integerRegisters))[4], ((calloutState1->integerRegisters))[5]); sRetPtr1 = ((void *)((&sddRet1))); @@ -4342,7 +4371,7 @@ primitiveCallout(void) ownVM(myThreadIndex1); ffiFail(FFIErrorWrongType); result2 = null; - goto l15; + goto l11; } ownVM(myThreadIndex1); @@ -4363,13 +4392,13 @@ primitiveCallout(void) memcpy(firstIndexableField(oop11), sRetPtr1, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - l15: /* end ffiCalloutTo:SpecOnStack:in: */; + l11: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4452,6 +4481,8 @@ primitiveCalloutWithArgs(void) sqIntptr_t *ptr2; sqInt registerType; sqInt registerType1; + sqInt registerType11; + sqInt registerType2; sqInt requiredStackSize; sqInt requiredStackSize1; sqInt result; @@ -4521,12 +4552,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l9; + goto l10; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } /* begin ffiLoadCalloutAddress: */ @@ -4565,7 +4596,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l9; + goto l10; } /* must be array of arg types */ @@ -4573,13 +4604,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l9; + goto l10; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # else // COGMTVM @@ -4587,7 +4618,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l9; + goto l10; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4597,7 +4628,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l9; + goto l10; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4607,10 +4638,42 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l3; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l3; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l3; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + registerType = (((calloutState->structReturnSize)) <= (WordSize * 2) + ? registerTypeForStructSpecsOfLength(firstIndexableField((calloutState->ffiRetSpec)), slotSizeOf((calloutState->ffiRetSpec))) + : 6); + (calloutState->structReturnType = registerType); + } + err = 0; + l3: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l9; + goto l10; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4631,13 +4694,13 @@ primitiveCalloutWithArgs(void) else { if ((((calloutState->currentArg)) + WordSize) > ((calloutState->limit))) { err = FFIErrorCallFrameTooBig; - goto l8; + goto l9; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + WordSize); } err = 0; - l8: /* end ffiPushPointer:in: */; + l9: /* end ffiPushPointer:in: */; if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { @@ -4646,11 +4709,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } for (i = 1; i <= nArgs; i += 1) { @@ -4669,11 +4732,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l9; + goto l10; } # endif result = ffiFail(err); - goto l9; + goto l10; } } assert(!(failed())); @@ -4718,7 +4781,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l6; + goto l7; } if (!returnStructByValue) { intRet = dispatchFunctionPointerwithwithwithwithwithwith(((sqInt (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address))), ((calloutState->integerRegisters))[0], ((calloutState->integerRegisters))[1], ((calloutState->integerRegisters))[2], ((calloutState->integerRegisters))[3], ((calloutState->integerRegisters))[4], ((calloutState->integerRegisters))[5]); @@ -4743,7 +4806,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet))) { retOop = nilObject(); - goto l3; + goto l6; } cString = ((char *) (((usqInt) intRet))); strLen = 0; @@ -4756,9 +4819,9 @@ primitiveCalloutWithArgs(void) strPtr[i1] = (cString[i1]); } retOop = strOop; - l3: /* end ffiReturnCStringFrom: */; + l6: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l6; + goto l7; } #if SPURVM @@ -4780,7 +4843,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, retType); result1 = retOop; - goto l6; + goto l7; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4805,7 +4868,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l6; + goto l7; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4819,7 +4882,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l6; + goto l7; } if (atomicType <= FFITypeSignedInt32) { @@ -4840,18 +4903,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l6; + goto l7; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l6; + goto l7; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l6; + goto l7; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4872,10 +4935,10 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - goto l6; + goto l7; } - registerType = (calloutState->structReturnType); - switch (registerType) { + registerType1 = (calloutState->structReturnType); + switch (registerType1) { case 0: sddRet = dispatchFunctionPointerwithwithwithwithwithwith(((SixteenByteReturnDD (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address))), ((calloutState->integerRegisters))[0], ((calloutState->integerRegisters))[1], ((calloutState->integerRegisters))[2], ((calloutState->integerRegisters))[3], ((calloutState->integerRegisters))[4], ((calloutState->integerRegisters))[5]); sRetPtr = ((void *)((&sddRet))); @@ -4912,7 +4975,7 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex); ffiFail(FFIErrorWrongType); result1 = null; - goto l6; + goto l7; } ownVM(myThreadIndex); @@ -4935,14 +4998,14 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop1), sRetPtr, (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - l6: /* end ffiCalloutTo:SpecOnStack:in: */; + l7: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l9: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4959,12 +5022,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l18; + goto l20; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } /* begin ffiLoadCalloutAddress: */ @@ -4973,13 +5036,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l13; + goto l18; } address11 = fetchPointerofObject(0, addressPtr1); - l13: /* end ffiContentsOfHandle:errCode: */; + l18: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l17; + goto l12; } if (address11 == 0) { @@ -4989,20 +5052,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l17; + goto l12; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l17; + goto l12; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l17: /* end ffiLoadCalloutAddress: */; + l12: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l18; + goto l20; } /* must be array of arg types */ @@ -5010,13 +5073,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l18; + goto l20; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # else // COGMTVM @@ -5024,7 +5087,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l18; + goto l20; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -5034,7 +5097,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l18; + goto l20; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -5044,10 +5107,42 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l15; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l15; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l15; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + registerType2 = (((calloutState1->structReturnSize)) <= (WordSize * 2) + ? registerTypeForStructSpecsOfLength(firstIndexableField((calloutState1->ffiRetSpec)), slotSizeOf((calloutState1->ffiRetSpec))) + : 6); + (calloutState1->structReturnType = registerType2); + } + err1 = 0; + l15: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l18; + goto l20; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -5068,13 +5163,13 @@ primitiveCalloutWithArgs(void) else { if ((((calloutState1->currentArg)) + WordSize) > ((calloutState1->limit))) { err1 = FFIErrorCallFrameTooBig; - goto l14; + goto l17; } longAtput((calloutState1->currentArg), pointer1); (calloutState1->currentArg = ((calloutState1->currentArg)) + WordSize); } err1 = 0; - l14: /* end ffiPushPointer:in: */; + l17: /* end ffiPushPointer:in: */; if (err1 != 0) { /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { @@ -5082,11 +5177,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } for (i2 = 1; i2 <= nArgs; i2 += 1) { @@ -5104,11 +5199,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l18; + goto l20; } # endif ffiFail(err1); - goto l18; + goto l20; } } assert(!(failed())); @@ -5153,7 +5248,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l15; + goto l11; } if (!returnStructByValue1) { intRet1 = dispatchFunctionPointerwithwithwithwithwithwith(((sqInt (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address2))), ((calloutState1->integerRegisters))[0], ((calloutState1->integerRegisters))[1], ((calloutState1->integerRegisters))[2], ((calloutState1->integerRegisters))[3], ((calloutState1->integerRegisters))[4], ((calloutState1->integerRegisters))[5]); @@ -5178,7 +5273,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l12; + goto l16; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -5191,9 +5286,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l12: /* end ffiReturnCStringFrom: */; + l16: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l15; + goto l11; } #if SPURVM @@ -5215,7 +5310,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, retType1); result2 = retOop2; - goto l15; + goto l11; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -5240,7 +5335,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l15; + goto l11; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -5254,7 +5349,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l15; + goto l11; } if (atomicType2 <= FFITypeSignedInt32) { @@ -5275,18 +5370,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l15; + goto l11; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l15; + goto l11; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l15; + goto l11; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -5307,10 +5402,10 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - goto l15; + goto l11; } - registerType1 = (calloutState1->structReturnType); - switch (registerType1) { + registerType11 = (calloutState1->structReturnType); + switch (registerType11) { case 0: sddRet1 = dispatchFunctionPointerwithwithwithwithwithwith(((SixteenByteReturnDD (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) (((void *) address2))), ((calloutState1->integerRegisters))[0], ((calloutState1->integerRegisters))[1], ((calloutState1->integerRegisters))[2], ((calloutState1->integerRegisters))[3], ((calloutState1->integerRegisters))[4], ((calloutState1->integerRegisters))[5]); sRetPtr1 = ((void *)((&sddRet1))); @@ -5347,7 +5442,7 @@ primitiveCalloutWithArgs(void) ownVM(myThreadIndex1); ffiFail(FFIErrorWrongType); result2 = null; - goto l15; + goto l11; } ownVM(myThreadIndex1); @@ -5370,13 +5465,13 @@ primitiveCalloutWithArgs(void) memcpy(firstIndexableField(oop11), sRetPtr1, (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - l15: /* end ffiCalloutTo:SpecOnStack:in: */; + l11: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l18: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } diff --git a/src/plugins/SqueakFFIPrims/X64Win64FFIPlugin.c b/src/plugins/SqueakFFIPrims/X64Win64FFIPlugin.c index 0bdcce0204..c0800b6663 100644 --- a/src/plugins/SqueakFFIPrims/X64Win64FFIPlugin.c +++ b/src/plugins/SqueakFFIPrims/X64Win64FFIPlugin.c @@ -1,9 +1,9 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + VMPluginCodeGenerator VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 from - ThreadedX64Win64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 + ThreadedX64Win64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 */ -static char __buildInfo[] = "ThreadedX64Win64FFIPlugin VMMaker.oscog-eem.3268 uuid: b157851d-3135-4853-9b4a-b72296787205 " __DATE__ ; +static char __buildInfo[] = "ThreadedX64Win64FFIPlugin VMMaker.oscog-eem.3310 uuid: ccb9d141-68dd-4a1a-86b9-906b72753322 " __DATE__ ; #include "config.h" @@ -177,7 +177,7 @@ static char __buildInfo[] = "ThreadedX64Win64FFIPlugin VMMaker.oscog-eem.3268 uu #define MaxNumArgs 15 #define NumFloatRegArgs 4 #define NumIntRegArgs 4 -#define PluginVersionInfo " VMMaker.oscog-eem.3268" +#define PluginVersionInfo " VMMaker.oscog-eem.3310" #define WordSize 8 typedef struct { @@ -231,7 +231,6 @@ static void cleanupCalloutState(CalloutState *calloutState); static void * ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); -static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static sqLong ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); @@ -533,7 +532,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "X64Win64FFIPlugin VMMaker.oscog-eem.3268 " INT_EXT; +static const char *moduleName = "X64Win64FFIPlugin VMMaker.oscog-eem.3310 " INT_EXT; /*** Macros ***/ @@ -2267,38 +2266,6 @@ ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *c } -/* Make sure we can return an object of the given type */ - - /* ThreadedFFIPlugin>>#ffiCheckReturn:With:in: */ -static sqInt -ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) -{ - if (!(retClass == (nilObject()))) { - if (!(includesBehaviorThatOf(retClass, classExternalStructure()))) { - return FFIErrorBadReturn; - } - } - if (!((isWords(retSpec)) - && ((slotSizeOf(retSpec)) > 0))) { - return FFIErrorWrongType; - } - (calloutState->ffiRetSpec = retSpec); - (calloutState->ffiRetHeader = fetchLong32ofObject(0, retSpec)); - if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { - if (retClass == (nilObject())) { - return FFIErrorBadReturn; - } - } - if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { - (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); - /* begin encodeStructReturnTypeIn: */ - (calloutState->structReturnType = (((calloutState->structReturnSize)) <= WordSize) - && ((((calloutState->structReturnSize)) & (((calloutState->structReturnSize)) - 1)) == 0)); - } - return 0; -} - - /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError @@ -3178,12 +3145,12 @@ primitiveCallout(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l10; + goto l11; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l10; + goto l11; } /* begin ffiLoadCalloutAddress: */ @@ -3222,7 +3189,7 @@ primitiveCallout(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l10; + goto l11; } /* must be array of arg types */ @@ -3230,13 +3197,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l10; + goto l11; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l10; + goto l11; } # else // COGMTVM @@ -3244,7 +3211,7 @@ primitiveCallout(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l10; + goto l11; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3252,7 +3219,7 @@ primitiveCallout(void) : -1); if (failed()) { result = primitiveFailFor(PrimErrBadMethod); - goto l10; + goto l11; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -3262,10 +3229,40 @@ primitiveCallout(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l3; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l3; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l3; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = (((calloutState->structReturnSize)) <= WordSize) + && ((((calloutState->structReturnSize)) & (((calloutState->structReturnSize)) - 1)) == 0)); + } + err = 0; + l3: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l10; + goto l11; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3286,13 +3283,13 @@ primitiveCallout(void) else { if ((((calloutState->currentArg)) + WordSize) > ((calloutState->limit))) { err = FFIErrorCallFrameTooBig; - goto l9; + goto l10; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + WordSize); } err = 0; - l9: /* end ffiPushPointer:in: */; + l10: /* end ffiPushPointer:in: */; if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { @@ -3301,11 +3298,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l10; + goto l11; } # endif result = ffiFail(err); - goto l10; + goto l11; } } for (i = 1; i <= nArgs; i += 1) { @@ -3322,11 +3319,11 @@ primitiveCallout(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l10; + goto l11; } # endif result = ffiFail(err); - goto l10; + goto l11; } } assert(!(failed())); @@ -3373,7 +3370,7 @@ primitiveCallout(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l7; + goto l8; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3405,7 +3402,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet))) { retOop = nilObject(); - goto l3; + goto l5; } cString = ((char *) (((usqInt) intRet))); strLen = 0; @@ -3418,9 +3415,9 @@ primitiveCallout(void) strPtr[i1] = (cString[i1]); } retOop = strOop; - l3: /* end ffiReturnCStringFrom: */; + l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l7; + goto l8; } #if SPURVM @@ -3442,7 +3439,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l7; + goto l8; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3467,7 +3464,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l7; + goto l8; } /* begin ffiReturnStruct:ofType:in: */ intRetPtr = (&intRet); @@ -3486,7 +3483,7 @@ primitiveCallout(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l7; + goto l8; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -3500,7 +3497,7 @@ primitiveCallout(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l7; + goto l8; } if (atomicType <= FFITypeSignedInt32) { @@ -3521,18 +3518,18 @@ primitiveCallout(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l7; + goto l8; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l7; + goto l8; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l7; + goto l8; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -3553,14 +3550,14 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result1 = -1; } - l7: /* end ffiCalloutTo:SpecOnStack:in: */; + l8: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l11: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -3571,12 +3568,12 @@ primitiveCallout(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l20; + goto l22; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l20; + goto l22; } /* begin ffiLoadCalloutAddress: */ @@ -3585,13 +3582,13 @@ primitiveCallout(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l18; + goto l20; } address11 = fetchPointerofObject(0, addressPtr1); - l18: /* end ffiContentsOfHandle:errCode: */; + l20: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l12; + goto l13; } if (address11 == 0) { @@ -3601,20 +3598,20 @@ primitiveCallout(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l12; + goto l13; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l12; + goto l13; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l12: /* end ffiLoadCalloutAddress: */; + l13: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l20; + goto l22; } /* must be array of arg types */ @@ -3622,13 +3619,13 @@ primitiveCallout(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs1 + 1)))) { ffiFail(FFIErrorBadArgs); - goto l20; + goto l22; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l20; + goto l22; } # else // COGMTVM @@ -3636,7 +3633,7 @@ primitiveCallout(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l20; + goto l22; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -3644,7 +3641,7 @@ primitiveCallout(void) : -1); if (failed()) { primitiveFailFor(PrimErrBadMethod); - goto l20; + goto l22; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -3654,10 +3651,40 @@ primitiveCallout(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l16; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l16; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l16; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = (((calloutState1->structReturnSize)) <= WordSize) + && ((((calloutState1->structReturnSize)) & (((calloutState1->structReturnSize)) - 1)) == 0)); + } + err1 = 0; + l16: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l20; + goto l22; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -3692,11 +3719,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l20; + goto l22; } # endif ffiFail(err1); - goto l20; + goto l22; } } for (i2 = 1; i2 <= nArgs1; i2 += 1) { @@ -3712,11 +3739,11 @@ primitiveCallout(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l20; + goto l22; } # endif ffiFail(err1); - goto l20; + goto l22; } } assert(!(failed())); @@ -3763,7 +3790,7 @@ primitiveCallout(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l11; + goto l15; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -3795,7 +3822,7 @@ primitiveCallout(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l15; + goto l14; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -3808,9 +3835,9 @@ primitiveCallout(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l15: /* end ffiReturnCStringFrom: */; + l14: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l11; + goto l15; } #if SPURVM @@ -3832,7 +3859,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l11; + goto l15; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -3857,7 +3884,7 @@ primitiveCallout(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l11; + goto l15; } /* begin ffiReturnStruct:ofType:in: */ intRetPtr1 = (&intRet1); @@ -3876,7 +3903,7 @@ primitiveCallout(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l11; + goto l15; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -3890,7 +3917,7 @@ primitiveCallout(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l11; + goto l15; } if (atomicType2 <= FFITypeSignedInt32) { @@ -3911,18 +3938,18 @@ primitiveCallout(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l11; + goto l15; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l11; + goto l15; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l11; + goto l15; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -3943,13 +3970,13 @@ primitiveCallout(void) error("Case not found and no otherwise clause"); result2 = -1; } - l11: /* end ffiCalloutTo:SpecOnStack:in: */; + l15: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l22: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; } @@ -4083,12 +4110,12 @@ primitiveCalloutWithArgs(void) primNumArgs = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { result = ffiFail(FFIErrorNotFunction); - goto l10; + goto l11; } flags = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { result = ffiFail(FFIErrorBadArgs); - goto l10; + goto l11; } /* begin ffiLoadCalloutAddress: */ @@ -4127,7 +4154,7 @@ primitiveCalloutWithArgs(void) l2: /* end ffiLoadCalloutAddress: */; if (failed()) { result = 0; - goto l10; + goto l11; } /* must be array of arg types */ @@ -4135,13 +4162,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray)) && ((slotSizeOf(argTypeArray)) == (nArgs + 1)))) { result = ffiFail(FFIErrorBadArgs); - goto l10; + goto l11; } # if COGMTVM if (!(((flags & FFICallTypesMask) == FFICallTypeCDecl) || ((flags & FFICallTypesMask) == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l10; + goto l11; } # else // COGMTVM @@ -4149,7 +4176,7 @@ primitiveCalloutWithArgs(void) if (!((flags == FFICallTypeCDecl) || (flags == FFICallTypeApi))) { result = ffiFail(FFIErrorCallType); - goto l10; + goto l11; } # endif // COGMTVM requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4159,7 +4186,7 @@ primitiveCalloutWithArgs(void) result = primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l10; + goto l11; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize @@ -4169,10 +4196,40 @@ primitiveCalloutWithArgs(void) (calloutState->callFlags = flags); argType = fetchPointerofObject(0, argTypeArray); argSpec = fetchPointerofObject(0, argType); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass = fetchPointerofObject(1, argType); - if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) { + err = FFIErrorBadReturn; + goto l3; + } + } + if (!((isWords(argSpec)) + && ((slotSizeOf(argSpec)) > 0))) { + err = FFIErrorWrongType; + goto l3; + } + (calloutState->ffiRetSpec = argSpec); + (calloutState->ffiRetHeader = fetchLong32ofObject(0, argSpec)); + if (!(((((calloutState->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass == (nilObject())) { + err = FFIErrorBadReturn; + goto l3; + } + } + if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState->structReturnType = (((calloutState->structReturnSize)) <= WordSize) + && ((((calloutState->structReturnSize)) & (((calloutState->structReturnSize)) - 1)) == 0)); + } + err = 0; + l3: /* end ffiCheckReturn:With:in: */; + if (err != 0) { result = ffiFail(err); - goto l10; + goto l11; } allocation = alloca((stackSize + ((calloutState->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4193,13 +4250,13 @@ primitiveCalloutWithArgs(void) else { if ((((calloutState->currentArg)) + WordSize) > ((calloutState->limit))) { err = FFIErrorCallFrameTooBig; - goto l9; + goto l10; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + WordSize); } err = 0; - l9: /* end ffiPushPointer:in: */; + l10: /* end ffiPushPointer:in: */; if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { @@ -4208,11 +4265,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l10; + goto l11; } # endif result = ffiFail(err); - goto l10; + goto l11; } } for (i = 1; i <= nArgs; i += 1) { @@ -4231,11 +4288,11 @@ primitiveCalloutWithArgs(void) # if COGMTVM if (err == (-PrimErrObjectMayMove)) { result = PrimErrObjectMayMove; - goto l10; + goto l11; } # endif result = ffiFail(err); - goto l10; + goto l11; } } assert(!(failed())); @@ -4282,7 +4339,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex); result1 = floatObjectOf(floatRet); - goto l7; + goto l8; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -4316,7 +4373,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet))) { retOop = nilObject(); - goto l3; + goto l5; } cString = ((char *) (((usqInt) intRet))); strLen = 0; @@ -4329,9 +4386,9 @@ primitiveCalloutWithArgs(void) strPtr[i1] = (cString[i1]); } retOop = strOop; - l3: /* end ffiReturnCStringFrom: */; + l5: /* end ffiReturnCStringFrom: */; result1 = retOop; - goto l7; + goto l8; } #if SPURVM @@ -4353,7 +4410,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop, returnType); result1 = retOop; - goto l7; + goto l8; } classOop = (((((calloutState->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4378,7 +4435,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop, oop2); result1 = retOop; - goto l7; + goto l8; } /* begin ffiReturnStruct:ofType:in: */ intRetPtr = (&intRet); @@ -4397,7 +4454,7 @@ primitiveCalloutWithArgs(void) : (calloutState->limit)), (calloutState->structReturnSize)); storePointerofObjectwithValue(0, retOop1, oop1); result1 = retOop1; - goto l7; + goto l8; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType)))); @@ -4411,7 +4468,7 @@ primitiveCalloutWithArgs(void) result1 = (value == 0 ? falseObject() : trueObject()); - goto l7; + goto l8; } if (atomicType <= FFITypeSignedInt32) { @@ -4432,18 +4489,18 @@ primitiveCalloutWithArgs(void) value = (value & (mask - 1)) - (value & mask); } result1 = integerObjectOf(value); - goto l7; + goto l8; } result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l7; + goto l8; } if ((((usqInt)(atomicType)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result1 = (((atomicType & 1) != 0) ? signed64BitIntegerFor(intRet) : positive64BitIntegerFor(intRet)); - goto l7; + goto l8; } assert(isCharacterAtomicType(atomicType)); switch (atomicType) { @@ -4464,14 +4521,14 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result1 = -1; } - l7: /* end ffiCalloutTo:SpecOnStack:in: */; + l8: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } popthenPush(primNumArgs + 1, result1); result = result1; - l10: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l11: /* end ffiCall:ArgArrayOrNil:NumArgs: */; if (!((result == PrimErrObjectMayMove) && (((retryCount += 1)) <= (nArgs + 1)))) break; tenuringIncrementalGC(); @@ -4488,12 +4545,12 @@ primitiveCalloutWithArgs(void) primNumArgs1 = methodArgumentCount(); if (!(isKindOfClass(externalFunction, classExternalFunction()))) { ffiFail(FFIErrorNotFunction); - goto l20; + goto l22; } flags1 = fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (failed()) { ffiFail(FFIErrorBadArgs); - goto l20; + goto l22; } /* begin ffiLoadCalloutAddress: */ @@ -4502,13 +4559,13 @@ primitiveCalloutWithArgs(void) if (!((isBytes(addressPtr1)) && ((byteSizeOf(addressPtr1)) == (sizeof(sqInt))))) { address11 = ffiFail(FFIErrorBadAddress); - goto l18; + goto l20; } address11 = fetchPointerofObject(0, addressPtr1); - l18: /* end ffiContentsOfHandle:errCode: */; + l20: /* end ffiContentsOfHandle:errCode: */; if (failed()) { address2 = 0; - goto l12; + goto l13; } if (address11 == 0) { @@ -4518,20 +4575,20 @@ primitiveCalloutWithArgs(void) } if ((slotSizeOf(externalFunction)) < 5) { address2 = ffiFail(FFIErrorNoModule); - goto l12; + goto l13; } address11 = ffiLoadCalloutAddressFrom(externalFunction); if (failed()) { address2 = 0; - goto l12; + goto l13; } ptr2 = firstIndexableField(addressPtr1); ptr2[0] = address11; } address2 = address11; - l12: /* end ffiLoadCalloutAddress: */; + l13: /* end ffiLoadCalloutAddress: */; if (failed()) { - goto l20; + goto l22; } /* must be array of arg types */ @@ -4539,13 +4596,13 @@ primitiveCalloutWithArgs(void) if (!((isArray(argTypeArray1)) && ((slotSizeOf(argTypeArray1)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); - goto l20; + goto l22; } # if COGMTVM if (!(((flags1 & FFICallTypesMask) == FFICallTypeCDecl) || ((flags1 & FFICallTypesMask) == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l20; + goto l22; } # else // COGMTVM @@ -4553,7 +4610,7 @@ primitiveCalloutWithArgs(void) if (!((flags1 == FFICallTypeCDecl) || (flags1 == FFICallTypeApi))) { ffiFail(FFIErrorCallType); - goto l20; + goto l22; } # endif // COGMTVM requiredStackSize1 = (externalFunctionInstSize > ExternalFunctionStackSizeIndex @@ -4563,7 +4620,7 @@ primitiveCalloutWithArgs(void) primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); - goto l20; + goto l22; } stackSize1 = (requiredStackSize1 < 0 ? DefaultMaxStackSize @@ -4573,10 +4630,40 @@ primitiveCalloutWithArgs(void) (calloutState1->callFlags = flags1); argType1 = fetchPointerofObject(0, argTypeArray1); argSpec1 = fetchPointerofObject(0, argType1); + + /* Witten this way to allow Slang to inline ffiCheckReturn:With:in: */ argClass1 = fetchPointerofObject(1, argType1); - if (((err1 = ffiCheckReturnWithin(argSpec1, argClass1, calloutState1))) != 0) { + /* begin ffiCheckReturn:With:in: */ + if (!(argClass1 == (nilObject()))) { + if (!(includesBehaviorThatOf(argClass1, classExternalStructure()))) { + err1 = FFIErrorBadReturn; + goto l16; + } + } + if (!((isWords(argSpec1)) + && ((slotSizeOf(argSpec1)) > 0))) { + err1 = FFIErrorWrongType; + goto l16; + } + (calloutState1->ffiRetSpec = argSpec1); + (calloutState1->ffiRetHeader = fetchLong32ofObject(0, argSpec1)); + if (!(((((calloutState1->ffiRetHeader)) & FFIFlagAtomic) != 0))) { + if (argClass1 == (nilObject())) { + err1 = FFIErrorBadReturn; + goto l16; + } + } + if ((((calloutState1->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { + (calloutState1->structReturnSize = ((calloutState1->ffiRetHeader)) & FFIStructSizeMask); + /* begin encodeStructReturnTypeIn: */ + (calloutState1->structReturnType = (((calloutState1->structReturnSize)) <= WordSize) + && ((((calloutState1->structReturnSize)) & (((calloutState1->structReturnSize)) - 1)) == 0)); + } + err1 = 0; + l16: /* end ffiCheckReturn:With:in: */; + if (err1 != 0) { ffiFail(err1); - goto l20; + goto l22; } allocation1 = alloca((stackSize1 + ((calloutState1->structReturnSize))) + (cStackAlignment())); if (mustAlignStack()) { @@ -4611,11 +4698,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l20; + goto l22; } # endif ffiFail(err1); - goto l20; + goto l22; } } for (i2 = 1; i2 <= nArgs; i2 += 1) { @@ -4633,11 +4720,11 @@ primitiveCalloutWithArgs(void) } # if COGMTVM if (err1 == (-PrimErrObjectMayMove)) { - goto l20; + goto l22; } # endif ffiFail(err1); - goto l20; + goto l22; } } assert(!(failed())); @@ -4684,7 +4771,7 @@ primitiveCalloutWithArgs(void) } ownVM(myThreadIndex1); result2 = floatObjectOf(floatRet1); - goto l11; + goto l15; } /* undo any callee argument pops because it may confuse stack management with the alloca. */ @@ -4718,7 +4805,7 @@ primitiveCalloutWithArgs(void) /* begin ffiReturnCStringFrom: */ if (!(((usqInt) intRet1))) { retOop2 = nilObject(); - goto l15; + goto l14; } cString1 = ((char *) (((usqInt) intRet1))); strLen1 = 0; @@ -4731,9 +4818,9 @@ primitiveCalloutWithArgs(void) strPtr1[i11] = (cString1[i11]); } retOop2 = strOop1; - l15: /* end ffiReturnCStringFrom: */; + l14: /* end ffiReturnCStringFrom: */; result2 = retOop2; - goto l11; + goto l15; } #if SPURVM @@ -4755,7 +4842,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(1, retOop2, returnType1); result2 = retOop2; - goto l11; + goto l15; } classOop1 = (((((calloutState1->ffiRetHeader)) & FFIFlagStructure) != 0) ? classByteArray() @@ -4780,7 +4867,7 @@ primitiveCalloutWithArgs(void) #endif /* SPURVM */ storePointerofObjectwithValue(0, retOop2, oop21); result2 = retOop2; - goto l11; + goto l15; } /* begin ffiReturnStruct:ofType:in: */ intRetPtr1 = (&intRet1); @@ -4799,7 +4886,7 @@ primitiveCalloutWithArgs(void) : (calloutState1->limit)), (calloutState1->structReturnSize)); storePointerofObjectwithValue(0, retOop11, oop11); result2 = retOop11; - goto l11; + goto l15; } /* begin ffiCreateIntegralResultOop:ofAtomicType:in: */ assert(!((isFloatAtomicType(atomicType2)))); @@ -4813,7 +4900,7 @@ primitiveCalloutWithArgs(void) result2 = (value1 == 0 ? falseObject() : trueObject()); - goto l11; + goto l15; } if (atomicType2 <= FFITypeSignedInt32) { @@ -4834,18 +4921,18 @@ primitiveCalloutWithArgs(void) value1 = (value1 & (mask1 - 1)) - (value1 & mask1); } result2 = integerObjectOf(value1); - goto l11; + goto l15; } result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l11; + goto l15; } if ((((usqInt)(atomicType2)) >> 1) == (((usqInt)(FFITypeSignedInt64)) >> 1)) { result2 = (((atomicType2 & 1) != 0) ? signed64BitIntegerFor(intRet1) : positive64BitIntegerFor(intRet1)); - goto l11; + goto l15; } assert(isCharacterAtomicType(atomicType2)); switch (atomicType2) { @@ -4866,13 +4953,13 @@ primitiveCalloutWithArgs(void) error("Case not found and no otherwise clause"); result2 = -1; } - l11: /* end ffiCalloutTo:SpecOnStack:in: */; + l15: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState1->stringArgIndex)) > 0) { free(((calloutState1->stringArgs))[(calloutState1->stringArgIndex = ((calloutState1->stringArgIndex)) - 1)]); } popthenPush(primNumArgs1 + 1, result2); - l20: /* end ffiCall:ArgArrayOrNil:NumArgs: */; + l22: /* end ffiCall:ArgArrayOrNil:NumArgs: */; # endif // COGMTVM return; }