[commit] r2377 - Fix checkin snafu; submit the correct SqueakFFIPrims from ReentrantIA32FFIPlugin

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[commit] r2377 - Fix checkin snafu; submit the correct SqueakFFIPrims from ReentrantIA32FFIPlugin

commits-3
 
Author: eliot
Date: 2011-04-01 12:51:41 -0700 (Fri, 01 Apr 2011)
New Revision: 2377

Modified:
   branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c
Log:
Fix checkin snafu; submit the correct SqueakFFIPrims from ReentrantIA32FFIPlugin


Modified: branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c
===================================================================
--- branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c 2011-04-01 19:39:21 UTC (rev 2376)
+++ branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c 2011-04-01 19:51:41 UTC (rev 2377)
@@ -1,9 +1,9 @@
 /* Automatically generated by
  VMPluginCodeGenerator VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
    from
- ThreadedARMFFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
+ ReentrantIA32FFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
  */
-static char __buildInfo[] = "ThreadedARMFFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7 " __DATE__ ;
+static char __buildInfo[] = "ReentrantIA32FFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7 " __DATE__ ;
 
 
 
@@ -53,26 +53,20 @@
 # define setsp(ignored) 0
 #endif
 
-#if !defined(STACK_ALIGN_BYTES)
-# if __APPLE__ && __MACH__ && __i386__
-#  define STACK_ALIGN_BYTES 16
-# elif __linux__ && __i386__
-#  define STACK_ALIGN_BYTES 16
-# elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
-#  define STACK_ALIGN_BYTES 16
-# elif defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__)
-#  define STACK_ALIGN_BYTES 16
-# elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must preceed 32-bit sparc defs */
-#  define STACK_ALIGN_BYTES 16
-# elif defined(sparc) || defined(__sparc__) || defined(__sparclite__)
-#  define STACK_ALIGN_BYTES 8
-# else
-#  define STACK_ALIGN_BYTES 0
-# endif
-#endif /* !defined(STACK_ALIGN_BYTES) */
-
-#if !defined(STACK_OFFSET_BYTES)
-# define STACK_OFFSET_BYTES 0
+#if __APPLE__ && __MACH__ && __i386__
+# define STACK_ALIGN_BYTES 16
+#elif __linux__ && __i386__
+# define STACK_ALIGN_BYTES 16
+#elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
+# define STACK_ALIGN_BYTES 16
+#elif defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__)
+# define STACK_ALIGN_BYTES 16
+#elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must preceed 32-bit sparc defs */
+# define STACK_ALIGN_BYTES 16
+#elif defined(sparc) || defined(__sparc__) || defined(__sparclite__)
+# define STACK_ALIGN_BYTES 8
+#else
+# define STACK_ALIGN_BYTES 0
 #endif
 
 #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
@@ -124,11 +118,9 @@
  sqInt ffiRetHeader;
  sqInt stringArgIndex;
  char *stringArgs[15];
- sqInt regIndex;
- sqInt integerRegisters[8];
  } CalloutState;
 
-#define ThreadedFFICalloutStateForARM CalloutState
+#define ReentrantFFICalloutState CalloutState
 
 
 
@@ -141,7 +133,6 @@
 #define ExternalFunctionStackSizeIndex 3
 #define FFIAtomicTypeMask 0xF000000
 #define FFIAtomicTypeShift 24
-#define FFICallFlagThreaded null
 #define FFICallTypeApi 1
 #define FFIErrorAddressNotFound 13
 #define FFIErrorAttemptToPassVoid 14
@@ -152,6 +143,7 @@
 #define FFIErrorBadExternalFunction 17
 #define FFIErrorBadExternalLibrary 16
 #define FFIErrorBadReturn 10
+#define FFIErrorCallFrameTooBig 19
 #define FFIErrorCallType 9
 #define FFIErrorCoercionFailed 6
 #define FFIErrorIntAsPointer 4
@@ -182,7 +174,6 @@
 #define PrimErrBadNumArgs 5
 #define PrimErrBadReceiver 2
 #define PrimErrNoCMemory 10
-#define PrimErrObjectMayMove 14
 
 
 /*** Function Prototypes ***/
@@ -194,7 +185,7 @@
 static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState);
 static sqInt ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState);
 static sqInt ffiAtomicStructByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState);
-static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, sqInt calloutState);
+static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState);
 static sqInt ffiCallArgArrayOrNilNumArgs(sqInt externalFunction, sqInt argArrayOrNil, sqInt nArgs);
 static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState);
 static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode);
@@ -207,16 +198,16 @@
 static sqInt ffiLoadCalloutModule(sqInt module);
 static void ffiLogCallout(sqInt lit);
 EXPORT(sqInt) ffiLogCallsTo(char*fileName);
-static sqInt ffiPushDoubleFloatin(sqInt value, sqInt calloutState);
+static sqInt ffiPushDoubleFloatin(double value, CalloutState *calloutState);
 static sqInt ffiPushPointerContentsOfin(sqInt oop, CalloutState *calloutState);
-static sqInt ffiPushPointerin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushPointerin(void *pointer, CalloutState *calloutState);
 static sqInt ffiPushSignedBytein(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedCharin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedIntin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedLongLongOopin(sqInt oop, CalloutState *calloutState);
-static sqInt ffiPushSignedLongLongin(sqLong value, CalloutState *calloutState);
+static sqInt ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState);
 static sqInt ffiPushSignedShortin(sqInt value, CalloutState *calloutState);
-static sqInt ffiPushSingleFloatin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushSingleFloatin(float value, CalloutState *calloutState);
 static sqInt ffiPushStringOfLengthin(char *pointer, sqInt length, CalloutState *calloutState);
 static sqInt ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState);
 static sqInt ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState);
@@ -225,12 +216,11 @@
 static sqInt ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushUnsignedLongLongOopin(sqInt oop, CalloutState *calloutState);
 static sqInt ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState);
-static sqInt ffiPushUnsignedLongin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushVoidin(sqInt ignored, CalloutState *calloutState);
 static sqInt ffiReturnCStringFrom(sqInt cPointer);
 static sqInt ffiReturnPointerofTypein(usqLong retVal, sqInt retType, CalloutState *calloutState);
-static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetClass, CalloutState *calloutState);
+static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState);
 static sqInt ffiReturnType(sqInt specOnStack);
 static sqInt ffiSupportsCallingConvention(sqInt aCallingConvention);
 static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType);
@@ -238,7 +228,6 @@
 EXPORT(const char*) getModuleName(void);
 static sqInt halt(void);
 EXPORT(sqInt) initialiseModule(void);
-static void initialize(CalloutState * self_in_initialize);
 static sqInt isAlien(sqInt anOop);
 static sqInt isAtomicType(sqInt typeSpec);
 static sqInt isDirectAlien(sqInt oop);
@@ -261,7 +250,6 @@
 EXPORT(sqInt) primitiveLogCallsTo(void);
 EXPORT(sqInt) primitiveSetManualSurfacePointer(void);
 static sqInt registerArgsSlop(void);
-static sqInt returnStructInRegisters(sqInt returnStructSize);
 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
 static sqInt sizeField(sqInt oop);
 static sqInt startOfData(sqInt oop);
@@ -292,6 +280,7 @@
 #define ffiAlloc(bytes) (usqInt)malloc(bytes)
 #define ffiFree(pointer) free((void *)(pointer))
 #define isCalleePopsConvention(callType) (PLATFORM_API_USES_CALLEE_POPS_CONVENTION && (callType) == FFICallTypeApi)
+#define returnStructInRegisters(sz) (WIN32_X86_STRUCT_RETURN && (sz) <= 8 && !((sz)&((sz)-1)))
 
 
 static sqInt
@@ -472,12 +461,20 @@
  }
  if (atomicType == FFITypeSingleFloat) {
  /* begin ffiPushSingleFloat:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  else {
  /* begin ffiPushDoubleFloat:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
  }
 }
@@ -510,9 +507,14 @@
     sqInt oopClass1;
     sqInt oopClass2;
     char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
     sqInt ptrAddress;
     sqInt ptrClass;
     sqInt ptrType;
+    sqInt roundedSize;
+    sqInt roundedSize1;
     sqInt spec;
     sqInt specOop;
     sqInt specType;
@@ -521,9 +523,6 @@
     sqInt typeSpec;
     sqInt typeSpec1;
     sqInt typeSpec2;
-    sqInt value;
-    sqInt value1;
-    sqInt value2;
     sqInt valueOop;
     sqInt valueOop1;
 
@@ -599,8 +598,13 @@
  structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
  argSpec2 = (calloutState->ffiArgSpec);
  argSpecSize = (calloutState->ffiArgSpecSize);
- subclassResponsibility();
- return null;
+ roundedSize = (structSize + 3) & (~3);
+ if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize);
+ (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+ return 0;
  }
  if (ptrClass == (interpreterProxy->classByteArray())) {
  if (!((interpreterProxy->byteSizeOf(valueOop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) {
@@ -608,16 +612,17 @@
  }
  ptrAddress = ((int) (interpreterProxy->firstIndexableField(valueOop)));
  if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) {
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && (interpreterProxy->isYoung(valueOop))) {
- return -PrimErrObjectMayMove;
- }
  /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
  structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
  argSpec1 = (calloutState->ffiArgSpec);
  argSpecSize1 = (calloutState->ffiArgSpecSize);
- subclassResponsibility();
- return null;
+ roundedSize1 = (structSize1 + 3) & (~3);
+ if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1);
+ (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1);
+ return 0;
  }
  if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) {
  return FFIErrorStructSize;
@@ -627,7 +632,11 @@
  return FFIErrorInvalidPointer;
  }
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ptrAddress);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  return FFIErrorBadArg;
@@ -638,7 +647,11 @@
  }
  if (oop == (interpreterProxy->nilObject())) {
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), null);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) {
@@ -732,32 +745,38 @@
  ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
  (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), copy);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  atomicType2 = FFITypeUnsignedByte;
  }
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && (((!isAlien)
- || (isDirectAlien(oop)))
- && (interpreterProxy->isYoung(oop)))) {
- return -PrimErrObjectMayMove;
- }
  if ((atomicType2 == FFITypeVoid)
  || ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
  if (isString
  || (oopClass == (interpreterProxy->classByteArray()))) {
  /* begin ffiPushPointer:in: */
- value = interpreterProxy->firstIndexableField(oop);
- error("shouldBeImplemented");
+ pointer1 = interpreterProxy->firstIndexableField(oop);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer1);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (isAlien) {
  /* begin ffiPushPointer:in: */
- value1 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+ pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
  ? (oop + BaseHeaderSize) + BytesPerOop
  : longAt((oop + BaseHeaderSize) + BytesPerOop)));
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer2);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (!(atomicType2 == FFITypeVoid)) {
@@ -768,8 +787,12 @@
  || (atomicType2 == FFITypeSingleFloat)) {
  if (interpreterProxy->isWords(oop)) {
  /* begin ffiPushPointer:in: */
- value2 = interpreterProxy->firstIndexableField(oop);
- error("shouldBeImplemented");
+ pointer3 = interpreterProxy->firstIndexableField(oop);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer3);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  }
@@ -880,12 +903,20 @@
  }
  if (atomicType1 == FFITypeSingleFloat) {
  /* begin ffiPushSingleFloat:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  else {
  /* begin ffiPushDoubleFloat:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
  }
  }
@@ -908,10 +939,10 @@
     sqInt isString;
     sqInt length;
     char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
     sqInt typeSpec;
-    sqInt value;
-    sqInt value1;
-    sqInt value2;
 
  /* begin atomicTypeOf: */
  typeSpec = (calloutState->ffiArgHeader);
@@ -939,32 +970,38 @@
  ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
  (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), copy);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  atomicType = FFITypeUnsignedByte;
  }
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && (((!isAlien)
- || (isDirectAlien(oop)))
- && (interpreterProxy->isYoung(oop)))) {
- return -PrimErrObjectMayMove;
- }
  if ((atomicType == FFITypeVoid)
  || ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
  if (isString
  || (oopClass == (interpreterProxy->classByteArray()))) {
  /* begin ffiPushPointer:in: */
- value = interpreterProxy->firstIndexableField(oop);
- error("shouldBeImplemented");
+ pointer1 = interpreterProxy->firstIndexableField(oop);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer1);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (isAlien) {
  /* begin ffiPushPointer:in: */
- value1 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+ pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
  ? (oop + BaseHeaderSize) + BytesPerOop
  : longAt((oop + BaseHeaderSize) + BytesPerOop)));
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer2);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (!(atomicType == FFITypeVoid)) {
@@ -975,8 +1012,12 @@
  || (atomicType == FFITypeSingleFloat)) {
  if (interpreterProxy->isWords(oop)) {
  /* begin ffiPushPointer:in: */
- value2 = interpreterProxy->firstIndexableField(oop);
- error("shouldBeImplemented");
+ pointer3 = interpreterProxy->firstIndexableField(oop);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer3);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  }
@@ -1062,17 +1103,155 @@
 }
 
 
-/* Perform the callout, collect the result and and create the return value.
- If a threaded call, disown and own VM around the call. If there are
- floating-point arguments that are passed in registers then call a dummy
- function to load them.
- This *must* be inlined because of the alloca of the outgoing stack frame
- in ffiCall:SpecOnStack:Flags:NumArgs:Args:AndTypes: */
+/* Go out, call this guy and create the return value. This *must* be inlined
+ because of
+ the alloca of the outgoing stack frame in
+ ffiCall:WithFlags:NumArgs:Args:AndTypes:
+ */
 
 static sqInt
-ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, sqInt calloutState)
+ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState)
 {
- subclassResponsibility();
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    sqInt classOop;
+    char *cString;
+    sqInt ffiRetType;
+    double floatRet;
+    sqInt i;
+    usqLong intRet;
+    sqInt oop;
+    sqInt oop1;
+    sqInt *ptr;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    sqInt typeSpec;
+    sqInt typeSpec1;
+
+ if ((0 + (cStackAlignment())) > 0) {
+ setsp((calloutState->argVector));
+ }
+ /* begin atomicTypeOf: */
+ typeSpec = (calloutState->ffiRetHeader);
+ atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ floatRet = dispatchFunctionPointer(((double (*)()) procAddr));
+ }
+ else {
+ intRet = dispatchFunctionPointer(((usqLong (*)()) procAddr));
+ }
+ if (isCalleePopsConvention((calloutState->callFlags))) {
+ setsp((calloutState->argVector));
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+ /* begin ffiReturnPointer:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral1 = (specOnStack
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+ retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+ retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+ if (retClass1 == (interpreterProxy->nilObject())) {
+ /* begin atomicTypeOf: */
+ typeSpec1 = (calloutState->ffiRetHeader);
+ atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+ /* begin ffiReturnCStringFrom: */
+ if ((((usqInt) intRet)) == null) {
+ return interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+ }
+ cString = ((char *) (((usqInt) intRet)));
+ strLen = 0;
+ while (!((cString[strLen]) == 0)) {
+ strLen += 1;
+ }
+ strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+ strPtr = interpreterProxy->firstIndexableField(strOop);
+ for (i = 0; i <= (strLen - 1); i += 1) {
+ strPtr[i] = (cString[i]);
+ }
+ return interpreterProxy->methodReturnValue(strOop);
+ }
+ interpreterProxy->pushRemappableOop(retType);
+ oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+ ptr = interpreterProxy->firstIndexableField(oop1);
+ ptr[0] = (((sqInt) intRet));
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+ /* return type */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+ return interpreterProxy->methodReturnValue(retOop1);
+ }
+ interpreterProxy->pushRemappableOop(retClass1);
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ classOop = interpreterProxy->classByteArray();
+ }
+ else {
+ classOop = interpreterProxy->classExternalAddress();
+ }
+ oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+ ptr = interpreterProxy->firstIndexableField(oop1);
+ ptr[0] = (((sqInt) intRet));
+
+ /* return class */
+
+ retClass1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+ return interpreterProxy->methodReturnValue(retOop1);
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ /* begin ffiReturnStruct:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral = (specOnStack
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+ ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+ retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+ retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+ interpreterProxy->pushRemappableOop(retOop);
+ oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+ if (returnStructInRegisters((calloutState->structReturnSize))) {
+ memcpy(interpreterProxy->firstIndexableField(oop), (&intRet), (calloutState->structReturnSize));
+ }
+ else {
+ memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize));
+ }
+ retOop = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop, oop);
+ return interpreterProxy->methodReturnValue(retOop);
+ }
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ return interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+ }
+ return interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
 }
 
 
@@ -1092,18 +1271,43 @@
     sqInt argSpec;
     sqInt argType;
     sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
     CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
     sqInt err;
+    sqInt ffiRetType;
     sqInt flags;
+    double floatRet;
     sqInt functionName;
     sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
     int *ptr;
+    sqInt *ptr1;
     sqInt requiredStackSize;
     sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
     sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
     CalloutState theCalloutState;
-    sqInt value;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
  if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
  return ffiFail(FFIErrorNotFunction);
@@ -1132,21 +1336,21 @@
  /* begin ffiContentsOfHandle:errCode: */
  if ((addressPtr & 1)) {
  address1 = ffiFail(FFIErrorBadAddress);
- goto l2;
+ goto l3;
  }
  if (!(interpreterProxy->isBytes(addressPtr))) {
  address1 = ffiFail(FFIErrorBadAddress);
- goto l2;
+ goto l3;
  }
  if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
  address1 = ffiFail(FFIErrorBadAddress);
- goto l2;
+ goto l3;
  }
  address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
-l2: /* end ffiContentsOfHandle:errCode: */;
+l3: /* end ffiContentsOfHandle:errCode: */;
  if (interpreterProxy->failed()) {
  address = 0;
- goto l3;
+ goto l4;
  }
  if (address1 == 0) {
  if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
@@ -1154,18 +1358,18 @@
  }
  if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
  address = ffiFail(FFIErrorNoModule);
- goto l3;
+ goto l4;
  }
  address1 = ffiLoadCalloutAddressFrom(externalFunction);
  if (interpreterProxy->failed()) {
  address = 0;
- goto l3;
+ goto l4;
  }
  ptr = interpreterProxy->firstIndexableField(addressPtr);
  ptr[0] = address1;
  }
  address = address1;
-l3: /* end ffiLoadCalloutAddress: */;
+l4: /* end ffiLoadCalloutAddress: */;
  if (interpreterProxy->failed()) {
  return 0;
  }
@@ -1205,8 +1409,13 @@
  && (1
  && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
  /* begin ffiPushPointer:in: */
- value = (calloutState->limit);
- error("shouldBeImplemented");
+ pointer = (calloutState->limit);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ goto l1;
+ }
+ longAtput((calloutState->currentArg), pointer);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
+ l1: /* end ffiPushPointer:in: */;
  }
  for (i = 1; i <= nArgs; i += 1) {
  argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
@@ -1221,9 +1430,6 @@
  while (((calloutState->stringArgIndex)) > 0) {
  free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
  }
- if (err == (-PrimErrObjectMayMove)) {
- return PrimErrObjectMayMove;
- }
  return ffiFail(err);
  }
  }
@@ -1232,18 +1438,138 @@
  if (ffiLogEnabled) {
  functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
  if (!(interpreterProxy->isBytes(functionName))) {
- goto l1;
+ goto l2;
  }
  ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
  }
-l1: /* end ffiLogCallout: */;
+l2: /* end ffiLogCallout: */;
  if ((requiredStackSize < 0)
  && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
  stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
  interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
  }
  /* begin ffiCalloutTo:SpecOnStack:in: */
- subclassResponsibility();
+ if ((0 + (cStackAlignment())) > 0) {
+ setsp((calloutState->argVector));
+ }
+ /* begin atomicTypeOf: */
+ typeSpec = (calloutState->ffiRetHeader);
+ atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ floatRet = dispatchFunctionPointer(((double (*)()) address));
+ }
+ else {
+ intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+ }
+ if (isCalleePopsConvention((calloutState->callFlags))) {
+ setsp((calloutState->argVector));
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+ /* begin ffiReturnPointer:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral1 = (argArrayOrNil != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+ retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+ retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+ if (retClass1 == (interpreterProxy->nilObject())) {
+ /* begin atomicTypeOf: */
+ typeSpec1 = (calloutState->ffiRetHeader);
+ atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+ /* begin ffiReturnCStringFrom: */
+ if ((((usqInt) intRet)) == null) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+ goto l5;
+ }
+ cString = ((char *) (((usqInt) intRet)));
+ strLen = 0;
+ while (!((cString[strLen]) == 0)) {
+ strLen += 1;
+ }
+ strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+ strPtr = interpreterProxy->firstIndexableField(strOop);
+ for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+ strPtr[i1] = (cString[i1]);
+ }
+ result = interpreterProxy->methodReturnValue(strOop);
+ goto l5;
+ }
+ interpreterProxy->pushRemappableOop(retType);
+ oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+ /* return type */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l5;
+ }
+ interpreterProxy->pushRemappableOop(retClass1);
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ classOop = interpreterProxy->classByteArray();
+ }
+ else {
+ classOop = interpreterProxy->classExternalAddress();
+ }
+ oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+
+ /* return class */
+
+ retClass1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l5;
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ /* begin ffiReturnStruct:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral = (argArrayOrNil != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+ ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+ retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+ retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+ interpreterProxy->pushRemappableOop(retOop);
+ oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+ if (returnStructInRegisters((calloutState->structReturnSize))) {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+ }
+ else {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+ }
+ retOop = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+ result = interpreterProxy->methodReturnValue(retOop);
+ goto l5;
+ }
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+ goto l5;
+ }
+ result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l5: /* end ffiCalloutTo:SpecOnStack:in: */;
  /* begin cleanupCalloutState: */
  while (((calloutState->stringArgIndex)) > 0) {
  free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
@@ -1700,9 +2026,13 @@
 }
 
 static sqInt
-ffiPushDoubleFloatin(sqInt value, sqInt calloutState)
+ffiPushDoubleFloatin(double value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeFloatAtPointerfrom((calloutState->currentArg), value);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
 }
 
@@ -1725,60 +2055,80 @@
  return FFIErrorInvalidPointer;
  }
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ptrAddress);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (ptrClass == (interpreterProxy->classByteArray())) {
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && (interpreterProxy->isYoung(oop))) {
- return -PrimErrObjectMayMove;
- }
  ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop)));
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ptrAddress);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  if (interpreterProxy->includesBehaviorThatOf(ptrClass, interpreterProxy->classAlien())) {
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && ((isDirectAlien(oop))
- && (interpreterProxy->isYoung(oop)))) {
- return -PrimErrObjectMayMove;
- }
  ptrAddress = ((longAt(oop + BaseHeaderSize)) > 0
  ? (oop + BaseHeaderSize) + BytesPerOop
  : longAt((oop + BaseHeaderSize) + BytesPerOop));
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ptrAddress);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  return FFIErrorBadArg;
 }
 
 static sqInt
-ffiPushPointerin(sqInt value, CalloutState *calloutState)
+ffiPushPointerin(void *pointer, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), pointer);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
 ffiPushSignedBytein(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((signed char) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
 ffiPushSignedCharin(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((signed char) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
 ffiPushSignedIntin(sqInt value, CalloutState *calloutState)
 {
- subclassResponsibility();
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), value);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
+ return 0;
 }
 
 
@@ -1806,28 +2156,46 @@
  }
  }
  /* begin ffiPushSignedLongLong:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((usqInt) value));
+ longAtput(((calloutState->currentArg)) + 4, ((usqInt) (((unsigned sqLong )value) >> 32)));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
 }
 
 static sqInt
-ffiPushSignedLongLongin(sqLong value, CalloutState *calloutState)
+ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((usqInt) value));
+ longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
 }
 
 static sqInt
 ffiPushSignedShortin(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((signed short) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
-ffiPushSingleFloatin(sqInt value, CalloutState *calloutState)
+ffiPushSingleFloatin(float value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ storeSingleFloatAtPointerfrom((calloutState->currentArg), value);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
@@ -1848,7 +2216,11 @@
  ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
  (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), copy);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
@@ -1864,6 +2236,8 @@
     sqInt argSpecSize1;
     sqInt ptrAddress;
     sqInt ptrClass;
+    sqInt roundedSize;
+    sqInt roundedSize1;
     sqInt structSize;
     sqInt structSize1;
 
@@ -1882,8 +2256,13 @@
  structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
  argSpec = (calloutState->ffiArgSpec);
  argSpecSize = (calloutState->ffiArgSpecSize);
- subclassResponsibility();
- return null;
+ roundedSize = (structSize + 3) & (~3);
+ if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize);
+ (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+ return 0;
  }
  if (ptrClass == (interpreterProxy->classByteArray())) {
  if (!((interpreterProxy->byteSizeOf(oop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) {
@@ -1891,16 +2270,17 @@
  }
  ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop)));
  if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) {
- if ((((calloutState->callFlags)) & FFICallFlagThreaded)
- && (interpreterProxy->isYoung(oop))) {
- return -PrimErrObjectMayMove;
- }
  /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
  structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
  argSpec1 = (calloutState->ffiArgSpec);
  argSpecSize1 = (calloutState->ffiArgSpecSize);
- subclassResponsibility();
- return null;
+ roundedSize1 = (structSize1 + 3) & (~3);
+ if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1);
+ (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1);
+ return 0;
  }
  if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) {
  return FFIErrorStructSize;
@@ -1910,7 +2290,11 @@
  return FFIErrorInvalidPointer;
  }
  /* begin ffiPushPointer:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ptrAddress);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
  }
  return FFIErrorBadArg;
@@ -1919,27 +2303,48 @@
 static sqInt
 ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState)
 {
- subclassResponsibility();
+    sqInt roundedSize;
+
+ roundedSize = (structSize + 3) & (~3);
+ if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ memcpy((calloutState->currentArg), pointer, structSize);
+ (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+ return 0;
 }
 
 static sqInt
 ffiPushUnsignedBytein(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((unsigned char) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
 ffiPushUnsignedCharin(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((unsigned char) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
 static sqInt
 ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState)
 {
- subclassResponsibility();
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), value);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
+ return 0;
 }
 
 
@@ -1967,28 +2372,35 @@
  }
  }
  /* begin ffiPushUnsignedLongLong:in: */
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((usqInt) value));
+ longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
 }
 
 static sqInt
 ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((usqInt) value));
+ longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 8);
  return 0;
 }
 
 static sqInt
-ffiPushUnsignedLongin(sqInt value, CalloutState *calloutState)
-{
- error("shouldBeImplemented");
- return 0;
-}
-
-static sqInt
 ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState)
 {
- error("shouldBeImplemented");
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ return FFIErrorCallFrameTooBig;
+ }
+ longAtput((calloutState->currentArg), ((unsigned short) value));
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
  return 0;
 }
 
@@ -2122,9 +2534,25 @@
  alloca'ed space pointed to by the calloutState. */
 
 static sqInt
-ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetClass, CalloutState *calloutState)
+ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState)
 {
- subclassResponsibility();
+    sqInt oop;
+    sqInt retClass;
+    sqInt retOop;
+
+ retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+ retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+ interpreterProxy->pushRemappableOop(retOop);
+ oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+ if (returnStructInRegisters((calloutState->structReturnSize))) {
+ memcpy(interpreterProxy->firstIndexableField(oop), (&longLongRet), (calloutState->structReturnSize));
+ }
+ else {
+ memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize));
+ }
+ retOop = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop, oop);
+ return interpreterProxy->methodReturnValue(retOop);
 }
 
 
@@ -2255,16 +2683,6 @@
  return 1;
 }
 
-static void
-initialize(CalloutState * self_in_initialize)
-{
- (self_in_initialize->stringArgs) = on(CArrayAccessor, new(Array, maxNumArgs(ThreadedFFIPlugin)));
- (self_in_initialize->stringArgIndex) = 0;
- (self_in_initialize->structReturnSize) = 0;
- (self_in_initialize->regIndex) = 0;
- (self_in_initialize->integerRegisters) = on(CArrayAccessor, new(Array, numRegArgs(ThreadedARMFFIPlugin)));
-}
-
 static sqInt
 isAlien(sqInt anOop)
 {
@@ -2312,22 +2730,335 @@
 EXPORT(void)
 primitiveCallout(void)
 {
+    sqInt address;
+    sqInt address1;
+    sqInt addressPtr;
+    char *allocation;
+    sqInt argClass;
+    sqInt argSpec;
+    sqInt argType;
+    sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
+    sqInt err;
     sqInt externalFunction;
+    sqInt ffiRetType;
+    sqInt flags;
+    double floatRet;
+    sqInt functionName;
+    sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt meth;
     sqInt nArgs;
-    sqInt retryCount;
+    sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
+    int *ptr;
+    sqInt *ptr1;
+    sqInt requiredStackSize;
+    sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    CalloutState theCalloutState;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
  meth = interpreterProxy->primitiveMethod();
  if (!((interpreterProxy->literalCountOf(meth)) > 0)) {
  interpreterProxy->primitiveFailFor(PrimErrBadMethod); return;
  }
  externalFunction = interpreterProxy->literalofMethod(0, meth);
+ /* begin ffiCall:ArgArrayOrNil:NumArgs: */
  nArgs = interpreterProxy->methodArgumentCount();
- retryCount = 0;
- while (((ffiCallArgArrayOrNilNumArgs(externalFunction, null, nArgs)) == PrimErrObjectMayMove)
- && (((retryCount += 1)) <= nArgs)) {
- interpreterProxy->tenuringIncrementalGC();
+ if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
+ ffiFail(FFIErrorNotFunction);
+ goto l3;
  }
+ flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction);
+ if (interpreterProxy->failed()) {
+ ffiFail(FFIErrorBadArgs);
+ goto l3;
+ }
+
+ /* must be array of arg types */
+
+ argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction);
+ if (!((interpreterProxy->isArray(argTypeArray))
+ && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) {
+ ffiFail(FFIErrorBadArgs);
+ goto l3;
+ }
+ if (!(1)) {
+ ffiFail(FFIErrorCallType);
+ goto l3;
+ }
+ /* begin ffiLoadCalloutAddress: */
+
+ /* Lookup the address */
+ /* Make sure it's an external handle */
+
+ addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction);
+ /* begin ffiContentsOfHandle:errCode: */
+ if ((addressPtr & 1)) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ if (!(interpreterProxy->isBytes(addressPtr))) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
+l4: /* end ffiContentsOfHandle:errCode: */;
+ if (interpreterProxy->failed()) {
+ address = 0;
+ goto l5;
+ }
+ if (address1 == 0) {
+ if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
+ interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1));
+ }
+ if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
+ address = ffiFail(FFIErrorNoModule);
+ goto l5;
+ }
+ address1 = ffiLoadCalloutAddressFrom(externalFunction);
+ if (interpreterProxy->failed()) {
+ address = 0;
+ goto l5;
+ }
+ ptr = interpreterProxy->firstIndexableField(addressPtr);
+ ptr[0] = address1;
+ }
+ address = address1;
+l5: /* end ffiLoadCalloutAddress: */;
+ if (interpreterProxy->failed()) {
+ goto l3;
+ }
+ requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex
+ ? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction)
+ : -1);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor((null == null
+ ? PrimErrBadMethod
+ : PrimErrBadReceiver));
+ goto l3;
+ }
+ stackSize = (requiredStackSize < 0
+ ? DefaultMaxStackSize
+ : requiredStackSize);
+ null;
+ calloutState = (&theCalloutState);
+ memset(calloutState, 0, sizeof(CalloutState));
+;
+ (calloutState->callFlags = flags);
+ argType = interpreterProxy->fetchPointerofObject(0, argTypeArray);
+ argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+ argClass = interpreterProxy->fetchPointerofObject(1, argType);
+ if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) {
+ ffiFail(err);
+ goto l3;
+ }
+ allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment()));
+ if (allocaLiesSoUseGetsp()) {
+ allocation = getsp();
+ }
+ if ((cStackAlignment()) != 0) {
+ allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1))));
+ }
+ (calloutState->argVector = allocation);
+ (calloutState->currentArg = allocation + 0);
+ (calloutState->limit = (allocation + stackSize) + 0);
+ if ((((calloutState->structReturnSize)) > 0)
+ && (1
+ && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
+ /* begin ffiPushPointer:in: */
+ pointer = (calloutState->limit);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ goto l1;
+ }
+ longAtput((calloutState->currentArg), pointer);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
+ l1: /* end ffiPushPointer:in: */;
+ }
+ for (i = 1; i <= nArgs; i += 1) {
+ argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
+ argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+ argClass = interpreterProxy->fetchPointerofObject(1, argType);
+ oop = (null == null
+ ? interpreterProxy->stackValue(nArgs - i)
+ : interpreterProxy->fetchPointerofObject(i - 1, null));
+ err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState);
+ if (err != 0) {
+ /* begin cleanupCalloutState: */
+ while (((calloutState->stringArgIndex)) > 0) {
+ free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+ }
+ ffiFail(err);
+ goto l3;
+ }
+ }
+ assert(!(interpreterProxy->failed()));
+ /* begin ffiLogCallout: */
+ if (ffiLogEnabled) {
+ functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
+ if (!(interpreterProxy->isBytes(functionName))) {
+ goto l2;
+ }
+ ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
+ }
+l2: /* end ffiLogCallout: */;
+ if ((requiredStackSize < 0)
+ && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
+ stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
+ interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
+ }
+ /* begin ffiCalloutTo:SpecOnStack:in: */
+ if ((0 + (cStackAlignment())) > 0) {
+ setsp((calloutState->argVector));
+ }
+ /* begin atomicTypeOf: */
+ typeSpec = (calloutState->ffiRetHeader);
+ atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ floatRet = dispatchFunctionPointer(((double (*)()) address));
+ }
+ else {
+ intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+ }
+ if (isCalleePopsConvention((calloutState->callFlags))) {
+ setsp((calloutState->argVector));
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+ /* begin ffiReturnPointer:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral1 = (null != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+ retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+ retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+ if (retClass1 == (interpreterProxy->nilObject())) {
+ /* begin atomicTypeOf: */
+ typeSpec1 = (calloutState->ffiRetHeader);
+ atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+ /* begin ffiReturnCStringFrom: */
+ if ((((usqInt) intRet)) == null) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+ goto l6;
+ }
+ cString = ((char *) (((usqInt) intRet)));
+ strLen = 0;
+ while (!((cString[strLen]) == 0)) {
+ strLen += 1;
+ }
+ strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+ strPtr = interpreterProxy->firstIndexableField(strOop);
+ for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+ strPtr[i1] = (cString[i1]);
+ }
+ result = interpreterProxy->methodReturnValue(strOop);
+ goto l6;
+ }
+ interpreterProxy->pushRemappableOop(retType);
+ oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+ /* return type */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l6;
+ }
+ interpreterProxy->pushRemappableOop(retClass1);
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ classOop = interpreterProxy->classByteArray();
+ }
+ else {
+ classOop = interpreterProxy->classExternalAddress();
+ }
+ oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+
+ /* return class */
+
+ retClass1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l6;
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ /* begin ffiReturnStruct:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral = (null != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+ ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+ retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+ retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+ interpreterProxy->pushRemappableOop(retOop);
+ oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+ if (returnStructInRegisters((calloutState->structReturnSize))) {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+ }
+ else {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+ }
+ retOop = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+ result = interpreterProxy->methodReturnValue(retOop);
+ goto l6;
+ }
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+ goto l6;
+ }
+ result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l6: /* end ffiCalloutTo:SpecOnStack:in: */;
+ /* begin cleanupCalloutState: */
+ while (((calloutState->stringArgIndex)) > 0) {
+ free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+ }
+l3: /* end ffiCall:ArgArrayOrNil:NumArgs: */;
  return;
 }
 
@@ -2338,26 +3069,338 @@
 EXPORT(void)
 primitiveCalloutWithArgs(void)
 {
+    sqInt address;
+    sqInt address1;
+    sqInt addressPtr;
+    char *allocation;
     sqInt argArray;
+    sqInt argClass;
+    sqInt argSpec;
+    sqInt argType;
+    sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
+    sqInt err;
     sqInt externalFunction;
+    sqInt ffiRetType;
+    sqInt flags;
+    double floatRet;
+    sqInt functionName;
+    sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt nArgs;
-    sqInt retryCount;
+    sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
+    int *ptr;
+    sqInt *ptr1;
+    sqInt requiredStackSize;
+    sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    CalloutState theCalloutState;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
  if (!((interpreterProxy->methodArgumentCount()) == 1)) {
  interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); return;
  }
- retryCount = 0;
- while (1) {
- externalFunction = interpreterProxy->stackValue(1);
- argArray = interpreterProxy->stackValue(0);
- if (!(interpreterProxy->isArray(argArray))) {
- interpreterProxy->primitiveFailFor(PrimErrBadArgument); return;
+ externalFunction = interpreterProxy->stackValue(1);
+ argArray = interpreterProxy->stackValue(0);
+ if (!(interpreterProxy->isArray(argArray))) {
+ interpreterProxy->primitiveFailFor(PrimErrBadArgument); return;
+ }
+ nArgs = interpreterProxy->slotSizeOf(argArray);
+ /* begin ffiCall:ArgArrayOrNil:NumArgs: */
+ if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
+ ffiFail(FFIErrorNotFunction);
+ goto l3;
+ }
+ flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction);
+ if (interpreterProxy->failed()) {
+ ffiFail(FFIErrorBadArgs);
+ goto l3;
+ }
+
+ /* must be array of arg types */
+
+ argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction);
+ if (!((interpreterProxy->isArray(argTypeArray))
+ && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) {
+ ffiFail(FFIErrorBadArgs);
+ goto l3;
+ }
+ if (!(1)) {
+ ffiFail(FFIErrorCallType);
+ goto l3;
+ }
+ /* begin ffiLoadCalloutAddress: */
+
+ /* Lookup the address */
+ /* Make sure it's an external handle */
+
+ addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction);
+ /* begin ffiContentsOfHandle:errCode: */
+ if ((addressPtr & 1)) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ if (!(interpreterProxy->isBytes(addressPtr))) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
+ address1 = ffiFail(FFIErrorBadAddress);
+ goto l4;
+ }
+ address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
+l4: /* end ffiContentsOfHandle:errCode: */;
+ if (interpreterProxy->failed()) {
+ address = 0;
+ goto l5;
+ }
+ if (address1 == 0) {
+ if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
+ interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1));
  }
- nArgs = interpreterProxy->slotSizeOf(argArray);
- if (!(((ffiCallArgArrayOrNilNumArgs(externalFunction, argArray, nArgs)) == PrimErrObjectMayMove)
- && (((retryCount += 1)) <= nArgs))) break;
- interpreterProxy->tenuringIncrementalGC();
+ if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
+ address = ffiFail(FFIErrorNoModule);
+ goto l5;
+ }
+ address1 = ffiLoadCalloutAddressFrom(externalFunction);
+ if (interpreterProxy->failed()) {
+ address = 0;
+ goto l5;
+ }
+ ptr = interpreterProxy->firstIndexableField(addressPtr);
+ ptr[0] = address1;
  }
+ address = address1;
+l5: /* end ffiLoadCalloutAddress: */;
+ if (interpreterProxy->failed()) {
+ goto l3;
+ }
+ requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex
+ ? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction)
+ : -1);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor((argArray == null
+ ? PrimErrBadMethod
+ : PrimErrBadReceiver));
+ goto l3;
+ }
+ stackSize = (requiredStackSize < 0
+ ? DefaultMaxStackSize
+ : requiredStackSize);
+ null;
+ calloutState = (&theCalloutState);
+ memset(calloutState, 0, sizeof(CalloutState));
+;
+ (calloutState->callFlags = flags);
+ argType = interpreterProxy->fetchPointerofObject(0, argTypeArray);
+ argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+ argClass = interpreterProxy->fetchPointerofObject(1, argType);
+ if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) {
+ ffiFail(err);
+ goto l3;
+ }
+ allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment()));
+ if (allocaLiesSoUseGetsp()) {
+ allocation = getsp();
+ }
+ if ((cStackAlignment()) != 0) {
+ allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1))));
+ }
+ (calloutState->argVector = allocation);
+ (calloutState->currentArg = allocation + 0);
+ (calloutState->limit = (allocation + stackSize) + 0);
+ if ((((calloutState->structReturnSize)) > 0)
+ && (1
+ && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
+ /* begin ffiPushPointer:in: */
+ pointer = (calloutState->limit);
+ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+ goto l1;
+ }
+ longAtput((calloutState->currentArg), pointer);
+ (calloutState->currentArg = ((calloutState->currentArg)) + 4);
+ l1: /* end ffiPushPointer:in: */;
+ }
+ for (i = 1; i <= nArgs; i += 1) {
+ argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
+ argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+ argClass = interpreterProxy->fetchPointerofObject(1, argType);
+ oop = (argArray == null
+ ? interpreterProxy->stackValue(nArgs - i)
+ : interpreterProxy->fetchPointerofObject(i - 1, argArray));
+ err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState);
+ if (err != 0) {
+ /* begin cleanupCalloutState: */
+ while (((calloutState->stringArgIndex)) > 0) {
+ free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+ }
+ ffiFail(err);
+ goto l3;
+ }
+ }
+ assert(!(interpreterProxy->failed()));
+ /* begin ffiLogCallout: */
+ if (ffiLogEnabled) {
+ functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
+ if (!(interpreterProxy->isBytes(functionName))) {
+ goto l2;
+ }
+ ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
+ }
+l2: /* end ffiLogCallout: */;
+ if ((requiredStackSize < 0)
+ && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
+ stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
+ interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
+ }
+ /* begin ffiCalloutTo:SpecOnStack:in: */
+ if ((0 + (cStackAlignment())) > 0) {
+ setsp((calloutState->argVector));
+ }
+ /* begin atomicTypeOf: */
+ typeSpec = (calloutState->ffiRetHeader);
+ atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ floatRet = dispatchFunctionPointer(((double (*)()) address));
+ }
+ else {
+ intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+ }
+ if (isCalleePopsConvention((calloutState->callFlags))) {
+ setsp((calloutState->argVector));
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+ /* begin ffiReturnPointer:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral1 = (argArray != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+ retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+ retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+ if (retClass1 == (interpreterProxy->nilObject())) {
+ /* begin atomicTypeOf: */
+ typeSpec1 = (calloutState->ffiRetHeader);
+ atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+ if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+ /* begin ffiReturnCStringFrom: */
+ if ((((usqInt) intRet)) == null) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+ goto l6;
+ }
+ cString = ((char *) (((usqInt) intRet)));
+ strLen = 0;
+ while (!((cString[strLen]) == 0)) {
+ strLen += 1;
+ }
+ strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+ strPtr = interpreterProxy->firstIndexableField(strOop);
+ for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+ strPtr[i1] = (cString[i1]);
+ }
+ result = interpreterProxy->methodReturnValue(strOop);
+ goto l6;
+ }
+ interpreterProxy->pushRemappableOop(retType);
+ oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+ /* return type */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l6;
+ }
+ interpreterProxy->pushRemappableOop(retClass1);
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ classOop = interpreterProxy->classByteArray();
+ }
+ else {
+ classOop = interpreterProxy->classExternalAddress();
+ }
+ oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+ ptr1 = interpreterProxy->firstIndexableField(oop1);
+ ptr1[0] = (((sqInt) intRet));
+
+ /* return class */
+
+ retClass1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->pushRemappableOop(oop1);
+ retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+ /* external address */
+
+ oop1 = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+ result = interpreterProxy->methodReturnValue(retOop1);
+ goto l6;
+ }
+ if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+ /* begin ffiReturnStruct:ofType:in: */
+ /* begin ffiReturnType: */
+ specLiteral = (argArray != null
+ ? interpreterProxy->stackValue(1)
+ : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+ argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+ ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+ retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+ retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+ interpreterProxy->pushRemappableOop(retOop);
+ oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+ if (returnStructInRegisters((calloutState->structReturnSize))) {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+ }
+ else {
+ memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+ }
+ retOop = interpreterProxy->popRemappableOop();
+ interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+ result = interpreterProxy->methodReturnValue(retOop);
+ goto l6;
+ }
+ if ((atomicType == FFITypeSingleFloat)
+ || (atomicType == FFITypeDoubleFloat)) {
+ result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+ goto l6;
+ }
+ result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l6: /* end ffiCalloutTo:SpecOnStack:in: */;
+ /* begin cleanupCalloutState: */
+ while (((calloutState->stringArgIndex)) > 0) {
+ free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+ }
+l3: /* end ffiCall:ArgArrayOrNil:NumArgs: */;
  return;
 }
 
@@ -2870,8 +3913,7 @@
 /* Answer any space needed to prevent the alloca'ed outgoing arguments
  marshalling area from
  being overwritten by any register arguments during calls during
- marshalling. On ARM we
- believe this is zero. */
+ marshalling. On x86 this is 0 */
 
 static sqInt
 registerArgsSlop(void)
@@ -2880,15 +3922,6 @@
 }
 
 
-/* Answer if a struct result of a given size is returned in memory or not. */
-
-static sqInt
-returnStructInRegisters(sqInt returnStructSize)
-{
- return subclassResponsibility();
-}
-
-
 /* Note: This is coded so that is can be run from Squeak. */
 
 EXPORT(sqInt)