ac2f8e5af8
Reviewed-by: mcimadamore
238 lines
6.3 KiB
C
238 lines
6.3 KiB
C
/*
|
|
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "shared.h"
|
|
|
|
struct S_FFFF { float p0; float p1; float p2; float p3; };
|
|
|
|
typedef void (*writeback_t)(int,void*);
|
|
|
|
typedef struct {
|
|
writeback_t writeback;
|
|
int* argids;
|
|
} call_info;
|
|
|
|
#define CASE(num, type) case num: { \
|
|
type x = va_arg(a_list, type); \
|
|
writeback(i, &x); \
|
|
} break;
|
|
|
|
enum NativeType {
|
|
T_INT,
|
|
T_DOUBLE,
|
|
T_POINTER,
|
|
T_S_I,
|
|
T_S_F,
|
|
T_S_D,
|
|
T_S_P,
|
|
T_S_II,
|
|
T_S_IF,
|
|
T_S_ID,
|
|
T_S_IP,
|
|
T_S_FI,
|
|
T_S_FF,
|
|
T_S_FD,
|
|
T_S_FP,
|
|
T_S_DI,
|
|
T_S_DF,
|
|
T_S_DD,
|
|
T_S_DP,
|
|
T_S_PI,
|
|
T_S_PF,
|
|
T_S_PD,
|
|
T_S_PP,
|
|
T_S_III,
|
|
T_S_IIF,
|
|
T_S_IID,
|
|
T_S_IIP,
|
|
T_S_IFI,
|
|
T_S_IFF,
|
|
T_S_IFD,
|
|
T_S_IFP,
|
|
T_S_IDI,
|
|
T_S_IDF,
|
|
T_S_IDD,
|
|
T_S_IDP,
|
|
T_S_IPI,
|
|
T_S_IPF,
|
|
T_S_IPD,
|
|
T_S_IPP,
|
|
T_S_FII,
|
|
T_S_FIF,
|
|
T_S_FID,
|
|
T_S_FIP,
|
|
T_S_FFI,
|
|
T_S_FFF,
|
|
T_S_FFD,
|
|
T_S_FFP,
|
|
T_S_FDI,
|
|
T_S_FDF,
|
|
T_S_FDD,
|
|
T_S_FDP,
|
|
T_S_FPI,
|
|
T_S_FPF,
|
|
T_S_FPD,
|
|
T_S_FPP,
|
|
T_S_DII,
|
|
T_S_DIF,
|
|
T_S_DID,
|
|
T_S_DIP,
|
|
T_S_DFI,
|
|
T_S_DFF,
|
|
T_S_DFD,
|
|
T_S_DFP,
|
|
T_S_DDI,
|
|
T_S_DDF,
|
|
T_S_DDD,
|
|
T_S_DDP,
|
|
T_S_DPI,
|
|
T_S_DPF,
|
|
T_S_DPD,
|
|
T_S_DPP,
|
|
T_S_PII,
|
|
T_S_PIF,
|
|
T_S_PID,
|
|
T_S_PIP,
|
|
T_S_PFI,
|
|
T_S_PFF,
|
|
T_S_PFD,
|
|
T_S_PFP,
|
|
T_S_PDI,
|
|
T_S_PDF,
|
|
T_S_PDD,
|
|
T_S_PDP,
|
|
T_S_PPI,
|
|
T_S_PPF,
|
|
T_S_PPD,
|
|
T_S_PPP,
|
|
T_S_FFFF,
|
|
};
|
|
|
|
// need to pass `num` separately as last argument preceding varargs according to spec (and for MSVC)
|
|
EXPORT void varargs(call_info* info, int num, ...) {
|
|
va_list a_list;
|
|
va_start(a_list, num);
|
|
writeback_t writeback = info->writeback;
|
|
|
|
for (int i = 0; i < num; i++) {
|
|
int id = info->argids[i];
|
|
switch (id) {
|
|
CASE(T_INT, int)
|
|
CASE(T_DOUBLE, double)
|
|
CASE(T_POINTER, void*)
|
|
CASE(T_S_I, struct S_I)
|
|
CASE(T_S_F, struct S_F)
|
|
CASE(T_S_D, struct S_D)
|
|
CASE(T_S_P, struct S_P)
|
|
CASE(T_S_II, struct S_II)
|
|
CASE(T_S_IF, struct S_IF)
|
|
CASE(T_S_ID, struct S_ID)
|
|
CASE(T_S_IP, struct S_IP)
|
|
CASE(T_S_FI, struct S_FI)
|
|
CASE(T_S_FF, struct S_FF)
|
|
CASE(T_S_FD, struct S_FD)
|
|
CASE(T_S_FP, struct S_FP)
|
|
CASE(T_S_DI, struct S_DI)
|
|
CASE(T_S_DF, struct S_DF)
|
|
CASE(T_S_DD, struct S_DD)
|
|
CASE(T_S_DP, struct S_DP)
|
|
CASE(T_S_PI, struct S_PI)
|
|
CASE(T_S_PF, struct S_PF)
|
|
CASE(T_S_PD, struct S_PD)
|
|
CASE(T_S_PP, struct S_PP)
|
|
CASE(T_S_III, struct S_III)
|
|
CASE(T_S_IIF, struct S_IIF)
|
|
CASE(T_S_IID, struct S_IID)
|
|
CASE(T_S_IIP, struct S_IIP)
|
|
CASE(T_S_IFI, struct S_IFI)
|
|
CASE(T_S_IFF, struct S_IFF)
|
|
CASE(T_S_IFD, struct S_IFD)
|
|
CASE(T_S_IFP, struct S_IFP)
|
|
CASE(T_S_IDI, struct S_IDI)
|
|
CASE(T_S_IDF, struct S_IDF)
|
|
CASE(T_S_IDD, struct S_IDD)
|
|
CASE(T_S_IDP, struct S_IDP)
|
|
CASE(T_S_IPI, struct S_IPI)
|
|
CASE(T_S_IPF, struct S_IPF)
|
|
CASE(T_S_IPD, struct S_IPD)
|
|
CASE(T_S_IPP, struct S_IPP)
|
|
CASE(T_S_FII, struct S_FII)
|
|
CASE(T_S_FIF, struct S_FIF)
|
|
CASE(T_S_FID, struct S_FID)
|
|
CASE(T_S_FIP, struct S_FIP)
|
|
CASE(T_S_FFI, struct S_FFI)
|
|
CASE(T_S_FFF, struct S_FFF)
|
|
CASE(T_S_FFD, struct S_FFD)
|
|
CASE(T_S_FFP, struct S_FFP)
|
|
CASE(T_S_FDI, struct S_FDI)
|
|
CASE(T_S_FDF, struct S_FDF)
|
|
CASE(T_S_FDD, struct S_FDD)
|
|
CASE(T_S_FDP, struct S_FDP)
|
|
CASE(T_S_FPI, struct S_FPI)
|
|
CASE(T_S_FPF, struct S_FPF)
|
|
CASE(T_S_FPD, struct S_FPD)
|
|
CASE(T_S_FPP, struct S_FPP)
|
|
CASE(T_S_DII, struct S_DII)
|
|
CASE(T_S_DIF, struct S_DIF)
|
|
CASE(T_S_DID, struct S_DID)
|
|
CASE(T_S_DIP, struct S_DIP)
|
|
CASE(T_S_DFI, struct S_DFI)
|
|
CASE(T_S_DFF, struct S_DFF)
|
|
CASE(T_S_DFD, struct S_DFD)
|
|
CASE(T_S_DFP, struct S_DFP)
|
|
CASE(T_S_DDI, struct S_DDI)
|
|
CASE(T_S_DDF, struct S_DDF)
|
|
CASE(T_S_DDD, struct S_DDD)
|
|
CASE(T_S_DDP, struct S_DDP)
|
|
CASE(T_S_DPI, struct S_DPI)
|
|
CASE(T_S_DPF, struct S_DPF)
|
|
CASE(T_S_DPD, struct S_DPD)
|
|
CASE(T_S_DPP, struct S_DPP)
|
|
CASE(T_S_PII, struct S_PII)
|
|
CASE(T_S_PIF, struct S_PIF)
|
|
CASE(T_S_PID, struct S_PID)
|
|
CASE(T_S_PIP, struct S_PIP)
|
|
CASE(T_S_PFI, struct S_PFI)
|
|
CASE(T_S_PFF, struct S_PFF)
|
|
CASE(T_S_PFD, struct S_PFD)
|
|
CASE(T_S_PFP, struct S_PFP)
|
|
CASE(T_S_PDI, struct S_PDI)
|
|
CASE(T_S_PDF, struct S_PDF)
|
|
CASE(T_S_PDD, struct S_PDD)
|
|
CASE(T_S_PDP, struct S_PDP)
|
|
CASE(T_S_PPI, struct S_PPI)
|
|
CASE(T_S_PPF, struct S_PPF)
|
|
CASE(T_S_PPD, struct S_PPD)
|
|
CASE(T_S_PPP, struct S_PPP)
|
|
CASE(T_S_FFFF, struct S_FFFF)
|
|
default: exit(-1); // invalid id
|
|
}
|
|
}
|
|
|
|
va_end(a_list);
|
|
}
|