/*
* dabusiness.h
*
* Written by Eliot Miranda 11/07.
* Updated 5/2011 to cope with Cog stack direction.
*
* Body of the various callIA32XXXReturn functions.
* Call a foreign function according to IA32-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;
#if STACK_ALIGN_BYTES
char *argstart;
#endif
#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);
}
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);
}
#if STACK_ALIGN_BYTES
/* 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;
#else
argvec = alloca(moduloPOT(sizeof(long),size));
# if defined(__MINGW32__) && (__GNUC__ >= 3)
/*
* cygwin & MinGW's 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.
*/
argvec = getsp();
# endif
#endif
#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;
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;
}
*(long *)argvec = v;
argvec += sizeof(long);
}
}
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;
}
*(long *)argvec = v;
argvec += sizeof(long);
}
}
funcAlien = interpreterProxy->stackValue(funcOffset);
f = *(void **)startOfParameterData(funcAlien);
#if STACK_ALIGN_BYTES
/* cut stack back to start of aligned args */
setsp(argstart);
#endif
r = f();
/* 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)));
}
return PrimNoErr;
|