[Vm-dev] [commit][2898] CogVM source as per VMMaker.oscog-eem.685.

commits at squeakvm.org commits at squeakvm.org
Mon Apr 21 19:44:56 UTC 2014


Revision: 2898
Author:   eliot
Date:     2014-04-21 12:44:55 -0700 (Mon, 21 Apr 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.685.

Add the new ARMFFIPlugin derived from ThreadedARMFFIPlugin (thanks Doug!!).
Generate the ThreadedIA32Plugin as IA32FFIPlugin and include either based on
the relevant defines from a now skeletal SqueakFFIPrims/SqueakFFIPrims.c.

Add history and product directories for a better organised build (arriving RSN).

Modified Paths:
--------------
    branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c

Added Paths:
-----------
    branches/Cog/history/
    branches/Cog/products/
    branches/Cog/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c
    branches/Cog/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c

Added: branches/Cog/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c
===================================================================
--- branches/Cog/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c	                        (rev 0)
+++ branches/Cog/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c	2014-04-21 19:44:55 UTC (rev 2898)
@@ -0,0 +1,5819 @@
+/* Automatically generated by
+	VMPluginCodeGenerator VMMaker.oscog-eem.685 uuid: 07bc1e83-6566-4de0-af79-d6c7874ffcdd
+   from
+	ThreadedARMFFIPlugin VMMaker.oscog-eem.685 uuid: 07bc1e83-6566-4de0-af79-d6c7874ffcdd
+ */
+static char __buildInfo[] = "ThreadedARMFFIPlugin VMMaker.oscog-eem.685 uuid: 07bc1e83-6566-4de0-af79-d6c7874ffcdd " __DATE__ ;
+
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Default EXPORT macro that does nothing (see comment in sq.h): */
+#define EXPORT(returnType) returnType
+
+/* Do not include the entire sq.h file but just those parts needed. */
+/*  The virtual machine proxy definition */
+#include "sqVirtualMachine.h"
+/* Configuration options */
+#include "sqConfig.h"
+/* Platform specific definitions */
+#include "sqPlatformSpecific.h"
+
+#define true 1
+#define false 0
+#define null 0  /* using 'null' because nil is predefined in Think C */
+#ifdef SQUEAK_BUILTIN_PLUGIN
+#undef EXPORT
+// was #undef EXPORT(returnType) but screws NorCroft cc
+#define EXPORT(returnType) static returnType
+#endif
+
+#include "sqMemoryAccess.h"
+
+
+/* ThreadedFFIPlugin class>>preambleCCode */
+
+#include "sqAssert.h" /* for assert */
+
+#ifdef _MSC_VER
+# define alloca _alloca
+#endif
+#if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))
+# define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp))
+# define getsp() ({ void *esp; asm volatile ("movl %%esp,%0" : "=r"(esp) : ); esp;})
+# elif defined(__GNUC__) && (defined(__arm__))
+# define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp))
+# define getsp() ({ void *sp; asm volatile ("mov %0, %%sp" : "=r"(sp) : ); sp;})
+#endif
+#if !defined(getsp)
+# define getsp() 0
+#endif 
+#if !defined(setsp)
+# 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
+# elif defined(__arm__) 
+#  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
+#endif
+
+#if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
+/* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size
+ * less than or equal to eight bytes in length in registers. Linux never does so.
+ */
+# if __linux__
+#	define WIN32_X86_STRUCT_RETURN 0
+# else
+#	define WIN32_X86_STRUCT_RETURN 1
+# endif
+# if WIN32
+#	define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1
+# else
+#	define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0
+# endif
+#endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */
+
+#if defined(__arm__)
+#	define WIN32_X86_STRUCT_RETURN 0
+#	define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0
+#endif /* defined(__arm__) */
+
+#if !defined(ALLOCA_LIES_SO_USE_GETSP)
+# if defined(__MINGW32__) && (__GNUC__ >= 3)
+    /*
+     * cygwin -mno-cygwin (MinGW) gcc 3.4.x's alloca is a library routine that answers
+     * %esp + 4, so the outgoing stack is offset by one word if uncorrected.
+     * Grab the actual stack pointer to correct.
+     */
+#	define ALLOCA_LIES_SO_USE_GETSP 1
+# else
+#	define ALLOCA_LIES_SO_USE_GETSP 0
+# endif
+#endif /* !defined(ALLOCA_LIES_SO_USE_GETSP) */
+
+/* The dispatchOn:in:with:with: generates an unwanted call on error.  Just squash it. */
+#define error(foo) 0
+
+/* but print assert failures. */
+void
+warning(char *s) { /* Print an error message but don't exit. */
+	printf("\n%s\n", s);
+}
+
+/* end ThreadedFFIPlugin class>>preambleCCode */
+
+typedef struct {
+	char *argVector;
+	char *currentArg;
+	char *limit;
+	sqInt	structReturnSize;
+	sqInt	callFlags;
+	void *ffiArgSpec;
+	sqInt	ffiArgSpecSize;
+	sqInt	ffiArgHeader;
+	sqInt	ffiRetHeader;
+	sqInt	stringArgIndex;
+	char *stringArgs [15];
+	sqInt	integerRegisterIndex;
+	sqInt		integerRegisters [4];
+	sqInt	floatRegisterIndex;
+	sqInt	backfillFloatRegisterIndex;
+	float		floatRegisters [16];
+ } CalloutState;
+
+#define ThreadedFFICalloutStateForARM CalloutState
+
+
+
+/*** Constants ***/
+#define DefaultMaxStackSize 16384
+#define ExternalFunctionArgTypesIndex 2
+#define ExternalFunctionFlagsIndex 1
+#define ExternalFunctionStackSizeIndex 3
+#define FFIAtomicTypeMask 0xF000000
+#define FFIAtomicTypeShift 24
+#define FFICallFlagThreaded 0x100
+#define FFICallTypeApi 1
+#define FFICallTypeCDecl 0
+#define FFICallTypesMask 0xFF
+#define FFIErrorAddressNotFound 13
+#define FFIErrorAttemptToPassVoid 14
+#define FFIErrorBadAddress 11
+#define FFIErrorBadArg 3
+#define FFIErrorBadArgs 2
+#define FFIErrorBadAtomicType 5
+#define FFIErrorBadExternalFunction 17
+#define FFIErrorBadExternalLibrary 16
+#define FFIErrorBadReturn 10
+#define FFIErrorCallFrameTooBig 19
+#define FFIErrorCallType 9
+#define FFIErrorCoercionFailed 6
+#define FFIErrorIntAsPointer 4
+#define FFIErrorInvalidPointer 18
+#define FFIErrorModuleNotFound 15
+#define FFIErrorNoModule 12
+#define FFIErrorNotFunction 1
+#define FFIErrorStructSize 8
+#define FFIErrorWrongType 7
+#define FFIFlagAtomic 0x40000
+#define FFIFlagPointer 0x20000
+#define FFIFlagStructure 0x10000
+#define FFINoCalloutAvailable -1
+#define FFIStructSizeMask 0xFFFF
+#define FFITypeBool 1
+#define FFITypeDoubleFloat 13
+#define FFITypeSignedByte 3
+#define FFITypeSignedChar 11
+#define FFITypeSignedInt 7
+#define FFITypeSignedLongLong 9
+#define FFITypeSignedShort 5
+#define FFITypeSingleFloat 12
+#define FFITypeUnsignedByte 2
+#define FFITypeVoid 0
+#define MaxNumArgs 15
+#define NumFloatRegArgs 16
+#define NumIntRegArgs 4
+#define PrimErrBadArgument 3
+#define PrimErrBadMethod 12
+#define PrimErrBadNumArgs 5
+#define PrimErrBadReceiver 2
+#define PrimErrNoCMemory 10
+#define PrimErrObjectMayMove 14
+
+
+/*** Function Prototypes ***/
+static sqInt atomicTypeOf(sqInt typeSpec);
+static void cleanupCalloutState(CalloutState *calloutState);
+static void dummyFloatFunctionwithwithwithwithwithwithwith(double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8);
+static sqInt externalFunctionHasStackSizeSlot(void);
+static sqInt 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 ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState);
+static sqInt ffiAtomicStructByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *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);
+static sqInt ffiCreateIntegralResultOopofAtomicTypein(usqLong retVal, sqInt atomicType, CalloutState *calloutState);
+static sqInt ffiFail(sqInt reason);
+static double ffiFloatValueOf(sqInt oop);
+static sqInt ffiIntegerValueOf(sqInt oop);
+static sqInt ffiLoadCalloutAddressFrom(sqInt oop);
+static sqInt ffiLoadCalloutAddress(sqInt lit);
+static sqInt ffiLoadCalloutModule(sqInt module);
+static void ffiLogCallout(sqInt lit);
+EXPORT(sqInt) ffiLogCallsTo(char*fileName);
+static sqInt ffiPushDoubleFloatin(double value, CalloutState *calloutState);
+static sqInt ffiPushPointerContentsOfin(sqInt oop, 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 ffiPushSignedShortin(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);
+static sqInt ffiPushUnsignedBytein(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushUnsignedCharin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushUnsignedLongLongOopin(sqInt oop, CalloutState *calloutState);
+static sqInt ffiPushUnsignedLongLongin(usqLong 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 ffiRetType, CalloutState *calloutState);
+static sqInt ffiReturnType(sqInt specOnStack);
+static sqInt ffiSupportsCallingConvention(sqInt aCallingConvention);
+static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType);
+static VirtualMachine * getInterpreter(void);
+EXPORT(const char*) getModuleName(void);
+static sqInt halt(void);
+EXPORT(sqInt) initialiseModule(void);
+static sqInt isAlien(sqInt anOop);
+static sqInt isAtomicType(sqInt typeSpec);
+static sqInt isDirectAlien(sqInt oop);
+static sqInt msg(char *s);
+static sqInt nonRegisterStructReturnIsViaImplicitFirstArgument(void);
+EXPORT(void) primitiveCallout(void);
+EXPORT(void) primitiveCalloutWithArgs(void);
+EXPORT(sqInt) primitiveCreateManualSurface(void);
+EXPORT(sqInt) primitiveDestroyManualSurface(void);
+EXPORT(sqInt) primitiveFFIAllocate(void);
+EXPORT(sqInt) primitiveFFIDoubleAt(void);
+EXPORT(sqInt) primitiveFFIDoubleAtPut(void);
+EXPORT(sqInt) primitiveFFIFloatAt(void);
+EXPORT(sqInt) primitiveFFIFloatAtPut(void);
+EXPORT(sqInt) primitiveFFIFree(void);
+EXPORT(sqInt) primitiveFFIGetLastError(void);
+EXPORT(sqInt) primitiveFFIIntegerAt(void);
+EXPORT(sqInt) primitiveFFIIntegerAtPut(void);
+EXPORT(sqInt) primitiveForceLoad(void);
+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);
+
+
+/*** Variables ***/
+static sqInt externalFunctionInstSize;
+static sqInt ffiLastError;
+static sqInt ffiLogEnabled;
+
+#if !defined(SQUEAK_BUILTIN_PLUGIN)
+static sqInt (*booleanValueOf)(sqInt obj);
+static sqInt (*byteSizeOf)(sqInt oop);
+static sqInt (*characterTable)(void);
+static sqInt (*characterValueOf)(sqInt aCharacter);
+static sqInt (*classAlien)(void);
+static sqInt (*classByteArray)(void);
+static sqInt (*classCharacter)(void);
+static sqInt (*classExternalAddress)(void);
+static sqInt (*classExternalData)(void);
+static sqInt (*classExternalFunction)(void);
+static sqInt (*classExternalLibrary)(void);
+static sqInt (*classExternalStructure)(void);
+static sqInt (*classFloat)(void);
+static sqInt (*classLargePositiveInteger)(void);
+static sqInt (*classString)(void);
+static sqInt (*disownVM)(sqInt flags);
+static sqInt (*failed)(void);
+static sqInt (*falseObject)(void);
+static sqInt (*fetchClassOf)(sqInt oop);
+static sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer);
+static sqInt (*fetchPointerofObject)(sqInt index, sqInt oop);
+static void * (*firstIndexableField)(sqInt oop);
+static sqInt (*floatObjectOf)(double  aFloat);
+static double (*floatValueOf)(sqInt oop);
+static sqInt (*includesBehaviorThatOf)(sqInt aClass, sqInt aSuperclass);
+static sqInt (*instanceSizeOf)(sqInt classObj);
+static sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size);
+static sqInt (*integerObjectOf)(sqInt value);
+static sqInt (*integerValueOf)(sqInt oop);
+static void * (*ioLoadModuleOfLength)(sqInt moduleNameIndex, sqInt moduleLength);
+static void * (*ioLoadSymbolOfLengthFromModule)(sqInt functionNameIndex, sqInt functionLength, sqInt moduleHandle);
+static sqInt (*isKindOfClass)(sqInt oop, sqInt aClass);
+static sqInt (*isArray)(sqInt oop);
+static sqInt (*isBytes)(sqInt oop);
+static sqInt (*isImmediate)(sqInt anObject);
+static sqInt (*isInMemory)(sqInt address);
+static sqInt (*isIntegerObject)(sqInt objectPointer);
+static sqInt (*isPointers)(sqInt oop);
+static sqInt (*isWords)(sqInt oop);
+static sqInt (*isYoung)(sqInt anOop);
+static sqInt (*literalofMethod)(sqInt offset, sqInt methodPointer);
+static sqInt (*literalCountOf)(sqInt methodPointer);
+static sqInt (*methodArgumentCount)(void);
+static sqInt (*methodReturnValue)(sqInt oop);
+static sqInt (*nilObject)(void);
+static sqInt (*ownVM)(sqInt flags);
+static sqInt (*pop)(sqInt nItems);
+static sqInt (*popthenPush)(sqInt nItems, sqInt oop);
+static sqInt (*popRemappableOop)(void);
+static sqInt (*positive32BitIntegerFor)(sqInt integerValue);
+static sqInt (*positive32BitValueOf)(sqInt oop);
+static sqInt (*positive64BitIntegerFor)(sqLong integerValue);
+static sqLong (*positive64BitValueOf)(sqInt oop);
+static sqInt (*primitiveErrorTable)(void);
+static sqInt (*primitiveFail)(void);
+static sqInt (*primitiveFailFor)(sqInt reasonCode);
+static sqInt (*primitiveMethod)(void);
+static sqInt (*pushFloat)(double  f);
+static sqInt (*pushInteger)(sqInt integerValue);
+static sqInt (*pushRemappableOop)(sqInt oop);
+static sqInt (*signed32BitIntegerFor)(sqInt integerValue);
+static int (*signed32BitValueOf)(sqInt oop);
+static sqInt (*signed64BitIntegerFor)(sqLong integerValue);
+static sqLong (*signed64BitValueOf)(sqInt oop);
+static long (*signedMachineIntegerValueOf)(sqInt oop);
+static sqInt (*slotSizeOf)(sqInt oop);
+static sqInt (*stackIntegerValue)(sqInt offset);
+static sqInt (*stackObjectValue)(sqInt offset);
+static sqInt (*stackValue)(sqInt offset);
+static sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer);
+static sqInt (*storePointerofObjectwithValue)(sqInt index, sqInt oop, sqInt valuePointer);
+static sqInt (*tenuringIncrementalGC)(void);
+static sqInt (*trueObject)(void);
+#else /* !defined(SQUEAK_BUILTIN_PLUGIN) */
+extern sqInt booleanValueOf(sqInt obj);
+extern sqInt byteSizeOf(sqInt oop);
+extern sqInt characterTable(void);
+#if VM_PROXY_MAJOR > 1 || (VM_PROXY_MAJOR == 1 && VM_PROXY_MINOR >= 13)
+extern sqInt characterValueOf(sqInt aCharacter);
+#else
+# define characterValueOf(aCharacter) 0
+#endif
+extern sqInt classAlien(void);
+extern sqInt classByteArray(void);
+extern sqInt classCharacter(void);
+extern sqInt classExternalAddress(void);
+extern sqInt classExternalData(void);
+extern sqInt classExternalFunction(void);
+extern sqInt classExternalLibrary(void);
+extern sqInt classExternalStructure(void);
+extern sqInt classFloat(void);
+extern sqInt classLargePositiveInteger(void);
+extern sqInt classString(void);
+extern sqInt disownVM(sqInt flags);
+extern sqInt failed(void);
+extern sqInt falseObject(void);
+extern sqInt fetchClassOf(sqInt oop);
+extern sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer);
+extern sqInt fetchPointerofObject(sqInt index, sqInt oop);
+extern void * firstIndexableField(sqInt oop);
+extern sqInt floatObjectOf(double  aFloat);
+extern double floatValueOf(sqInt oop);
+extern sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperclass);
+extern sqInt instanceSizeOf(sqInt classObj);
+extern sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size);
+extern sqInt integerObjectOf(sqInt value);
+extern sqInt integerValueOf(sqInt oop);
+extern void * ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleLength);
+extern void * ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionLength, sqInt moduleHandle);
+extern sqInt isKindOfClass(sqInt oop, sqInt aClass);
+extern sqInt isArray(sqInt oop);
+extern sqInt isBytes(sqInt oop);
+#if VM_PROXY_MAJOR > 1 || (VM_PROXY_MAJOR == 1 && VM_PROXY_MINOR >= 13)
+extern sqInt isImmediate(sqInt anObject);
+#else
+# define isImmediate(anObject) 0
+#endif
+extern sqInt isInMemory(sqInt address);
+extern sqInt isIntegerObject(sqInt objectPointer);
+extern sqInt isPointers(sqInt oop);
+extern sqInt isWords(sqInt oop);
+extern sqInt isYoung(sqInt anOop);
+extern sqInt literalofMethod(sqInt offset, sqInt methodPointer);
+extern sqInt literalCountOf(sqInt methodPointer);
+extern sqInt methodArgumentCount(void);
+extern sqInt methodReturnValue(sqInt oop);
+extern sqInt nilObject(void);
+extern sqInt ownVM(sqInt flags);
+extern sqInt pop(sqInt nItems);
+extern sqInt popthenPush(sqInt nItems, sqInt oop);
+extern sqInt popRemappableOop(void);
+extern sqInt positive32BitIntegerFor(sqInt integerValue);
+extern sqInt positive32BitValueOf(sqInt oop);
+extern sqInt positive64BitIntegerFor(sqLong integerValue);
+extern sqLong positive64BitValueOf(sqInt oop);
+extern sqInt primitiveErrorTable(void);
+extern sqInt primitiveFail(void);
+extern sqInt primitiveFailFor(sqInt reasonCode);
+extern sqInt primitiveMethod(void);
+extern sqInt pushFloat(double  f);
+extern sqInt pushInteger(sqInt integerValue);
+extern sqInt pushRemappableOop(sqInt oop);
+extern sqInt signed32BitIntegerFor(sqInt integerValue);
+extern int signed32BitValueOf(sqInt oop);
+extern sqInt signed64BitIntegerFor(sqLong integerValue);
+extern sqLong signed64BitValueOf(sqInt oop);
+extern long signedMachineIntegerValueOf(sqInt oop);
+extern sqInt slotSizeOf(sqInt oop);
+extern sqInt stackIntegerValue(sqInt offset);
+extern sqInt stackObjectValue(sqInt offset);
+extern sqInt stackValue(sqInt offset);
+extern sqInt storeIntegerofObjectwithValue(sqInt index, sqInt oop, sqInt integer);
+extern sqInt storePointerofObjectwithValue(sqInt index, sqInt oop, sqInt valuePointer);
+extern sqInt tenuringIncrementalGC(void);
+extern sqInt trueObject(void);
+extern
+#endif
+struct VirtualMachine* interpreterProxy;
+static const char *moduleName =
+#ifdef SQUEAK_BUILTIN_PLUGIN
+	"ARM32FFIPlugin VMMaker.oscog-eem.685 (i)"
+#else
+	"ARM32FFIPlugin VMMaker.oscog-eem.685 (e)"
+#endif
+;
+
+
+/*** Macros ***/
+#define allocaLiesSoUseGetsp() ALLOCA_LIES_SO_USE_GETSP
+#define cStackAlignment() STACK_ALIGN_BYTES
+#define dispatchFunctionPointer(aFunctionPointer) (aFunctionPointer)()
+#define dispatchFunctionPointerwithwithwithwith(aFunctionPointer, int1, int2, int3, int4) (aFunctionPointer)(int1, int2, int3, int4)
+#define ffiAlloc(bytes) (usqInt)malloc(bytes)
+#define ffiFree(pointer) free((void *)(pointer))
+#define isCalleePopsConvention(callType) (PLATFORM_API_USES_CALLEE_POPS_CONVENTION && (callType) == FFICallTypeApi)
+
+
+static sqInt
+atomicTypeOf(sqInt typeSpec)
+{
+	return ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+}
+
+
+/*	Free any temporary arg strings. */
+
+static void
+cleanupCalloutState(CalloutState *calloutState)
+{
+	while (((calloutState->stringArgIndex)) > 0) {
+		free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+	}
+}
+
+static void
+dummyFloatFunctionwithwithwithwithwithwithwith(double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8)
+{
+}
+
+static sqInt
+externalFunctionHasStackSizeSlot(void)
+{
+	return externalFunctionInstSize > ExternalFunctionStackSizeIndex;
+}
+
+
+/*	return an int of the address of the byteSize slot (byte, short, int,
+	whatever) at byteOffset in rcvr. Nominally intended for use with
+	ExternalAddress objects, this code will work (for obscure historical
+	reasons) with plain Byte or Word Arrays as well.
+ */
+
+static sqInt
+ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize)
+{
+    int addr;
+    sqInt rcvrClass;
+    sqInt rcvrSize;
+
+	if (!(isBytes(rcvr))) {
+		return primitiveFail();
+	}
+	if (!(byteOffset > 0)) {
+		return primitiveFail();
+	}
+	rcvrClass = fetchClassOf(rcvr);
+	rcvrSize = byteSizeOf(rcvr);
+	if (rcvrClass == (classExternalAddress())) {
+		if (!(rcvrSize == 4)) {
+			return primitiveFail();
+		}
+
+		/* don't you dare to read from object memory! */
+
+addr = fetchPointerofObject(0, rcvr);
+		if ((addr == 0)
+		 || (isInMemory(addr))) {
+			return primitiveFail();
+		}
+	}
+	else {
+if (!(((byteOffset + byteSize) - 1) <= rcvrSize)) {
+			return primitiveFail();
+		}
+		addr = ((int) (firstIndexableField(rcvr)));
+	}
+	addr = (addr + byteOffset) - 1;
+	return addr;
+}
+
+
+/*	Support for generic callout. Prepare an argument by value for a callout. */
+
+static sqInt
+ffiArgByValuein(sqInt oop, CalloutState *calloutState)
+{
+    sqInt atomicType;
+    double floatValue;
+    sqInt intValue;
+    sqInt oopClass;
+    sqInt oopClass1;
+    sqInt typeSpec;
+
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiArgHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if ((atomicType < 0)
+	 || (atomicType > FFITypeDoubleFloat)) {
+return FFIErrorBadAtomicType;
+	}
+	if (atomicType < FFITypeSingleFloat) {
+
+		/* integer types */
+
+if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) {
+
+			/* ffi support code must coerce longlong */
+
+intValue = oop;
+		}
+		else {
+/* begin ffiIntegerValueOf: */
+			if (isIntegerObject(oop)) {
+				intValue = integerValueOf(oop);
+				goto l1;
+			}
+			if (oop == (nilObject())) {
+				intValue = 0;
+				goto l1;
+			}
+			if (oop == (falseObject())) {
+				intValue = 0;
+				goto l1;
+			}
+			if (oop == (trueObject())) {
+				intValue = 1;
+				goto l1;
+			}
+			oopClass = fetchClassOf(oop);
+			if (oopClass == (classFloat())) {
+				intValue = ((sqInt)(floatValueOf(oop)));
+				goto l1;
+			}
+			if (oopClass == (classCharacter())) {
+				intValue = characterValueOf(oop);
+				goto l1;
+			}
+			if (oopClass == (classLargePositiveInteger())) {
+				intValue = positive32BitValueOf(oop);
+				goto l1;
+			}
+			intValue = signedMachineIntegerValueOf(oop);
+		l1:	/* end ffiIntegerValueOf: */;
+		}
+		if (failed()) {
+			return FFIErrorCoercionFailed;
+		}
+		
+		switch (atomicType) {
+		case 0:
+			return FFIErrorAttemptToPassVoid;
+		case 1:
+			return ffiPushUnsignedIntin(intValue, calloutState);
+		case 2:
+			return ffiPushUnsignedBytein(intValue, calloutState);
+		case 3:
+			return ffiPushSignedBytein(intValue, calloutState);
+		case 4:
+			return ffiPushUnsignedShortin(intValue, calloutState);
+		case 5:
+			return ffiPushSignedShortin(intValue, calloutState);
+		case 6:
+			return ffiPushUnsignedIntin(intValue, calloutState);
+		case 7:
+			return ffiPushSignedIntin(intValue, calloutState);
+		case 8:
+			return ffiPushUnsignedLongLongOopin(intValue, calloutState);
+		case 9:
+			return ffiPushSignedLongLongOopin(intValue, calloutState);
+		case 10:
+			return ffiPushUnsignedCharin(intValue, calloutState);
+		case 11:
+			return ffiPushSignedCharin(intValue, calloutState);
+
+		default:
+			error("Case not found");
+			return -1;
+		}
+	}
+	/* begin ffiFloatValueOf: */
+	oopClass1 = fetchClassOf(oop);
+	if (oopClass1 == (classFloat())) {
+		floatValue = floatValueOf(oop);
+		goto l2;
+	}
+	floatValue = ((double) (ffiIntegerValueOf(oop)) );
+l2:	/* end ffiFloatValueOf: */;
+	if (failed()) {
+		return FFIErrorCoercionFailed;
+	}
+	if (atomicType == FFITypeSingleFloat) {
+/* begin ffiPushSingleFloat:in: */
+		if (((calloutState->floatRegisterIndex)) < NumFloatRegArgs) {
+			if (((calloutState->backfillFloatRegisterIndex)) > 0) {
+				((calloutState->floatRegisters))[(calloutState->backfillFloatRegisterIndex)] = floatValue;
+				(calloutState->backfillFloatRegisterIndex = 0);
+			}
+			else {
+((calloutState->floatRegisters))[(calloutState->floatRegisterIndex)] = floatValue;
+				(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 1);
+			}
+		}
+		else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+		}
+		return 0;
+	}
+	else {
+/* begin ffiPushDoubleFloat:in: */
+		if (((calloutState->floatRegisterIndex)) < (NumFloatRegArgs - 1)) {
+			if ((((calloutState->floatRegisterIndex)) & 1) == 1) {
+				(calloutState->backfillFloatRegisterIndex = (calloutState->floatRegisterIndex));
+				(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 1);
+			}
+			(((double*) ((&(((calloutState->floatRegisters))[(calloutState->floatRegisterIndex)])))))[0] = floatValue;
+			(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 2);
+		}
+		else {
+if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			(calloutState->floatRegisterIndex = NumFloatRegArgs);
+			storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 8);
+		}
+		return 0;
+	}
+}
+
+
+/*	Callout support. Prepare the given oop as argument.
+	argSpec defines the compiled spec for the argument.
+	argClass (if non-nil) defines the required (super)class for the argument. */
+
+static sqInt
+ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState)
+{
+    sqInt *argSpec1;
+    sqInt *argSpec2;
+    sqInt argSpecSize;
+    sqInt argSpecSize1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    sqInt atomicType2;
+    sqInt availableRegisterSpace;
+    sqInt availableRegisterSpace1;
+    char *copy;
+    sqInt err;
+    double floatValue;
+    sqInt intValue;
+    sqInt isAlien;
+    sqInt isString;
+    sqInt isStruct;
+    sqInt length;
+    sqInt nilOop;
+    sqInt oopClass;
+    sqInt oopClass1;
+    sqInt oopClass2;
+    char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
+    int ptrAddress;
+    sqInt ptrClass;
+    sqInt ptrType;
+    sqInt roundedSize;
+    sqInt roundedSize1;
+    sqInt spec;
+    sqInt specOop;
+    sqInt specType;
+    sqInt stackPartSize;
+    sqInt stackPartSize1;
+    sqInt structSize;
+    sqInt structSize1;
+    sqInt typeSpec;
+    sqInt typeSpec1;
+    sqInt typeSpec2;
+    sqInt valueOop;
+    sqInt valueOop1;
+
+
+	/* Prefetch class (we'll need it) */
+
+oopClass = fetchClassOf(oop);
+
+	/* Do the necessary type checks */
+
+nilOop = nilObject();
+	if (!(argClass == nilOop)) {
+
+		/* Type check 1:
+		   Is the required class of the argument a subclass of ExternalStructure? */
+
+		if (!(includesBehaviorThatOf(argClass, classExternalStructure()))) {
+			return FFIErrorWrongType;
+		}
+		if (!((nilOop == oop)
+			 || (includesBehaviorThatOf(oopClass, argClass)))) {
+			return FFIErrorCoercionFailed;
+		}
+	}
+	isStruct = 0;
+	if (!((isImmediate(oop))
+		 || (oop == nilOop))) {
+
+		/* #isPointers: will fail if oop is immediate so don't even attempt to use it */
+
+if (isPointers(oop)) {
+			isStruct = includesBehaviorThatOf(oopClass, classExternalStructure());
+			if (!((argClass == nilOop)
+				 || (isStruct))) {
+				return FFIErrorCoercionFailed;
+			}
+		}
+	}
+	if (isStruct) {
+valueOop = fetchPointerofObject(0, oop);
+	}
+	else {
+valueOop = oop;
+	}
+	if (!(isWords(argSpec))) {
+		return FFIErrorWrongType;
+	}
+	(calloutState->ffiArgSpecSize = slotSizeOf(argSpec));
+	if (((calloutState->ffiArgSpecSize)) == 0) {
+		return FFIErrorWrongType;
+	}
+	(calloutState->ffiArgSpec = firstIndexableField(argSpec));
+	(calloutState->ffiArgHeader = longAt((calloutState->ffiArgSpec)));
+	if (((calloutState->ffiArgHeader)) & FFIFlagStructure) {
+
+		/* argument must be ExternalStructure */
+
+if (!isStruct) {
+return FFIErrorCoercionFailed;
+		}
+		if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) {
+			return FFIErrorWrongType;
+		}
+		/* begin ffiPushStructureContentsOf:in: */
+		ptrClass = fetchClassOf(valueOop);
+		if (ptrClass == (classExternalAddress())) {
+
+			/* ExternalAddress is bytes */
+
+
+			/* There is no way we can make sure the structure is valid.
+			   But we can at least check for attempts to pass pointers to ST memory. */
+
+			ptrAddress = fetchPointerofObject(0, valueOop);
+			if (isInMemory(ptrAddress)) {
+				return FFIErrorInvalidPointer;
+			}
+			/* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
+			structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
+			argSpec2 = (calloutState->ffiArgSpec);
+			argSpecSize = (calloutState->ffiArgSpecSize);
+			availableRegisterSpace = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * 4;
+			stackPartSize = structSize;
+			if (availableRegisterSpace > 0) {
+if (structSize <= availableRegisterSpace) {
+
+					/* all in registers */
+
+stackPartSize = 0;
+					memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ((void *) ptrAddress), structSize);
+					(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + (((usqInt) (structSize + 3) >> 2)));
+				}
+				else {
+
+					/* some in registers rest on stack */
+
+stackPartSize = structSize - availableRegisterSpace;
+					memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ((void *) ptrAddress), availableRegisterSpace);
+					(calloutState->integerRegisterIndex = NumIntRegArgs);
+				}
+			}
+			if (stackPartSize > 0) {
+roundedSize = (((stackPartSize + 3) | 3) - 3);
+				if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				memcpy((calloutState->currentArg), (&((((char *) (((void *) ptrAddress))))[availableRegisterSpace])), stackPartSize);
+				(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+			}
+			return 0;
+		}
+		if (ptrClass == (classByteArray())) {
+
+			/* The following is a somewhat pessimistic test but I like being sure... */
+
+if (!((byteSizeOf(valueOop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) {
+				return FFIErrorStructSize;
+			}
+			ptrAddress = ((int) (firstIndexableField(valueOop)));
+			if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) {
+
+				/* Since this involves passing the address of the first indexable field we need to fail
+				   the call if it is threaded and the object is young, since it may move during the call. */
+
+				
+#        if COGMTVM
+				if ((((calloutState->callFlags)) & FFICallFlagThreaded)
+				 && (isYoung(valueOop))) {
+					return -PrimErrObjectMayMove;
+				}
+
+#        endif /* COGMTVM */
+
+				/* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
+				structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
+				argSpec1 = (calloutState->ffiArgSpec);
+				argSpecSize1 = (calloutState->ffiArgSpecSize);
+				availableRegisterSpace1 = (NumIntRegArgs - ((calloutState->integerRegisterIndex))) * 4;
+				stackPartSize1 = structSize1;
+				if (availableRegisterSpace1 > 0) {
+if (structSize1 <= availableRegisterSpace1) {
+
+						/* all in registers */
+
+stackPartSize1 = 0;
+						memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ((void *) ptrAddress), structSize1);
+						(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + (((usqInt) (structSize1 + 3) >> 2)));
+					}
+					else {
+
+						/* some in registers rest on stack */
+
+stackPartSize1 = structSize1 - availableRegisterSpace1;
+						memcpy(((void *) ((&(((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)])))), ((void *) ptrAddress), availableRegisterSpace1);
+						(calloutState->integerRegisterIndex = NumIntRegArgs);
+					}
+				}
+				if (stackPartSize1 > 0) {
+roundedSize1 = (((stackPartSize1 + 3) | 3) - 3);
+					if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) {
+						return FFIErrorCallFrameTooBig;
+					}
+					memcpy((calloutState->currentArg), (&((((char *) (((void *) ptrAddress))))[availableRegisterSpace1])), stackPartSize1);
+					(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1);
+				}
+				return 0;
+			}
+			if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) {
+				return FFIErrorStructSize;
+			}
+			ptrAddress = fetchPointerofObject(0, valueOop);
+			if (isInMemory(ptrAddress)) {
+				return FFIErrorInvalidPointer;
+			}
+			/* begin ffiPushPointer:in: */
+			if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+				((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = ptrAddress;
+				(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				longAtput((calloutState->currentArg), ptrAddress);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		return FFIErrorBadArg;
+	}
+	if (((calloutState->ffiArgHeader)) & FFIFlagPointer) {
+
+		/* no integers (or characters) for pointers please */
+
+if (isImmediate(oop)) {
+			return FFIErrorIntAsPointer;
+		}
+		if (oop == nilOop) {
+/* begin ffiPushPointer:in: */
+			if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+				((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = null;
+				(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				longAtput((calloutState->currentArg), null);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) {
+
+			/* e.g., ExternalData */
+
+if (isStruct) {
+/* begin ffiAtomicStructByReference:Class:in: */
+				if (!(oopClass == (classExternalData()))) {
+					return FFIErrorCoercionFailed;
+				}
+				/* begin atomicTypeOf: */
+				typeSpec = (calloutState->ffiArgHeader);
+				atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+				if (atomicType != FFITypeVoid) {
+/* begin ffiValidateExternalData:AtomicType: */
+					ptrType = fetchPointerofObject(1, oop);
+					if (!((isPointers(ptrType))
+						 && ((slotSizeOf(ptrType)) >= 2))) {
+						err = FFIErrorWrongType;
+						goto l3;
+					}
+					specOop = fetchPointerofObject(0, ptrType);
+					if (!((isWords(specOop))
+						 && ((slotSizeOf(specOop)) > 0))) {
+						err = FFIErrorWrongType;
+						goto l3;
+					}
+					spec = fetchPointerofObject(0, specOop);
+					if (!(spec & FFIFlagAtomic)) {
+						err = FFIErrorWrongType;
+						goto l3;
+					}
+					specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+					if (specType != atomicType) {
+
+						/* Allow for signed/unsigned conversion but nothing else.
+						   See FFIConstants class>>#initializeTypeConstants */
+
+						if (!((atomicType >= FFITypeUnsignedByte)
+							 && ((atomicType <= FFITypeSignedChar)
+							 && ((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))))) {
+							err = FFIErrorCoercionFailed;
+							goto l3;
+						}
+					}
+					err = 0;
+				l3:	/* end ffiValidateExternalData:AtomicType: */;
+					if (err != 0) {
+return err;
+					}
+				}
+				valueOop1 = fetchPointerofObject(0, oop);
+				return ffiPushPointerContentsOfin(valueOop1, calloutState);
+			}
+			else {
+/* begin ffiAtomicArgByReference:Class:in: */
+				/* begin atomicTypeOf: */
+				typeSpec2 = (calloutState->ffiArgHeader);
+				atomicType2 = ((usqInt) (typeSpec2 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+				if (atomicType2 == FFITypeBool) {
+
+					/* No bools on input */
+
+return FFIErrorCoercionFailed;
+				}
+				isAlien = ((isString = includesBehaviorThatOf(oopClass, classString()))
+					? 0
+					: includesBehaviorThatOf(oopClass, classAlien()));
+				if ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+
+					/* string value (char*) */
+					/* note: the only types allowed for passing into char* types are
+					   ByteArray, String, Symbol, Alien and *no* other byte indexed objects
+					   (e.g., CompiledMethod, LargeInteger). We only check for strings
+					   here and fall through to the byte* check otherwise. */
+
+					if (isString) {
+
+						/* String/Symbol */
+						/* Strings must be allocated by the ffi support code */
+
+/* begin ffiPushString:OfLength:in: */
+						pointer = firstIndexableField(oop);
+						length = byteSizeOf(oop);
+						if (((calloutState->stringArgIndex)) >= MaxNumArgs) {
+							return -PrimErrBadNumArgs;
+						}
+						copy = malloc(length + 1);
+						if (copy == null) {
+return -PrimErrNoCMemory;
+						}
+						memcpy(copy, pointer, length);
+						copy[length] = 0;
+						((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
+						(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
+						/* begin ffiPushPointer:in: */
+						if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+							((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = copy;
+							(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+						}
+						else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+								return FFIErrorCallFrameTooBig;
+							}
+							longAtput((calloutState->currentArg), copy);
+							(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+						}
+						return 0;
+					}
+					atomicType2 = FFITypeUnsignedByte;
+				}
+				
+#        if COGMTVM
+
+				/* Since all the following pass the address of the first indexable field we need to fail
+				   the call if it is threaded and the object is young, since it may move during the call. */
+
+				if ((((calloutState->callFlags)) & FFICallFlagThreaded)
+				 && (((!isAlien)
+ || (isDirectAlien(oop)))
+				 && (isYoung(oop)))) {
+					return -PrimErrObjectMayMove;
+				}
+
+#        endif /* COGMTVM */
+
+				if ((atomicType2 == FFITypeVoid)
+				 || ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
+
+					/* byte* -- see comment on string above */
+
+if (isString
+					 || (oopClass == (classByteArray()))) {
+
+						/* String/Symbol/ByteArray */
+
+/* begin ffiPushPointer:in: */
+						pointer1 = firstIndexableField(oop);
+						if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+							((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = pointer1;
+							(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+						}
+						else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+								return FFIErrorCallFrameTooBig;
+							}
+							longAtput((calloutState->currentArg), pointer1);
+							(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+						}
+						return 0;
+					}
+					if (isAlien) {
+/* begin ffiPushPointer:in: */
+						pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+							? (oop + BaseHeaderSize) + BytesPerOop
+							: longAt((oop + BaseHeaderSize) + BytesPerOop)));
+						if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+							((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = pointer2;
+							(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+						}
+						else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+								return FFIErrorCallFrameTooBig;
+							}
+							longAtput((calloutState->currentArg), pointer2);
+							(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+						}
+						return 0;
+					}
+					if (!(atomicType2 == FFITypeVoid)) {
+						return FFIErrorCoercionFailed;
+					}
+				}
+				if ((atomicType2 <= FFITypeSignedInt)
+				 || (atomicType2 == FFITypeSingleFloat)) {
+
+					/* require a word subclass to work */
+
+if (isWords(oop)) {
+						/* begin ffiPushPointer:in: */
+						pointer3 = firstIndexableField(oop);
+						if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+							((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = pointer3;
+							(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+						}
+						else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+								return FFIErrorCallFrameTooBig;
+							}
+							longAtput((calloutState->currentArg), pointer3);
+							(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+						}
+						return 0;
+					}
+				}
+				return FFIErrorCoercionFailed;
+			}
+		}
+		if (!isStruct) {
+return FFIErrorCoercionFailed;
+		}
+		return ffiPushPointerContentsOfin(valueOop, calloutState);
+	}
+	if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) {
+
+		/* argument is atomic value */
+
+/* begin ffiArgByValue:in: */
+		/* begin atomicTypeOf: */
+		typeSpec1 = (calloutState->ffiArgHeader);
+		atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+		if ((atomicType1 < 0)
+		 || (atomicType1 > FFITypeDoubleFloat)) {
+return FFIErrorBadAtomicType;
+		}
+		if (atomicType1 < FFITypeSingleFloat) {
+
+			/* integer types */
+
+if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) {
+
+				/* ffi support code must coerce longlong */
+
+intValue = valueOop;
+			}
+			else {
+/* begin ffiIntegerValueOf: */
+				if (isIntegerObject(valueOop)) {
+					intValue = integerValueOf(valueOop);
+					goto l1;
+				}
+				if (valueOop == (nilObject())) {
+					intValue = 0;
+					goto l1;
+				}
+				if (valueOop == (falseObject())) {
+					intValue = 0;
+					goto l1;
+				}
+				if (valueOop == (trueObject())) {
+					intValue = 1;
+					goto l1;
+				}
+				oopClass2 = fetchClassOf(valueOop);
+				if (oopClass2 == (classFloat())) {
+					intValue = ((sqInt)(floatValueOf(valueOop)));
+					goto l1;
+				}
+				if (oopClass2 == (classCharacter())) {
+					intValue = characterValueOf(valueOop);
+					goto l1;
+				}
+				if (oopClass2 == (classLargePositiveInteger())) {
+					intValue = positive32BitValueOf(valueOop);
+					goto l1;
+				}
+				intValue = signedMachineIntegerValueOf(valueOop);
+			l1:	/* end ffiIntegerValueOf: */;
+			}
+			if (failed()) {
+				return FFIErrorCoercionFailed;
+			}
+			
+			switch (atomicType1) {
+			case 0:
+				return FFIErrorAttemptToPassVoid;
+			case 1:
+				return ffiPushUnsignedIntin(intValue, calloutState);
+			case 2:
+				return ffiPushUnsignedBytein(intValue, calloutState);
+			case 3:
+				return ffiPushSignedBytein(intValue, calloutState);
+			case 4:
+				return ffiPushUnsignedShortin(intValue, calloutState);
+			case 5:
+				return ffiPushSignedShortin(intValue, calloutState);
+			case 6:
+				return ffiPushUnsignedIntin(intValue, calloutState);
+			case 7:
+				return ffiPushSignedIntin(intValue, calloutState);
+			case 8:
+				return ffiPushUnsignedLongLongOopin(intValue, calloutState);
+			case 9:
+				return ffiPushSignedLongLongOopin(intValue, calloutState);
+			case 10:
+				return ffiPushUnsignedCharin(intValue, calloutState);
+			case 11:
+				return ffiPushSignedCharin(intValue, calloutState);
+
+			default:
+				error("Case not found");
+				return -1;
+			}
+		}
+		/* begin ffiFloatValueOf: */
+		oopClass1 = fetchClassOf(valueOop);
+		if (oopClass1 == (classFloat())) {
+			floatValue = floatValueOf(valueOop);
+			goto l2;
+		}
+		floatValue = ((double) (ffiIntegerValueOf(valueOop)) );
+	l2:	/* end ffiFloatValueOf: */;
+		if (failed()) {
+			return FFIErrorCoercionFailed;
+		}
+		if (atomicType1 == FFITypeSingleFloat) {
+/* begin ffiPushSingleFloat:in: */
+			if (((calloutState->floatRegisterIndex)) < NumFloatRegArgs) {
+				if (((calloutState->backfillFloatRegisterIndex)) > 0) {
+					((calloutState->floatRegisters))[(calloutState->backfillFloatRegisterIndex)] = floatValue;
+					(calloutState->backfillFloatRegisterIndex = 0);
+				}
+				else {
+((calloutState->floatRegisters))[(calloutState->floatRegisterIndex)] = floatValue;
+					(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 1);
+				}
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		else {
+/* begin ffiPushDoubleFloat:in: */
+			if (((calloutState->floatRegisterIndex)) < (NumFloatRegArgs - 1)) {
+				if ((((calloutState->floatRegisterIndex)) & 1) == 1) {
+					(calloutState->backfillFloatRegisterIndex = (calloutState->floatRegisterIndex));
+					(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 1);
+				}
+				(((double*) ((&(((calloutState->floatRegisters))[(calloutState->floatRegisterIndex)])))))[0] = floatValue;
+				(calloutState->floatRegisterIndex = ((calloutState->floatRegisterIndex)) + 2);
+			}
+			else {
+if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				(calloutState->floatRegisterIndex = NumFloatRegArgs);
+				storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 8);
+			}
+			return 0;
+		}
+	}
+	return FFIErrorWrongType;
+}
+
+
+/*	Support for generic callout. Prepare a pointer reference to an atomic type
+	for callout.
+	Note: for type 'void*' we allow ByteArray/String/Symbol,
+	wordVariableSubclass or Alien.
+ */
+
+static sqInt
+ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState)
+{
+    sqInt atomicType;
+    char *copy;
+    sqInt isAlien;
+    sqInt isString;
+    sqInt length;
+    char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
+    sqInt typeSpec;
+
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiArgHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if (atomicType == FFITypeBool) {
+
+		/* No bools on input */
+
+return FFIErrorCoercionFailed;
+	}
+	isAlien = ((isString = includesBehaviorThatOf(oopClass, classString()))
+		? 0
+		: includesBehaviorThatOf(oopClass, classAlien()));
+	if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+
+		/* string value (char*) */
+		/* note: the only types allowed for passing into char* types are
+		   ByteArray, String, Symbol, Alien and *no* other byte indexed objects
+		   (e.g., CompiledMethod, LargeInteger). We only check for strings
+		   here and fall through to the byte* check otherwise. */
+
+		if (isString) {
+
+			/* String/Symbol */
+			/* Strings must be allocated by the ffi support code */
+
+/* begin ffiPushString:OfLength:in: */
+			pointer = firstIndexableField(oop);
+			length = byteSizeOf(oop);
+			if (((calloutState->stringArgIndex)) >= MaxNumArgs) {
+				return -PrimErrBadNumArgs;
+			}
+			copy = malloc(length + 1);
+			if (copy == null) {
+return -PrimErrNoCMemory;
+			}
+			memcpy(copy, pointer, length);
+			copy[length] = 0;
+			((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
+			(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
+			/* begin ffiPushPointer:in: */
+			if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+				((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = copy;
+				(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				longAtput((calloutState->currentArg), copy);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		atomicType = FFITypeUnsignedByte;
+	}
+	
+#  if COGMTVM
+
+	/* Since all the following pass the address of the first indexable field we need to fail
+	   the call if it is threaded and the object is young, since it may move during the call. */
+
+	if ((((calloutState->callFlags)) & FFICallFlagThreaded)
+	 && (((!isAlien)
+ || (isDirectAlien(oop)))
+	 && (isYoung(oop)))) {
+		return -PrimErrObjectMayMove;
+	}
+
+#  endif /* COGMTVM */
+
+	if ((atomicType == FFITypeVoid)
+	 || ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
+
+		/* byte* -- see comment on string above */
+
+if (isString
+		 || (oopClass == (classByteArray()))) {
+
+			/* String/Symbol/ByteArray */
+
+/* begin ffiPushPointer:in: */
+			pointer1 = firstIndexableField(oop);
+			if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+				((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = pointer1;
+				(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				longAtput((calloutState->currentArg), pointer1);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		if (isAlien) {
+/* begin ffiPushPointer:in: */
+			pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+				? (oop + BaseHeaderSize) + BytesPerOop
+				: longAt((oop + BaseHeaderSize) + BytesPerOop)));
+			if (((calloutState->integerRegisterIndex)) < NumIntRegArgs) {
+				((calloutState->integerRegisters))[(calloutState->integerRegisterIndex)] = pointer2;
+				(calloutState->integerRegisterIndex = ((calloutState->integerRegisterIndex)) + 1);
+			}
+			else {
+if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				longAtput((calloutState->currentArg), pointer2);
+				(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+			}
+			return 0;
+		}
+		if (!(atomicType == FFITypeVoid)) {
+			return FFIErrorCoercionFailed;
+		}
+	}
+	if ((atomicType <= FFITypeSignedInt)

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list