[Vm-dev] [commit][3443]
Provide functional verisons of the Alien plugin for 64-bit unix (
Windows will
commits at squeakvm.org
commits at squeakvm.org
Wed Sep 23 18:09:54 UTC 2015
Revision: 3443
Author: eliot
Date: 2015-09-23 11:09:52 -0700 (Wed, 23 Sep 2015)
Log Message:
-----------
Provide functional verisons of the Alien plugin for 64-bit unix (Windows will
take a little more work).
Modified Paths:
--------------
trunk/platforms/Cross/plugins/IA32ABI/dax64business.h
trunk/platforms/Cross/plugins/IA32ABI/x64ia32abicc.c
Property Changed:
----------------
trunk/platforms/Cross/plugins/sqPluginsSCCSVersion.h
Modified: trunk/platforms/Cross/plugins/IA32ABI/dax64business.h
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/dax64business.h 2015-09-21 17:49:53 UTC (rev 3442)
+++ trunk/platforms/Cross/plugins/IA32ABI/dax64business.h 2015-09-23 18:09:52 UTC (rev 3443)
@@ -1,145 +1,194 @@
/*
* dax64business.h
*
- * Written by Eliot Miranda 12/14
+ * Written by Eliot Miranda 12/14, Ryan Macnak 9/15
*
* Body of the various callIA32XXXReturn functions.
* Call a foreign function according to x64-ish ABI rules.
* N.B. In Cog Stack and Cogit VMs numArgs is negative to access args from
* the downward-growing stack.
*/
- long i, size;
- sqInt funcAlien, resultMaybeAlien;
- char *argvec;
- char *argstart;
-#if STACKVM /* Need to access args downwards from first arg */
- if (numArgs < 0)
- for (i = size = 0; --i >= numArgs;) {
- sqInt arg = argVector[i+1];
- if (objIsAlien(arg) && sizeField(arg))
- size += moduloPOT(sizeof(long),abs(sizeField(arg)));
- else if (interpreterProxy->isFloatObject(arg))
- size += sizeof(double);
- else /* assume an integer or pointer. check below. */
- size += sizeof(long);
+ long i;
+ long size;
+ long nextReg;
+ long nextDReg;
+ long regs[NUM_REG_ARGS];
+ double dregs[NUM_DREG_ARGS];
+ sqInt funcAlien;
+ sqInt resultMaybeAlien;
+ long argvec;
+ long argstart;
+
+ assert(sizeof(long) == sizeof(void*)); /* Will need to fix for Windows. */
+
+ if (numArgs < 0) {
+ /* Stack or Cog VM. Need to access args downwards from first arg. */
+ for (i = size = 0; --i >= numArgs;) {
+ sqInt arg = argVector[i + 1];
+ if (objIsAlien(arg) && (sizeField(arg) != 0))
+ /* Direct or indirect Alien. */
+ size += RoundUpPowerOfTwo(abs(sizeField(arg)), 8);
+ else if (interpreterProxy->isFloatObject(arg))
+ size += sizeof(double);
+ else
+ /* Assume an integer or pointer Alien. Check below. */
+ size += sizeof(long);
+ }
}
- else
-#endif /* STACKVM */
- for (i = numArgs, size = 0; --i >= 0;) {
- sqInt arg = argVector[i];
- if (objIsAlien(arg) && sizeField(arg))
- size += moduloPOT(sizeof(long),abs(sizeField(arg)));
- else if (interpreterProxy->isFloatObject(arg))
- size += sizeof(double);
- else /* assume an integer or pointer. check below. */
- size += sizeof(long);
+ else {
+ /* Context Interpreter or array version of callout primitive. */
+ for (i = numArgs, size = 0; --i >= 0;) {
+ sqInt arg = argVector[i];
+ if (objIsAlien(arg) && (sizeField(arg) != 0))
+ /* Direct or indirect Alien. */
+ size += RoundUpPowerOfTwo(abs(sizeField(arg)), 8);
+ else if (interpreterProxy->isFloatObject(arg))
+ size += sizeof(double);
+ else
+ /* Assume an integer or pointer Alien. Check below. */
+ size += sizeof(long);
+ }
}
- /* At point of call stack must be aligned to STACK_ALIGN_BYTES. So alloca
- * at least enough for this plus the argvector, and start writing argvector
- * at aligned point. Then just prior to call cut-back stack to aligned.
- */
- argvec = alloca(STACK_ALIGN_BYTES + moduloPOT(STACK_ALIGN_BYTES,size));
- argvec = alignModuloPOT(STACK_ALIGN_BYTES, argvec);
- argstart = argvec;
+ size = RoundUpPowerOfTwo(size, STACK_ALIGN_BYTES);
-#if STACKVM /* Need to access args downwards from first arg */
- if (numArgs < 0)
- for (i = size = 0; --i >= numArgs;) {
- sqInt arg = argVector[i+1];
- if (isSmallInt(arg)) {
- *(long *)argvec = intVal(arg);
- argvec += sizeof(long);
- }
- else if (objIsAlien(arg)) {
- long argByteSize;
+ argstart = argvec = (long)alloca(size);
- if (!(size = sizeField(arg)))
- size = argByteSize = sizeof(void *);
- else
- argByteSize = abs(size);
- memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
- argvec += moduloPOT(sizeof(long), argByteSize);
- }
- else if (objIsUnsafeAlien(arg)) {
- sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
- void *v = interpreterProxy->firstIndexableField(bitsObj);
- *(void **)argvec = v;
- argvec += sizeof(long);
- }
- else if (interpreterProxy->isFloatObject(arg)) {
- double d = interpreterProxy->floatValueOf(arg);
- *(double *)argvec = d;
- argvec += sizeof(double);
- }
- else {
- long v = interpreterProxy->signed32BitValueOf(arg);
- if (interpreterProxy->failed()) {
- interpreterProxy->primitiveFailFor(0);
- v = interpreterProxy->positive32BitValueOf(arg);
- if (interpreterProxy->failed())
- return PrimErrBadArgument;
+ nextReg = 0;
+ nextDReg = 0;
+
+#define MaybePassAsRegArg(expr) \
+ if (nextReg < NUM_REG_ARGS) \
+ regs[nextReg++] = expr; \
+ else { \
+ *(long*)argvec = expr; \
+ argvec += sizeof(long); \
+ }
+
+#define MaybePassAsDRegArg(expr) \
+ if (nextDReg < NUM_DREG_ARGS) \
+ dregs[nextDReg++] = expr; \
+ else { \
+ argvec = RoundUpPowerOfTwo(argvec, 8); \
+ *(double*) argvec = expr; \
+ argvec += sizeof(double); \
+ }
+
+ if (numArgs < 0) {
+ /* Stack or Cog VM. Need to access args downwards from first arg. */
+ for (i = size = 0; --i >= numArgs;) {
+ sqInt arg = argVector[i+1];
+ if (isSmallInt(arg)) {
+ MaybePassAsRegArg(intVal(arg))
}
- *(long *)argvec = v;
- argvec += sizeof(long);
+ else if (objIsAlien(arg)) {
+ long argByteSize;
+ if ((size = sizeField(arg)) == 0) /* Pointer Alien. */
+ size = argByteSize = sizeof(void *);
+ else /* Direct or indirect Alien. */
+ argByteSize = abs(size);
+ if ((argByteSize <= sizeof(long)) && (nextReg < NUM_REG_ARGS)) {
+ regs[nextReg++] = *(long*)startOfDataWithSize(arg, size);
+ }
+ else {
+ memcpy((void*)argvec, startOfDataWithSize(arg, size), argByteSize);
+ argvec += RoundUpPowerOfTwo(argByteSize, 8);
+ }
+ }
+ else if (objIsUnsafeAlien(arg)) {
+ sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
+ long v = (long)interpreterProxy->firstIndexableField(bitsObj);
+ MaybePassAsRegArg(v)
+ }
+ else if (interpreterProxy->isFloatObject(arg)) {
+ double d = interpreterProxy->floatValueOf(arg);
+ MaybePassAsDRegArg(d)
+ }
+ else {
+ long v = interpreterProxy->signed64BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor(0);
+ v = interpreterProxy->positive64BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ return PrimErrBadArgument;
+ }
+ }
+ MaybePassAsDRegArg(v)
+ }
}
}
- else
-#endif /* STACKVM */
- for (i = 0; i < numArgs; i++) {
- sqInt arg = argVector[i];
- if (isSmallInt(arg)) {
- *(long *)argvec = intVal(arg);
- argvec += sizeof(long);
- }
- else if (objIsAlien(arg)) {
- long argByteSize;
-
- if (!(size = sizeField(arg)))
- size = argByteSize = sizeof(void *);
- else
- argByteSize = abs(size);
- memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
- argvec += moduloPOT(sizeof(long), argByteSize);
- }
- else if (objIsUnsafeAlien(arg)) {
- sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
- void *v = interpreterProxy->firstIndexableField(bitsObj);
- *(void **)argvec = v;
- argvec += sizeof(long);
- }
- else if (interpreterProxy->isFloatObject(arg)) {
- double d = interpreterProxy->floatValueOf(arg);
- *(double *)argvec = d;
- argvec += sizeof(double);
- }
- else {
- long v = interpreterProxy->signed32BitValueOf(arg);
- if (interpreterProxy->failed()) {
- interpreterProxy->primitiveFailFor(0);
- v = interpreterProxy->positive32BitValueOf(arg);
- if (interpreterProxy->failed())
- return PrimErrBadArgument;
+ else {
+ /* Context Interpreter or array version of callout primitive. */
+ for (i = 0; i < numArgs; i++) {
+ sqInt arg = argVector[i];
+ if (isSmallInt(arg))
+ MaybePassAsDRegArg(intVal(arg))
+ else if (objIsAlien(arg)) {
+ long argByteSize;
+ if ((size = sizeField(arg)) == 0) /* Pointer Alien. */
+ size = argByteSize = sizeof(void *);
+ else /* Direct or indirect Alien. */
+ argByteSize = abs(size);
+ if ((argByteSize <= sizeof(long)) && (nextReg < NUM_REG_ARGS)) {
+ regs[nextReg++] = *(long*)startOfDataWithSize(arg, size);
+ }
+ else {
+ memcpy((void*)argvec, startOfDataWithSize(arg, size), argByteSize);
+ argvec += RoundUpPowerOfTwo(argByteSize, 8);
+ }
}
- *(long *)argvec = v;
- argvec += sizeof(long);
+ else if (objIsUnsafeAlien(arg)) {
+ sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
+ long v = (long)interpreterProxy->firstIndexableField(bitsObj);
+ MaybePassAsRegArg(v)
+ }
+ else if (interpreterProxy->isFloatObject(arg)) {
+ double d = interpreterProxy->floatValueOf(arg);
+ MaybePassAsDRegArg(d)
+ }
+ else {
+ long v = interpreterProxy->signed64BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor(0);
+ v = interpreterProxy->positive64BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ return PrimErrBadArgument;
+ }
+ }
+ MaybePassAsRegArg(v)
+ }
}
}
funcAlien = interpreterProxy->stackValue(funcOffset);
- f = *(void **)startOfParameterData(funcAlien);
- /* cut stack back to start of aligned args */
- setsp(argstart);
- r = f();
- /* post call need to refresh stack pointer in case of call-back and GC. */
+ f = *(void**)startOfParameterData(funcAlien);
+
+ /* Note that this call a) passes the integer reg args in regs in the core
+ * integer registers, and b) passes the floating point args in dregs in the
+ * floating-point co-processor registers. Neat.
+ *
+ * But this trick WILL NOT WORK on the Windows ABI. The first integer
+ * argument allocates both the first integer register and the first float
+ * register, and vice versa. This means the call below would pass all the
+ * double arguments on the stack, which is not correct if there are double
+ * arguments among the first four arguments. Instead we will have to make
+ * two separate calls, the first a call of a dummy function to load the
+ * double arguments (if any) and the second to make the actual call.
+ */
+ r = f(regs[0], regs[1], regs[2], regs[3], regs[4], regs[5],
+ dregs[0], dregs[1], dregs[2], dregs[3],
+ dregs[4], dregs[5], dregs[6], dregs[7]);
+
+ /* Post call need to refresh stack pointer in case of call-back and GC. */
resultMaybeAlien = interpreterProxy->stackValue(resultOffset);
if (objIsAlien(resultMaybeAlien)) {
- if (!(size = sizeField(resultMaybeAlien)))
- size = sizeof(void *);
- memcpy(startOfDataWithSize(resultMaybeAlien,size),
- &r,
- min((unsigned)abs(size), sizeof(r)));
+ size = sizeField(resultMaybeAlien);
+ if (size == 0) /* Pointer Alien. */
+ size = sizeof(long);
+ memcpy(startOfDataWithSize(resultMaybeAlien, size),
+ &r,
+ min((unsigned)abs(size), sizeof(r)));
}
return PrimNoErr;
Modified: trunk/platforms/Cross/plugins/IA32ABI/x64ia32abicc.c
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/x64ia32abicc.c 2015-09-21 17:49:53 UTC (rev 3442)
+++ trunk/platforms/Cross/plugins/IA32ABI/x64ia32abicc.c 2015-09-23 18:09:52 UTC (rev 3443)
@@ -2,7 +2,7 @@
* x86ia32abicc.c
*
* Support for Call-outs and Call-backs from the Plugin on x86_64.
- * Written by Eliot Miranda 12/14
+ * Written by Eliot Miranda 12/14, Ryan Macnak 9/15
*
* Based on
* System V Application Binary Interface
@@ -13,6 +13,7 @@
#if defined(_MSC_VER) || defined(__MINGW32__)
# include "windows.h" /* for GetSystemInfo & VirtualAlloc */
+# error Windows doesn't use the SystemV ABI
#elif __APPLE__ && __MACH__
# include <sys/mman.h> /* for mprotect */
# if OBJC_DEBUG /* define this to get debug info for struct objc_class et al */
@@ -45,6 +46,9 @@
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
+#define NUM_REG_ARGS 6
+#define NUM_DREG_ARGS 8
+
#ifdef SQUEAK_BUILTIN_PLUGIN
extern
#endif
@@ -54,15 +58,18 @@
# define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp))
# define getsp() ({ void *sp; asm volatile ("movq %%rsp,%0" : "=r"(sp) : ); sp;})
#endif
-#define STACK_ALIGN_BYTES 32 /* x64ABI 3.2.2 */
+#define STACK_ALIGN_BYTES 32 /* 32 if a 256-bit argument is passed; 16 otherwise */
#if !defined(setsp)
# define setsp(ignored) 0
#endif
-#define moduloPOT(m,v) (((v)+(m)-1) & ~((m)-1))
-#define alignModuloPOT(m,v) ((void *)moduloPOT(m,(unsigned long)(v)))
+#define RoundUpPowerOfTwo(value, modulus) \
+ (((value) + (modulus) - 1) & ~((modulus) - 1))
+#define IsAlignedPowerOfTwo(value, modulus) \
+ (((value) & ((modulus) - 1)) == 0)
+
#define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()))
#define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien()))
@@ -84,9 +91,11 @@
* Call a foreign function that answers an integral result in %rax (and
* possibly %rdx?) according to x64-ish ABI rules.
*/
-sqInt
-callIA32IntegralReturn(SIGNATURE) {
-long (*f)(), r;
+sqInt callIA32IntegralReturn(SIGNATURE) {
+ long (*f)(long rdi, long rsi, long rdx, long rcx, long r8, long r9,
+ double xmm0, double xmm1, double xmm2, double xmm3,
+ double xmm4, double xmm5, double xmm6, double xmm7);
+ long r;
#include "dax64business.h"
}
@@ -94,8 +103,11 @@
* Call a foreign function that answers a single-precision floating-point
* result in %xmm0 according to x64-ish ABI rules.
*/
-sqInt
-callIA32FloatReturn(SIGNATURE) { float (*f)(), r;
+sqInt callIA32FloatReturn(SIGNATURE) {
+ float (*f)(long rdi, long rsi, long rdx, long rcx, long r8, long r9,
+ double xmm0, double xmm1, double xmm2, double xmm3,
+ double xmm4, double xmm5, double xmm6, double xmm7);
+ float r;
#include "dax64business.h"
}
@@ -103,8 +115,11 @@
* Call a foreign function that answers a double-precision floating-point
* result in %xmm0 according to x64-ish ABI rules.
*/
-sqInt
-callIA32DoubleReturn(SIGNATURE) { double (*f)(), r;
+sqInt callIA32DoubleReturn(SIGNATURE) {
+ double (*f)(long rdi, long rsi, long rdx, long rcx, long r8, long r9,
+ double xmm0, double xmm1, double xmm2, double xmm3,
+ double xmm4, double xmm5, double xmm6, double xmm7);
+ double r;
#include "dax64business.h"
}
Property changes on: trunk/platforms/Cross/plugins/sqPluginsSCCSVersion.h
___________________________________________________________________
Modified: checkindate
- Mon Sep 21 10:49:22 PDT 2015
+ Wed Sep 23 11:09:06 PDT 2015
More information about the Vm-dev
mailing list