summaryrefslogtreecommitdiff
path: root/src/lj_ccall.h
blob: b46483f1f5bf93d61416dac372e31b4a23cc2f63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
** FFI C call handling.
** Copyright (C) 2005-2022 Mike Pall. See Copyright Notice in luajit.h
*/

#ifndef _LJ_CCALL_H
#define _LJ_CCALL_H

#include "lj_obj.h"
#include "lj_ctype.h"

#if LJ_HASFFI

/* -- C calling conventions ----------------------------------------------- */

#if LJ_TARGET_X86ORX64

#if LJ_TARGET_X86
#define CCALL_NARG_GPR		2	/* For fastcall arguments. */
#define CCALL_NARG_FPR		0
#define CCALL_NRET_GPR		2
#define CCALL_NRET_FPR		1	/* For FP results on x87 stack. */
#define CCALL_ALIGN_STACKARG	0	/* Don't align argument on stack. */
#elif LJ_ABI_WIN
#define CCALL_NARG_GPR		4
#define CCALL_NARG_FPR		4
#define CCALL_NRET_GPR		1
#define CCALL_NRET_FPR		1
#define CCALL_SPS_EXTRA		4
#else
#define CCALL_NARG_GPR		6
#define CCALL_NARG_FPR		8
#define CCALL_NRET_GPR		2
#define CCALL_NRET_FPR		2
#define CCALL_VECTOR_REG	1	/* Pass vectors in registers. */
#endif

#define CCALL_SPS_FREE		1
#define CCALL_ALIGN_CALLSTATE	16

typedef LJ_ALIGN(16) union FPRArg {
  double d[2];
  float f[4];
  uint8_t b[16];
  uint16_t s[8];
  int i[4];
  int64_t l[2];
} FPRArg;

typedef intptr_t GPRArg;

#elif LJ_TARGET_ARM

#define CCALL_NARG_GPR		4
#define CCALL_NRET_GPR		2	/* For softfp double. */
#if LJ_ABI_SOFTFP
#define CCALL_NARG_FPR		0
#define CCALL_NRET_FPR		0
#else
#define CCALL_NARG_FPR		8
#define CCALL_NRET_FPR		4
#endif
#define CCALL_SPS_FREE		0

typedef intptr_t GPRArg;
typedef union FPRArg {
  double d;
  float f[2];
} FPRArg;

#elif LJ_TARGET_PPC

#define CCALL_NARG_GPR		8
#define CCALL_NARG_FPR		8
#define CCALL_NRET_GPR		4	/* For complex double. */
#define CCALL_NRET_FPR		1
#define CCALL_SPS_EXTRA		4
#define CCALL_SPS_FREE		0

typedef intptr_t GPRArg;
typedef double FPRArg;

#elif LJ_TARGET_PPCSPE

#define CCALL_NARG_GPR		8
#define CCALL_NARG_FPR		0
#define CCALL_NRET_GPR		4	/* For softfp complex double. */
#define CCALL_NRET_FPR		0
#define CCALL_SPS_FREE		0	/* NYI */

typedef intptr_t GPRArg;

#elif LJ_TARGET_MIPS

#define CCALL_NARG_GPR		4
#define CCALL_NARG_FPR		2
#define CCALL_NRET_GPR		2
#define CCALL_NRET_FPR		2
#define CCALL_SPS_EXTRA		7
#define CCALL_SPS_FREE		1

typedef intptr_t GPRArg;
typedef union FPRArg {
  double d;
  struct { LJ_ENDIAN_LOHI(float f; , float g;) };
} FPRArg;

#else
#error "Missing calling convention definitions for this architecture"
#endif

#ifndef CCALL_SPS_EXTRA
#define CCALL_SPS_EXTRA		0
#endif
#ifndef CCALL_VECTOR_REG
#define CCALL_VECTOR_REG	0
#endif
#ifndef CCALL_ALIGN_STACKARG
#define CCALL_ALIGN_STACKARG	1
#endif
#ifndef CCALL_ALIGN_CALLSTATE
#define CCALL_ALIGN_CALLSTATE	8
#endif

#define CCALL_NUM_GPR \
  (CCALL_NARG_GPR > CCALL_NRET_GPR ? CCALL_NARG_GPR : CCALL_NRET_GPR)
#define CCALL_NUM_FPR \
  (CCALL_NARG_FPR > CCALL_NRET_FPR ? CCALL_NARG_FPR : CCALL_NRET_FPR)

/* Check against constants in lj_ctype.h. */
LJ_STATIC_ASSERT(CCALL_NUM_GPR <= CCALL_MAX_GPR);
LJ_STATIC_ASSERT(CCALL_NUM_FPR <= CCALL_MAX_FPR);

#define CCALL_MAXSTACK		32

/* -- C call state -------------------------------------------------------- */

typedef LJ_ALIGN(CCALL_ALIGN_CALLSTATE) struct CCallState {
  void (*func)(void);		/* Pointer to called function. */
  uint32_t spadj;		/* Stack pointer adjustment. */
  uint8_t nsp;			/* Number of stack slots. */
  uint8_t retref;		/* Return value by reference. */
#if LJ_TARGET_X64
  uint8_t ngpr;			/* Number of arguments in GPRs. */
  uint8_t nfpr;			/* Number of arguments in FPRs. */
#elif LJ_TARGET_X86
  uint8_t resx87;		/* Result on x87 stack: 1:float, 2:double. */
#elif LJ_TARGET_PPC
  uint8_t nfpr;			/* Number of arguments in FPRs. */
#endif
#if LJ_32
  int32_t align1;
#endif
#if CCALL_NUM_FPR
  FPRArg fpr[CCALL_NUM_FPR];	/* Arguments/results in FPRs. */
#endif
  GPRArg gpr[CCALL_NUM_GPR];	/* Arguments/results in GPRs. */
  GPRArg stack[CCALL_MAXSTACK];	/* Stack slots. */
} CCallState;

/* -- C call handling ----------------------------------------------------- */

/* Really belongs to lj_vm.h. */
LJ_ASMF void LJ_FASTCALL lj_vm_ffi_call(CCallState *cc);

LJ_FUNC CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o);
LJ_FUNC int lj_ccall_func(lua_State *L, GCcdata *cd);

#endif

#endif