[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