Interpreter - Incremental API changes
[rune.git] / libi / clangdll.c
1 /*
2  * CLANGDLL.C   - Direct interface for C Language DLL functions
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 typedef void *void_ptr;
11 typedef void_ptr (*isys_generic_c_call_t)(runctx_p ct, Exp *exp, RefStor **prs);
12
13 /*
14  * isys_generic_c_call()
15  *
16  * Execute a generic C call.  Note that the right hand side should
17  * already be properly aligned for the call, we simply switch on the
18  * number of arguments and the size of the return value.
19  */
20 static __inline void *
21 isys_call(runctx_p ct, Exp *exp, RefStor **prs __unused, const int asize, const int rsize)
22 {
23         TmpStor *ts;
24         RefStor *rs = NULL;
25         struct my_rhs {
26                 int args[asize/4];
27         } *rhs;
28         struct my_lhs {
29                 int rsize[rsize/4];
30         };
31         union {
32                 void (*func0)(struct my_rhs rhs);
33                 int8_t (*func1)(struct my_rhs rhs);
34                 int16_t (*func2)(struct my_rhs rhs);
35                 int32_t (*func4)(struct my_rhs rhs);
36                 int64_t (*func8)(struct my_rhs rhs);
37                 struct my_lhs (*funcX)(struct my_rhs rhs);
38         } func;
39
40         ts = getExpTmpData(ct, exp);
41         rhs = exp->ex_Rhs->ex_Func(ct, exp->ex_Rhs, &rs);
42         func.func0 = exp->ex_Lhs->ex_Decl->d_ProcDecl.ed_DLLFunc;
43
44         switch(exp->ex_Type->ty_Bytes) {
45         case 0:
46                 func.func0(*rhs);
47                 break;
48         case 1:
49                 *(int8_t *)ts = func.func1(*rhs);
50                 break;
51         case 2:
52                 *(int16_t *)ts = func.func2(*rhs);
53                 break;
54         case 4:
55                 *(int32_t *)ts = func.func4(*rhs);
56                 break;
57         case 8:
58                 *(int64_t *)ts = func.func8(*rhs);
59                 break;
60         default:
61                 assert(0);
62                 /* *(struct my_lhs *)ts = func.funcX(*rhs); */
63                 break;
64         }
65         relsRefStor(rs);
66         return((void *)ts);
67 }
68
69 #define ISYS_CALL(asize,rsize)                                  \
70 static void *                                                   \
71 isys_call_ ## asize ## _ ## rsize(runctx_p ct, Exp *exp, RefStor **prs) \
72 {                                                               \
73                 return(isys_call(ct, exp, prs, 0x ## asize, 0x ## rsize));\
74 }                                                               \
75
76 #define ISYS_CALLGROUP(asize)                                   \
77 ISYS_CALL(asize,00)                                             \
78 ISYS_CALL(asize,01)                                             \
79 ISYS_CALL(asize,02)                                             \
80 ISYS_CALL(asize,04)                                             \
81 ISYS_CALL(asize,08)                                             \
82 ISYS_CALL(asize,0C)                                             \
83 ISYS_CALL(asize,10)                                             \
84 ISYS_CALL(asize,14)                                             \
85 ISYS_CALL(asize,18)                                             \
86 ISYS_CALL(asize,1C)                                             \
87 ISYS_CALL(asize,20)                                             \
88 ISYS_CALL(asize,24)                                             \
89 ISYS_CALL(asize,28)                                             \
90 ISYS_CALL(asize,2C)                                             \
91 ISYS_CALL(asize,30)                                             \
92 ISYS_CALL(asize,34)                                             \
93 ISYS_CALL(asize,38)                                             \
94 ISYS_CALL(asize,3C)                                             \
95
96 ISYS_CALLGROUP(00)
97 ISYS_CALLGROUP(04)
98 ISYS_CALLGROUP(08)
99 ISYS_CALLGROUP(0C)
100 ISYS_CALLGROUP(10)
101 ISYS_CALLGROUP(14)
102 ISYS_CALLGROUP(18)
103 ISYS_CALLGROUP(1C)
104 ISYS_CALLGROUP(20)
105 ISYS_CALLGROUP(24)
106 ISYS_CALLGROUP(28)
107 ISYS_CALLGROUP(2C)
108 ISYS_CALLGROUP(30)
109 ISYS_CALLGROUP(34)
110 ISYS_CALLGROUP(38)
111 ISYS_CALLGROUP(3C)
112
113 isys_generic_c_call_t   isys_array[64 / sizeof(int)][64] = {
114         {       isys_call_00_00, isys_call_00_01, isys_call_00_02, NULL,
115                 isys_call_00_04, NULL,            NULL,           NULL,
116                 isys_call_00_08, NULL,            NULL,           NULL,
117                 isys_call_00_0C, NULL,            NULL,           NULL,
118                 isys_call_00_10, NULL,            NULL,           NULL,
119                 isys_call_00_14, NULL,            NULL,           NULL,
120                 isys_call_00_18, NULL,            NULL,           NULL,
121                 isys_call_00_1C, NULL,            NULL,           NULL,
122                 isys_call_00_20, NULL,            NULL,           NULL,
123                 isys_call_00_24, NULL,            NULL,           NULL,
124                 isys_call_00_28, NULL,            NULL,           NULL,
125                 isys_call_00_2C, NULL,            NULL,           NULL,
126                 isys_call_00_30, NULL,            NULL,           NULL,
127                 isys_call_00_34, NULL,            NULL,           NULL,
128                 isys_call_00_38, NULL,            NULL,           NULL,
129                 isys_call_00_3C, NULL,            NULL,           NULL  },
130         {       isys_call_04_00, isys_call_04_01, isys_call_04_02, NULL,
131                 isys_call_04_04, NULL,            NULL,           NULL,
132                 isys_call_04_08, NULL,            NULL,           NULL,
133                 isys_call_04_0C, NULL,            NULL,           NULL,
134                 isys_call_04_10, NULL,            NULL,           NULL,
135                 isys_call_04_14, NULL,            NULL,           NULL,
136                 isys_call_04_18, NULL,            NULL,           NULL,
137                 isys_call_04_1C, NULL,            NULL,           NULL,
138                 isys_call_04_20, NULL,            NULL,           NULL,
139                 isys_call_04_24, NULL,            NULL,           NULL,
140                 isys_call_04_28, NULL,            NULL,           NULL,
141                 isys_call_04_2C, NULL,            NULL,           NULL,
142                 isys_call_04_30, NULL,            NULL,           NULL,
143                 isys_call_04_34, NULL,            NULL,           NULL,
144                 isys_call_04_38, NULL,            NULL,           NULL,
145                 isys_call_04_3C, NULL,            NULL,           NULL  },
146         {       isys_call_08_00, isys_call_08_01, isys_call_08_02, NULL,
147                 isys_call_08_04, NULL,            NULL,           NULL,
148                 isys_call_08_08, NULL,            NULL,           NULL,
149                 isys_call_08_0C, NULL,            NULL,           NULL,
150                 isys_call_08_10, NULL,            NULL,           NULL,
151                 isys_call_08_14, NULL,            NULL,           NULL,
152                 isys_call_08_18, NULL,            NULL,           NULL,
153                 isys_call_08_1C, NULL,            NULL,           NULL,
154                 isys_call_08_20, NULL,            NULL,           NULL,
155                 isys_call_08_24, NULL,            NULL,           NULL,
156                 isys_call_08_28, NULL,            NULL,           NULL,
157                 isys_call_08_2C, NULL,            NULL,           NULL,
158                 isys_call_08_30, NULL,            NULL,           NULL,
159                 isys_call_08_34, NULL,            NULL,           NULL,
160                 isys_call_08_38, NULL,            NULL,           NULL,
161                 isys_call_08_3C, NULL,            NULL,           NULL  },
162         {       isys_call_0C_00, isys_call_0C_01, isys_call_0C_02, NULL,
163                 isys_call_0C_04, NULL,            NULL,           NULL,
164                 isys_call_0C_08, NULL,            NULL,           NULL,
165                 isys_call_0C_0C, NULL,            NULL,           NULL,
166                 isys_call_0C_10, NULL,            NULL,           NULL,
167                 isys_call_0C_14, NULL,            NULL,           NULL,
168                 isys_call_0C_18, NULL,            NULL,           NULL,
169                 isys_call_0C_1C, NULL,            NULL,           NULL,
170                 isys_call_0C_20, NULL,            NULL,           NULL,
171                 isys_call_0C_24, NULL,            NULL,           NULL,
172                 isys_call_0C_28, NULL,            NULL,           NULL,
173                 isys_call_0C_2C, NULL,            NULL,           NULL,
174                 isys_call_0C_30, NULL,            NULL,           NULL,
175                 isys_call_0C_34, NULL,            NULL,           NULL,
176                 isys_call_0C_38, NULL,            NULL,           NULL,
177                 isys_call_0C_3C, NULL,            NULL,           NULL  },
178         {       isys_call_10_00, isys_call_10_01, isys_call_10_02, NULL,
179                 isys_call_10_04, NULL,            NULL,           NULL,
180                 isys_call_10_08, NULL,            NULL,           NULL,
181                 isys_call_10_0C, NULL,            NULL,           NULL,
182                 isys_call_10_10, NULL,            NULL,           NULL,
183                 isys_call_10_14, NULL,            NULL,           NULL,
184                 isys_call_10_18, NULL,            NULL,           NULL,
185                 isys_call_10_1C, NULL,            NULL,           NULL,
186                 isys_call_10_20, NULL,            NULL,           NULL,
187                 isys_call_10_24, NULL,            NULL,           NULL,
188                 isys_call_10_28, NULL,            NULL,           NULL,
189                 isys_call_10_2C, NULL,            NULL,           NULL,
190                 isys_call_10_30, NULL,            NULL,           NULL,
191                 isys_call_10_34, NULL,            NULL,           NULL,
192                 isys_call_10_38, NULL,            NULL,           NULL,
193                 isys_call_10_3C, NULL,            NULL,           NULL  },
194         {       isys_call_14_00, isys_call_14_01, isys_call_14_02, NULL,
195                 isys_call_14_04, NULL,            NULL,           NULL,
196                 isys_call_14_08, NULL,            NULL,           NULL,
197                 isys_call_14_0C, NULL,            NULL,           NULL,
198                 isys_call_14_10, NULL,            NULL,           NULL,
199                 isys_call_14_14, NULL,            NULL,           NULL,
200                 isys_call_14_18, NULL,            NULL,           NULL,
201                 isys_call_14_1C, NULL,            NULL,           NULL,
202                 isys_call_14_20, NULL,            NULL,           NULL,
203                 isys_call_14_24, NULL,            NULL,           NULL,
204                 isys_call_14_28, NULL,            NULL,           NULL,
205                 isys_call_14_2C, NULL,            NULL,           NULL,
206                 isys_call_14_30, NULL,            NULL,           NULL,
207                 isys_call_14_34, NULL,            NULL,           NULL,
208                 isys_call_14_38, NULL,            NULL,           NULL,
209                 isys_call_14_3C, NULL,            NULL,           NULL  },
210         {       isys_call_18_00, isys_call_18_01, isys_call_18_02, NULL,
211                 isys_call_18_04, NULL,            NULL,           NULL,
212                 isys_call_18_08, NULL,            NULL,           NULL,
213                 isys_call_18_0C, NULL,            NULL,           NULL,
214                 isys_call_18_10, NULL,            NULL,           NULL,
215                 isys_call_18_14, NULL,            NULL,           NULL,
216                 isys_call_18_18, NULL,            NULL,           NULL,
217                 isys_call_18_1C, NULL,            NULL,           NULL,
218                 isys_call_18_20, NULL,            NULL,           NULL,
219                 isys_call_18_24, NULL,            NULL,           NULL,
220                 isys_call_18_28, NULL,            NULL,           NULL,
221                 isys_call_18_2C, NULL,            NULL,           NULL,
222                 isys_call_18_30, NULL,            NULL,           NULL,
223                 isys_call_18_34, NULL,            NULL,           NULL,
224                 isys_call_18_38, NULL,            NULL,           NULL,
225                 isys_call_18_3C, NULL,            NULL,           NULL  },
226         {       isys_call_1C_00, isys_call_1C_01, isys_call_1C_02, NULL,
227                 isys_call_1C_04, NULL,            NULL,           NULL,
228                 isys_call_1C_08, NULL,            NULL,           NULL,
229                 isys_call_1C_0C, NULL,            NULL,           NULL,
230                 isys_call_1C_10, NULL,            NULL,           NULL,
231                 isys_call_1C_14, NULL,            NULL,           NULL,
232                 isys_call_1C_18, NULL,            NULL,           NULL,
233                 isys_call_1C_1C, NULL,            NULL,           NULL,
234                 isys_call_1C_20, NULL,            NULL,           NULL,
235                 isys_call_1C_24, NULL,            NULL,           NULL,
236                 isys_call_1C_28, NULL,            NULL,           NULL,
237                 isys_call_1C_2C, NULL,            NULL,           NULL,
238                 isys_call_1C_30, NULL,            NULL,           NULL,
239                 isys_call_1C_34, NULL,            NULL,           NULL,
240                 isys_call_1C_38, NULL,            NULL,           NULL,
241                 isys_call_1C_3C, NULL,            NULL,           NULL  },
242         {       isys_call_20_00, isys_call_20_01, isys_call_20_02, NULL,
243                 isys_call_20_04, NULL,            NULL,           NULL,
244                 isys_call_20_08, NULL,            NULL,           NULL,
245                 isys_call_20_0C, NULL,            NULL,           NULL,
246                 isys_call_20_10, NULL,            NULL,           NULL,
247                 isys_call_20_14, NULL,            NULL,           NULL,
248                 isys_call_20_18, NULL,            NULL,           NULL,
249                 isys_call_20_1C, NULL,            NULL,           NULL,
250                 isys_call_20_20, NULL,            NULL,           NULL,
251                 isys_call_20_24, NULL,            NULL,           NULL,
252                 isys_call_20_28, NULL,            NULL,           NULL,
253                 isys_call_20_2C, NULL,            NULL,           NULL,
254                 isys_call_20_30, NULL,            NULL,           NULL,
255                 isys_call_20_34, NULL,            NULL,           NULL,
256                 isys_call_20_38, NULL,            NULL,           NULL,
257                 isys_call_20_3C, NULL,            NULL,           NULL  },
258         {       isys_call_24_00, isys_call_24_01, isys_call_24_02, NULL,
259                 isys_call_24_04, NULL,            NULL,           NULL,
260                 isys_call_24_08, NULL,            NULL,           NULL,
261                 isys_call_24_0C, NULL,            NULL,           NULL,
262                 isys_call_24_10, NULL,            NULL,           NULL,
263                 isys_call_24_14, NULL,            NULL,           NULL,
264                 isys_call_24_18, NULL,            NULL,           NULL,
265                 isys_call_24_1C, NULL,            NULL,           NULL,
266                 isys_call_24_20, NULL,            NULL,           NULL,
267                 isys_call_24_24, NULL,            NULL,           NULL,
268                 isys_call_24_28, NULL,            NULL,           NULL,
269                 isys_call_24_2C, NULL,            NULL,           NULL,
270                 isys_call_24_30, NULL,            NULL,           NULL,
271                 isys_call_24_34, NULL,            NULL,           NULL,
272                 isys_call_24_38, NULL,            NULL,           NULL,
273                 isys_call_24_3C, NULL,            NULL,           NULL  },
274         {       isys_call_28_00, isys_call_28_01, isys_call_28_02, NULL,
275                 isys_call_28_04, NULL,            NULL,           NULL,
276                 isys_call_28_08, NULL,            NULL,           NULL,
277                 isys_call_28_0C, NULL,            NULL,           NULL,
278                 isys_call_28_10, NULL,            NULL,           NULL,
279                 isys_call_28_14, NULL,            NULL,           NULL,
280                 isys_call_28_18, NULL,            NULL,           NULL,
281                 isys_call_28_1C, NULL,            NULL,           NULL,
282                 isys_call_28_20, NULL,            NULL,           NULL,
283                 isys_call_28_24, NULL,            NULL,           NULL,
284                 isys_call_28_28, NULL,            NULL,           NULL,
285                 isys_call_28_2C, NULL,            NULL,           NULL,
286                 isys_call_28_30, NULL,            NULL,           NULL,
287                 isys_call_28_34, NULL,            NULL,           NULL,
288                 isys_call_28_38, NULL,            NULL,           NULL,
289                 isys_call_28_3C, NULL,            NULL,           NULL  },
290         {       isys_call_2C_00, isys_call_2C_01, isys_call_2C_02, NULL,
291                 isys_call_2C_04, NULL,            NULL,           NULL,
292                 isys_call_2C_08, NULL,            NULL,           NULL,
293                 isys_call_2C_0C, NULL,            NULL,           NULL,
294                 isys_call_2C_10, NULL,            NULL,           NULL,
295                 isys_call_2C_14, NULL,            NULL,           NULL,
296                 isys_call_2C_18, NULL,            NULL,           NULL,
297                 isys_call_2C_1C, NULL,            NULL,           NULL,
298                 isys_call_2C_20, NULL,            NULL,           NULL,
299                 isys_call_2C_24, NULL,            NULL,           NULL,
300                 isys_call_2C_28, NULL,            NULL,           NULL,
301                 isys_call_2C_2C, NULL,            NULL,           NULL,
302                 isys_call_2C_30, NULL,            NULL,           NULL,
303                 isys_call_2C_34, NULL,            NULL,           NULL,
304                 isys_call_2C_38, NULL,            NULL,           NULL,
305                 isys_call_2C_3C, NULL,            NULL,           NULL  },
306         {       isys_call_30_00, isys_call_30_01, isys_call_30_02, NULL,
307                 isys_call_30_04, NULL,            NULL,           NULL,
308                 isys_call_30_08, NULL,            NULL,           NULL,
309                 isys_call_30_0C, NULL,            NULL,           NULL,
310                 isys_call_30_10, NULL,            NULL,           NULL,
311                 isys_call_30_14, NULL,            NULL,           NULL,
312                 isys_call_30_18, NULL,            NULL,           NULL,
313                 isys_call_30_1C, NULL,            NULL,           NULL,
314                 isys_call_30_20, NULL,            NULL,           NULL,
315                 isys_call_30_24, NULL,            NULL,           NULL,
316                 isys_call_30_28, NULL,            NULL,           NULL,
317                 isys_call_30_2C, NULL,            NULL,           NULL,
318                 isys_call_30_30, NULL,            NULL,           NULL,
319                 isys_call_30_34, NULL,            NULL,           NULL,
320                 isys_call_30_38, NULL,            NULL,           NULL,
321                 isys_call_30_3C, NULL,            NULL,           NULL  },
322         {       isys_call_34_00, isys_call_34_01, isys_call_34_02, NULL,
323                 isys_call_34_04, NULL,            NULL,           NULL,
324                 isys_call_34_08, NULL,            NULL,           NULL,
325                 isys_call_34_0C, NULL,            NULL,           NULL,
326                 isys_call_34_10, NULL,            NULL,           NULL,
327                 isys_call_34_14, NULL,            NULL,           NULL,
328                 isys_call_34_18, NULL,            NULL,           NULL,
329                 isys_call_34_1C, NULL,            NULL,           NULL,
330                 isys_call_34_20, NULL,            NULL,           NULL,
331                 isys_call_34_24, NULL,            NULL,           NULL,
332                 isys_call_34_28, NULL,            NULL,           NULL,
333                 isys_call_34_2C, NULL,            NULL,           NULL,
334                 isys_call_34_30, NULL,            NULL,           NULL,
335                 isys_call_34_34, NULL,            NULL,           NULL,
336                 isys_call_34_38, NULL,            NULL,           NULL,
337                 isys_call_34_3C, NULL,            NULL,           NULL  },
338         {       isys_call_38_00, isys_call_38_01, isys_call_38_02, NULL,
339                 isys_call_38_04, NULL,            NULL,           NULL,
340                 isys_call_38_08, NULL,            NULL,           NULL,
341                 isys_call_38_0C, NULL,            NULL,           NULL,
342                 isys_call_38_10, NULL,            NULL,           NULL,
343                 isys_call_38_14, NULL,            NULL,           NULL,
344                 isys_call_38_18, NULL,            NULL,           NULL,
345                 isys_call_38_1C, NULL,            NULL,           NULL,
346                 isys_call_38_20, NULL,            NULL,           NULL,
347                 isys_call_38_24, NULL,            NULL,           NULL,
348                 isys_call_38_28, NULL,            NULL,           NULL,
349                 isys_call_38_2C, NULL,            NULL,           NULL,
350                 isys_call_38_30, NULL,            NULL,           NULL,
351                 isys_call_38_34, NULL,            NULL,           NULL,
352                 isys_call_38_38, NULL,            NULL,           NULL,
353                 isys_call_38_3C, NULL,            NULL,           NULL  },
354         {       isys_call_3C_00, isys_call_3C_01, isys_call_3C_02, NULL,
355                 isys_call_3C_04, NULL,            NULL,           NULL,
356                 isys_call_3C_08, NULL,            NULL,           NULL,
357                 isys_call_3C_0C, NULL,            NULL,           NULL,
358                 isys_call_3C_10, NULL,            NULL,           NULL,
359                 isys_call_3C_14, NULL,            NULL,           NULL,
360                 isys_call_3C_18, NULL,            NULL,           NULL,
361                 isys_call_3C_1C, NULL,            NULL,           NULL,
362                 isys_call_3C_20, NULL,            NULL,           NULL,
363                 isys_call_3C_24, NULL,            NULL,           NULL,
364                 isys_call_3C_28, NULL,            NULL,           NULL,
365                 isys_call_3C_2C, NULL,            NULL,           NULL,
366                 isys_call_3C_30, NULL,            NULL,           NULL,
367                 isys_call_3C_34, NULL,            NULL,           NULL,
368                 isys_call_3C_38, NULL,            NULL,           NULL,
369                 isys_call_3C_3C, NULL,            NULL,           NULL          }
370 };
371
372 /*
373  * Construct an interpreter Exp execution function for this C Language
374  * procedure call.
375  */
376 ex_func_t
377 DLLCLangConstruct(Declaration *d)
378 {
379         Type *type;
380         runesize_t atsize;
381         runesize_t rtsize;
382
383         /*
384          * If the resolver could not find the DLL symbol there is nothing
385          * we can do here.
386          */
387         dassert(d->d_Op == DOP_PROC);
388         if (d->d_ProcDecl.ed_DLLFunc == NULL)
389                 return(NULL);
390
391         /*
392          * Validate argument and return type sizes
393          */
394         type = d->d_ProcDecl.ed_Type;
395         atsize = type->ty_ProcType.et_ArgsType->ty_Bytes;
396         if (atsize & (sizeof(int) - 1)) {
397                 fatal("DLLLFunction %s args not C-aligned (%d bytes)",
398                           d->d_Id, atsize);
399         }
400         if (atsize >= 64) {
401                 fatal("DLLLFunction %s args %d "
402                       "bytes >= 64 bytes, not supported!",
403                           d->d_Id, atsize);
404         }
405         rtsize = type->ty_ProcType.et_RetType->ty_Bytes;
406         if (rtsize > sizeof(int) && (rtsize & (sizeof(int) - 1))) {
407                 fatal("DLLLFunction %s return type > sizeof(int) must be "
408                       "C-aligned (%d bytes)",
409                       d->d_Id, rtsize);
410         }
411         if (rtsize >= 64) {
412                 fatal("DLLLFunction %s return type %d bytes >= 64 bytes, "
413                       "not supported!",
414                       d->d_Id, rtsize);
415         }
416         return(isys_array[atsize / sizeof(int)][rtsize]);
417 }