Permalink
Newer
Older
100644 367 lines (250 sloc) 8.63 KB
Michael Scott
Feb 17, 2004
1
/*
2
Copyright (C) 2001-2011, Parrot Foundation.
Michael Scott
Feb 17, 2004
3
4
=head1 NAME
5
6
src/pmc/nci.pmc - Native Call Interface
Michael Scott
Feb 17, 2004
7
8
=head1 DESCRIPTION
9
10
The vtable functions for the native C call functions.
11
12
=head2 Methods
13
14
=over 4
15
16
=cut
17
18
*/
20
/* HEADERIZER HFILE: none */
21
/* HEADERIZER BEGIN: static */
22
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
23
24
PARROT_IGNORABLE_RESULT
25
static nci_thunk_t /*@alt void@*/
26
build_func(PARROT_INTERP,
27
ARGIN(PMC *obj),
28
ARGMOD(Parrot_NCI_attributes *nci))
29
__attribute__nonnull__(1)
30
__attribute__nonnull__(2)
31
__attribute__nonnull__(3)
32
FUNC_MODIFIES(*nci);
33
34
#define ASSERT_ARGS_build_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
35
PARROT_ASSERT_ARG(interp) \
36
, PARROT_ASSERT_ARG(obj) \
37
, PARROT_ASSERT_ARG(nci))
38
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
39
/* HEADERIZER END: static */
40
43
=item C<static nci_thunk_t build_func(PARROT_INTERP, PMC *obj,
44
Parrot_NCI_attributes *nci)>
46
Actually build the NCI thunk.
47
48
=cut
49
50
*/
51
52
PARROT_IGNORABLE_RESULT
53
static nci_thunk_t
54
build_func(PARROT_INTERP, ARGIN(PMC *obj), ARGMOD(Parrot_NCI_attributes *nci))
56
ASSERT_ARGS(build_func)
58
Parrot_nci_sig_to_pcc(interp, nci->signature,
59
&nci->pcc_params_signature,
60
&nci->pcc_return_signature);
62
/* Arity is length of the signature minus one (the return type). */
63
nci->arity = VTABLE_elements(interp, nci->signature) - 1;
65
/* Build call function. */
66
nci->fb_info = build_call_func(interp, nci->signature);
67
nci->func = F2DPTR(VTABLE_get_pointer(interp, nci->fb_info));
68
PARROT_GC_WRITE_BARRIER(interp, obj);
69
70
return (nci_thunk_t)nci->func;
74
pmclass NCI auto_attrs provides invokable {
75
/* NCI thunk handling attributes */
76
ATTR PMC *signature; /* parsed signature */
77
ATTR void *func; /* function pointer to call */
78
ATTR PMC *fb_info; /* frame-builder info */
79
ATTR void *orig_func; /* pointer to wrapped function */
81
/* Parrot Sub-ish attributes */
82
ATTR STRING *pcc_params_signature;
83
ATTR STRING *pcc_return_signature;
84
ATTR INTVAL arity;
87
ATTR STRING *long_signature;
88
ATTR PMC *multi_sig;
Michael Scott
Feb 17, 2004
90
/*
91
94
Return the MMD signature PMC, if any or C<PMCNULL>.
95
96
=cut
97
98
*/
99
101
PMC *sig;
102
GET_ATTR_multi_sig(INTERP, SELF, sig);
[core] partial fix for TT #667, examples/namespace/namespace_dump.pir…
May 18, 2009
103
if (PMC_IS_NULL(sig))
106
}
107
108
/*
109
Michael Scott
Feb 17, 2004
110
=item C<void init()>
111
112
Initializes the NCI with a C<NULL> function pointer.
113
114
=cut
115
116
*/
117
119
PObj_custom_mark_SET(SELF);
Leopold Toetsch
nci
Jan 21, 2003
120
}
121
122
VTABLE void *get_pointer() {
123
return PARROT_NCI(SELF)->orig_func;
124
}
125
Michael Scott
Feb 17, 2004
126
/*
127
128
=item C<void set_pmc_keyed(PMC *key, PMC *p)>
129
130
=item C<void set_pmc_keyed_str(STRING *key, PMC *p)>
131
132
Call the equivalent C<set_pointer*> function.
133
134
=cut
135
136
*/
137
138
VTABLE void set_pmc_keyed(PMC *key, PMC *p) {
139
STATICSELF.set_pointer_keyed(key, VTABLE_get_pointer(INTERP, p));
140
}
141
142
VTABLE void set_pmc_keyed_str(STRING *key, PMC *p) {
143
STATICSELF.set_pointer_keyed_str(key, VTABLE_get_pointer(INTERP, p));
144
}
145
146
/*
147
148
=item C<void set_pointer_keyed(PMC *key, void *func)>
Michael Scott
Feb 17, 2004
149
150
Sets the specified function pointer and signature (C<*key>).
Michael Scott
Feb 17, 2004
151
152
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
153
154
Sets the specified function pointer and siganture as described in the string C<key>.
155
Michael Scott
Feb 17, 2004
156
=cut
157
158
*/
159
160
VTABLE void set_pointer_keyed(PMC *key, void *func) {
161
/* Store the original function and signature. */
162
SET_ATTR_orig_func(INTERP, SELF, func);
163
SET_ATTR_signature(INTERP, SELF, key);
164
}
166
VTABLE void set_pointer_keyed_str(STRING *key, void *func) {
167
SELF.set_pointer_keyed(Parrot_nci_parse_signature(INTERP, key), func);
170
/*
171
172
=item C<void mark()>
173
174
Mark any referenced strings and PMCs.
175
176
=cut
177
178
*/
179
VTABLE void mark() {
180
if (PARROT_NCI(SELF)) {
181
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
183
Parrot_gc_mark_PMC_alive(interp, nci_info->signature);
184
Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
185
Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig);
187
Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
188
Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
189
Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_return_signature);
190
}
191
}
192
193
/*
194
Michael Scott
Feb 17, 2004
195
=item C<PMC *clone()>
196
197
Creates and returns a clone of the NCI.
198
199
=cut
200
201
*/
202
204
Parrot_NCI_attributes * const nci_info_self = PARROT_NCI(SELF);
206
PMC * const ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
207
Parrot_NCI_attributes * const nci_info_ret = PARROT_NCI(ret);
Michael Scott
Feb 17, 2004
209
/* FIXME if data is malloced (JIT/i386!) then we need
210
* the length of data here, to memcpy it
211
* ManagedStruct or Buffer?
212
*/
213
nci_info_ret->func = nci_info_self->func;
214
nci_info_ret->fb_info = nci_info_self->fb_info;
215
nci_info_ret->orig_func = nci_info_self->orig_func;
216
nci_info_ret->signature = nci_info_self->signature;
217
nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature;
218
nci_info_ret->pcc_return_signature = nci_info_self->pcc_params_signature;
219
nci_info_ret->arity = nci_info_self->arity;
220
PObj_get_FLAGS(ret) = PObj_get_FLAGS(SELF);
Michael Scott
Feb 17, 2004
222
return ret;
Michael Scott
Feb 17, 2004
225
/*
226
227
=item C<INTVAL defined()>
228
229
Returns whether the NCI is defined.
230
231
=cut
232
233
*/
234
236
const Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
237
return nci_info->orig_func != NULL;
Michael Scott
Feb 17, 2004
240
/*
241
242
=item C<opcode_t *invoke(void *next)>
Michael Scott
Feb 17, 2004
243
244
Calls the associated C function, returning C<*next>. If the invocant is a
245
class, the PMC arguments are shifted down.
Michael Scott
Feb 17, 2004
246
247
=cut
248
249
*/
250
251
VTABLE opcode_t *invoke(void *next) {
252
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
253
nci_thunk_t func;
254
PMC *fb_info;
256
257
func = (nci_thunk_t)D2FPTR(nci_info->func);
258
259
if (!func) {
260
/* build the thunk only when necessary */
261
func = build_func(interp, SELF, nci_info);
264
Parrot_ex_throw_from_c_args(INTERP, NULL,
265
EXCEPTION_INVALID_OPERATION,
266
"attempt to call NULL function");
269
GET_ATTR_fb_info(INTERP, SELF, fb_info);
271
cont = INTERP->current_cont;
Fix for TT #1029. The return continuation was being mangled in the PI…
Jan 5, 2011
272
func(INTERP, SELF, fb_info);
273
274
/*
275
* If the NCI function was tailcalled, the return result
276
* is already passed back to the caller of this frame
277
* - see Parrot_init_ret_nci(). We therefore invoke the
278
* return continuation here, which gets rid of this frame
279
* and returns the real return address
280
*/
281
if (cont && cont != NEED_CONTINUATION
282
&& (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) {
283
cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp));
284
next = VTABLE_invoke(INTERP, cont, next);
285
}
287
return (opcode_t *)next;
Michael Scott
Feb 17, 2004
290
/*
291
292
=item C<INTVAL get_integer()>
293
294
Returns the function pointer as an integer.
295
296
=cut
297
298
*/
299
301
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
302
if (!nci_info->func)
303
build_func(INTERP, SELF, nci_info);
304
return (INTVAL)nci_info->func;
307
/*
308
309
=item C<INTVAL get_bool()>
310
311
Returns the boolean value of the pointer.
312
313
=cut
314
315
*/
316
318
const Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
319
return (0 != (INTVAL)nci_info->orig_func);
320
}
321
326
Return the arity of the NCI (the number of arguments).
332
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
335
if (!nci_info->func)
336
build_func(INTERP, SELF, nci_info);
337
if (nci_info->func) {
338
const INTVAL arity = nci_info->arity;
339
RETURN(INTVAL arity);
343
Parrot_ex_throw_from_c_args(INTERP, NULL,
344
EXCEPTION_INVALID_OPERATION,
345
"You cannot get the arity of an undefined NCI.");
Michael Scott
Feb 17, 2004
348
349
/*
350
351
=back
352
353
=head1 SEE ALSO
354
355
F<docs/pdds/pdd03_calling_conventions.pod>.
Michael Scott
Feb 17, 2004
357
=cut
358
359
*/
360
361
/*
362
* Local variables:
363
* c-file-style: "parrot"
364
* End:
365
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :