| /* | |
| * 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); | |
| } |