Skip to content

Commit

Permalink
Increment stackSlotCount for structs correctly in FFI Upcall on z/OS
Browse files Browse the repository at this point in the history
This commit fixes a bug in FFI Upcall on z/OS where the counter for
stack slots in memory is not always increased when iterating through
arguments. Specifically, the counter was not being incremented when
structs were present in the argument list. It will now be incremented
correctly for every argument.

Signed-off-by: Dhruv Chopra <[email protected]>
  • Loading branch information
dchopra001 committed Oct 9, 2024
1 parent 1153568 commit 1cd7257
Showing 1 changed file with 15 additions and 25 deletions.
40 changes: 15 additions & 25 deletions runtime/vm/mz64/UpcallThunkGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ createUpcallThunk(J9UpcallMetaData *metaData)
}
for (I_32 i = 0; i < lastSigIdx; i++) {
U_32 argSizeInBytes = sigArray[i].sizeInByte;
int totalStackSlotsReq = ((argSizeInBytes - 1) / 8) + 1;
switch(sigArray[i].type) {
case J9_FFI_UPCALL_SIG_TYPE_CHAR: /* Fall through */
case J9_FFI_UPCALL_SIG_TYPE_SHORT: /* Fall through */
Expand Down Expand Up @@ -328,33 +329,28 @@ createUpcallThunk(J9UpcallMetaData *metaData)
if (fprIndex <= maxFPRIndex - 2) {
thunkMem += STEY(thunkMem, fprIndex, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8));
thunkMem += STEY(thunkMem, fprIndex + 2, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8) + 4);
currStackSlotIndex += 1;
fprIndex += 4;
if (i < 3) {
gprIndex += 2;
}
}
else if (fprIndex <= maxFPRIndex) {
thunkMem += STEY(thunkMem, fprIndex, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8));
currStackSlotIndex += 1;
fprIndex += 2;
}
}
else { // All other pure float structs are passed in GPR (if there's space)
if (gprIndex <= maxGPRIndex) {
int totalStackSlotsReq = ((argSizeInBytes - 1) / 8) + 1;
int numGPRsAvailable = maxGPRIndex - gprIndex + 1;
int tempArgIndex = currStackSlotIndex;
for (int i = 1; i <= std::min(numGPRsAvailable, totalStackSlotsReq); i++) {
thunkMem += STG(thunkMem, gprIndex, 0, R4, argAreaOffsetFromSP + (tempArgIndex * 8));
tempArgIndex += 1;
gprIndex++;
}

// increase currStackSlotIndex by the number of slots this struct takes in memory
currStackSlotIndex += totalStackSlotsReq;
}
}
currStackSlotIndex += totalStackSlotsReq;
break;
case J9_FFI_UPCALL_SIG_TYPE_STRUCT_AGGREGATE_ALL_DP:
if (argSizeInBytes == 2 * sizeof(double)) {
Expand All @@ -364,34 +360,30 @@ createUpcallThunk(J9UpcallMetaData *metaData)
// argument area.
if (fprIndex <= maxFPRIndex - 2) {
thunkMem += STDY(thunkMem, fprIndex, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8));
currStackSlotIndex += 1;
thunkMem += STDY(thunkMem, fprIndex + 2, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8));
currStackSlotIndex += 1;
thunkMem += STDY(thunkMem, fprIndex + 2, 0, R4, argAreaOffsetFromSP + ((currStackSlotIndex + 1) * 8));
fprIndex += 4;
if (i < 3) {
gprIndex += 2;
}
}
else if (fprIndex <= maxFPRIndex) {
thunkMem += STDY(thunkMem, fprIndex, 0, R4, argAreaOffsetFromSP + (currStackSlotIndex * 8));
currStackSlotIndex += 1;
fprIndex += 2;
}
}
else { // This is for all other pure double structs (they will be passed in GPRs if there's space)
if (gprIndex <= maxGPRIndex) {
int totalStackSlotsReq = argSizeInBytes / 8; // the size in bytes for a struct with only doubles will always be a multiple of 8.
int numGPRsAvailable = maxGPRIndex - gprIndex + 1;
int tempArgIndex = currStackSlotIndex;
for (int i = 1; i <= std::min(numGPRsAvailable, totalStackSlotsReq); i++) {
thunkMem += STG(thunkMem, gprIndex, 0, R4, argAreaOffsetFromSP + (tempArgIndex * 8));
tempArgIndex += 1;
gprIndex++;
else { // This is for all other pure double structs (they will be passed in GPRs if there's space)
if (gprIndex <= maxGPRIndex) {
int numGPRsAvailable = maxGPRIndex - gprIndex + 1;
int tempArgIndex = currStackSlotIndex;
for (int i = 1; i <= std::min(numGPRsAvailable, totalStackSlotsReq); i++) {
thunkMem += STG(thunkMem, gprIndex, 0, R4, argAreaOffsetFromSP + (tempArgIndex * 8));
tempArgIndex += 1;
gprIndex++;
}
// increase currStackSlotIndex by the number of slots this struct takes in memory
}
// increase currStackSlotIndex by the number of slots this struct takes in memory
currStackSlotIndex += totalStackSlotsReq;
}
}
currStackSlotIndex += totalStackSlotsReq;
break;
case J9_FFI_UPCALL_SIG_TYPE_STRUCT_AGGREGATE_SP_DP:
case J9_FFI_UPCALL_SIG_TYPE_STRUCT_AGGREGATE_SP_SP_DP:
Expand All @@ -404,17 +396,15 @@ createUpcallThunk(J9UpcallMetaData *metaData)
case J9_FFI_UPCALL_SIG_TYPE_STRUCT_AGGREGATE_OTHER:
case J9_FFI_UPCALL_SIG_TYPE_STRUCT_AGGREGATE_MISC:
if (gprIndex <= maxGPRIndex) {
int totalStackSlotsReq = ((argSizeInBytes - 1) / 8) + 1;
int numGPRsAvailable = maxGPRIndex - gprIndex + 1;
int tempArgIndex = currStackSlotIndex;
for (int i = 1; i <= std::min(numGPRsAvailable, totalStackSlotsReq); i++) {
thunkMem += STG(thunkMem, gprIndex, 0, R4, argAreaOffsetFromSP + (tempArgIndex * 8));
tempArgIndex += 1;
gprIndex++;
}
// increase currStackSlotIndex by the number of slots this struct takes in memory
currStackSlotIndex += totalStackSlotsReq;
}
currStackSlotIndex += totalStackSlotsReq;
break;
default:
Assert_VM_unreachable();
Expand Down

0 comments on commit 1cd7257

Please sign in to comment.