private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize) { // We need to add 8 bytes to the total size, as the call to this // function already pushed 8 bytes (the return address). int intMask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters; int vecMask = CallingConvention.GetVecCalleeSavedRegisters() & allocResult.VecUsedRegisters; xmmSaveRegionSize = BitUtils.CountBits(vecMask) * 16; int calleeSaveRegionSize = BitUtils.CountBits(intMask) * 8 + xmmSaveRegionSize + 8; int argsCount = maxCallArgs; if (argsCount < 0) { // When the function has no calls, argsCount is -1. // In this case, we don't need to allocate the shadow space. argsCount = 0; } else if (argsCount < 4) { // The ABI mandates that the space for at least 4 arguments // is reserved on the stack (this is called shadow space). argsCount = 4; } int frameSize = calleeSaveRegionSize + allocResult.SpillRegionSize; // TODO: Instead of always multiplying by 16 (the largest possible size of a variable, // since a V128 has 16 bytes), we should calculate the exact size consumed by the // arguments passed to the called functions on the stack. int callArgsAndFrameSize = frameSize + argsCount * 16; // Ensure that the Stack Pointer will be aligned to 16 bytes. callArgsAndFrameSize = (callArgsAndFrameSize + 0xf) & ~0xf; return(callArgsAndFrameSize - frameSize); }