1 /*
2 Copyright (C) 2001-2014, Parrot Foundation.
3
4 =head1 NAME
5
6 src/call/pcc.c
7
8 =head1 DESCRIPTION
9
10 B<Parrot Calling Conventions>: Functions in this file handle argument/return
11 value passing to and from subroutines.
12
13 =head1 FUNCTIONS
14
15 =over 4
16
17 =cut
18
19 */
20
21 #include "parrot/parrot.h"
22 #include "parrot/runcore_api.h"
23 #include "parrot/oplib/ops.h"
24 #include "pcc.str"
25 #include "pmc/pmc_key.h"
26 #include "pmc/pmc_continuation.h"
27 #include "pmc/pmc_callcontext.h"
28
29 /* HEADERIZER HFILE: include/parrot/call.h */
30
31 /* HEADERIZER BEGIN: static */
32 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
33
34 static int do_run_ops(PARROT_INTERP, ARGIN(PMC *sub_obj))
35 __attribute__nonnull__(1)
36 __attribute__nonnull__(2);
37
38 PARROT_INLINE
39 PARROT_WARN_UNUSED_RESULT
40 static int is_invokable(PARROT_INTERP, ARGIN(PMC *sub_obj))
41 __attribute__nonnull__(1)
42 __attribute__nonnull__(2);
43
44 #define ASSERT_ARGS_do_run_ops __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
45 PARROT_ASSERT_ARG(interp) \
46 , PARROT_ASSERT_ARG(sub_obj))
47 #define ASSERT_ARGS_is_invokable __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
48 PARROT_ASSERT_ARG(interp) \
49 , PARROT_ASSERT_ARG(sub_obj))
50 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
51 /* HEADERIZER END: static */
52
53
54 /*
55
56 =item C<void Parrot_pcc_invoke_sub_from_c_args(PARROT_INTERP, PMC *sub_obj,
57 const char *sig, ...)>
58
59 C<pmc> is the invocant.
60
61 C<sub_obj> is the sub to invoke.
62
63 C<sig> is the signature.
64
65 Variable args contains the IN arguments followed by the OUT results variables.
66 You must pass the address_of(&) the OUT results, of course.
67
68
69 Signatures:
70 uppercase letters represent each arg and denote its types
71
72 I INTVAL
73 N FLOATVAL
74 S STRING *
75 P PMC *
76
77 lowercase letters are adverb modifiers to the preceding uppercase arg
78 identifier
79
80 f flatten
81 n named
82 s slurpy
83 o optional
84 p opt flag
85 l lookahead parameter (next positional, or next named if no positionals)
86 i invocant
87
88 -> is the separator between args and results, similar to type theory
89 notation.
90
91 Named args require two arg slots. The first is the name, the second the arg.
92
93 Example signature:
94
95 "SnIPf->INPs"
96
97 The args to the method invocation are
98 a named INTVAL: SnI
99 a flattened PMC: Pf
100
101 The results of the method invocation are
102 a INTVAL: I
103 a FLOATVAL: N
104 a slurpy PMC: Ps
105
106
107 =cut
108
109 */
110
111 PARROT_EXPORT
112 void
Parrot_pcc_invoke_sub_from_c_args(PARROT_INTERP,ARGIN (PMC * sub_obj),ARGIN (const char * sig),...)113 Parrot_pcc_invoke_sub_from_c_args(PARROT_INTERP, ARGIN(PMC *sub_obj),
114 ARGIN(const char *sig), ...)
115 {
116 ASSERT_ARGS(Parrot_pcc_invoke_sub_from_c_args)
117 PMC *call_obj;
118 va_list args;
119 const char *arg_sig, *ret_sig;
120 PMC * const old_call_obj =
121 Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
122
123 Parrot_pcc_split_signature_string(sig, &arg_sig, &ret_sig);
124
125 va_start(args, sig);
126 call_obj = Parrot_pcc_build_call_from_varargs(interp, PMCNULL,
127 arg_sig, &args);
128 Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), call_obj);
129 Parrot_pcc_invoke_from_sig_object(interp, sub_obj, call_obj);
130 call_obj = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
131 Parrot_pcc_fill_params_from_varargs(interp, call_obj, ret_sig, &args,
132 PARROT_ERRORS_RESULT_COUNT_FLAG);
133 va_end(args);
134 Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_call_obj);
135 }
136
137 /*
138
139 =item C<void Parrot_pcc_invoke_method_from_c_args(PARROT_INTERP, PMC* pmc,
140 STRING *method_name, const char *signature, ...)>
141
142 Makes a method call given the name of the method and the arguments as a C
143 variadic argument list. C<pmc> is the invocant, C<method_name> is the string
144 name of the method, C<signature> is a C string describing the signature of the
145 invocation, according to the Parrot calling conventions. The variadic argument
146 list contains the input arguments followed by the output results in the same
147 order that they appear in the function signature.
148
149 =cut
150
151 */
152
153 PARROT_EXPORT
154 void
Parrot_pcc_invoke_method_from_c_args(PARROT_INTERP,ARGIN (PMC * pmc),ARGMOD (STRING * method_name),ARGIN (const char * signature),...)155 Parrot_pcc_invoke_method_from_c_args(PARROT_INTERP, ARGIN(PMC* pmc),
156 ARGMOD(STRING *method_name),
157 ARGIN(const char *signature), ...)
158 {
159 ASSERT_ARGS(Parrot_pcc_invoke_method_from_c_args)
160 PMC *call_obj;
161 PMC *sub_obj;
162 va_list args;
163 const char *arg_sig, *ret_sig;
164 PMC *arg_flags;
165 PMC * const old_call_obj =
166 Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
167
168 Parrot_pcc_split_signature_string(signature, &arg_sig, &ret_sig);
169
170 va_start(args, signature);
171 call_obj = Parrot_pcc_build_call_from_varargs(interp, PMCNULL, arg_sig, &args);
172
173 /* inlined version of pcc_add_invocant */
174 arg_flags = PARROT_CALLCONTEXT(call_obj)->arg_flags;
175 VTABLE_unshift_integer(interp, arg_flags, PARROT_ARG_PMC | PARROT_ARG_INVOCANT);
176 Parrot_CallContext_unshift_pmc(interp, call_obj, pmc);
177
178 Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), call_obj);
179
180 /* Find the subroutine object as a named method on pmc */
181 sub_obj = VTABLE_find_method(interp, pmc, method_name);
182
183 if (UNLIKELY(PMC_IS_NULL(sub_obj)))
184 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_METHOD_NOT_FOUND,
185 "Method '%Ss' not found", method_name);
186
187 /* Invoke the subroutine object with the given CallContext object */
188 Parrot_pcc_invoke_from_sig_object(interp, sub_obj, call_obj);
189 call_obj = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
190 Parrot_pcc_fill_params_from_varargs(interp, call_obj, ret_sig, &args,
191 PARROT_ERRORS_RESULT_COUNT_FLAG);
192 va_end(args);
193 Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_call_obj);
194 }
195
196
197 /*
198
199 =item C<static int is_invokable(PARROT_INTERP, PMC *sub_obj)>
200
201 Check if the PMC is a Sub or does invokable. Helper for do_run_ops.
202
203 =cut
204
205 */
206
207 PARROT_INLINE
208 PARROT_WARN_UNUSED_RESULT
209 static int
is_invokable(PARROT_INTERP,ARGIN (PMC * sub_obj))210 is_invokable(PARROT_INTERP, ARGIN(PMC *sub_obj))
211 {
212 ASSERT_ARGS(is_invokable)
213
214 if (VTABLE_isa(interp, sub_obj, CONST_STRING(interp, "Sub")))
215 return 1;
216 else
217 return VTABLE_does(interp, sub_obj, CONST_STRING(interp, "invokable"));
218 }
219
220 /*
221
222 =item C<static int do_run_ops(PARROT_INTERP, PMC *sub_obj)>
223
224 Check should we run ops.
225
226 PIR Subs need runops to run their opcodes. Methods and NCI subs don't.
227
228 =cut
229
230 */
231
232 static int
do_run_ops(PARROT_INTERP,ARGIN (PMC * sub_obj))233 do_run_ops(PARROT_INTERP, ARGIN(PMC *sub_obj))
234 {
235 ASSERT_ARGS(do_run_ops)
236
237 if (sub_obj->vtable->base_type < enum_class_core_max) {
238 switch (sub_obj->vtable->base_type) {
239 case enum_class_Sub:
240 case enum_class_MultiSub:
241 case enum_class_Continuation:
242 return 1;
243 case enum_class_Object:
244 break;
245 default:
246 return 0;
247 }
248 }
249 return is_invokable(interp, sub_obj);
250 }
251
252 /*
253
254 =item C<INTVAL Parrot_pcc_do_run_ops(PARROT_INTERP, PMC *sub_obj)>
255
256 Check if current object require running ops.
257
258 =cut
259
260 */
261 PARROT_EXPORT
262 INTVAL
Parrot_pcc_do_run_ops(PARROT_INTERP,ARGIN (PMC * sub_obj))263 Parrot_pcc_do_run_ops(PARROT_INTERP, ARGIN(PMC *sub_obj))
264 {
265 ASSERT_ARGS(Parrot_pcc_do_run_ops)
266 return do_run_ops(interp, sub_obj);
267 }
268
269 /*
270
271 =item C<void Parrot_pcc_invoke_from_sig_object(PARROT_INTERP, PMC *sub_obj, PMC
272 *call_object)>
273
274 Follows the same conventions as C<Parrot_pcc_invoke_method_from_c_args>, but
275 the signature string and call arguments are passed in a CallSignature PMC.
276
277 =cut
278
279 */
280
281 PARROT_EXPORT
282 void
Parrot_pcc_invoke_from_sig_object(PARROT_INTERP,ARGIN (PMC * sub_obj),ARGIN (PMC * call_object))283 Parrot_pcc_invoke_from_sig_object(PARROT_INTERP, ARGIN(PMC *sub_obj),
284 ARGIN(PMC *call_object))
285 {
286 ASSERT_ARGS(Parrot_pcc_invoke_from_sig_object)
287
288 opcode_t *dest;
289 PMC * const ret_cont = Parrot_pmc_new(interp, enum_class_Continuation);
290 if (UNLIKELY(PMC_IS_NULL(call_object)))
291 call_object = Parrot_pmc_new(interp, enum_class_CallContext);
292
293 Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), call_object);
294 PARROT_CONTINUATION(ret_cont)->from_ctx = call_object;
295 Parrot_pcc_set_continuation(interp, call_object, ret_cont);
296 interp->current_cont = ret_cont;
297
298 /* Invoke the function */
299 dest = VTABLE_invoke(interp, sub_obj, NULL);
300
301 /* PIR Subs need runops to run their opcodes. Methods and NCI subs
302 * don't. */
303 if (dest && do_run_ops(interp, sub_obj)) {
304 Parrot_runcore_t * const old_core = interp->run_core;
305 const opcode_t offset = dest - interp->code->base.data;
306
307 runops(interp, offset);
308 Interp_core_SET(interp, old_core);
309 }
310 }
311
312 /*
313
314 =item C<PMC * Parrot_pcc_new_call_object(PARROT_INTERP)>
315
316 Returns a new CallContext object, suitable for making a Sub call.
317
318 =cut
319
320 */
321
322 PARROT_EXPORT
323 PARROT_CANNOT_RETURN_NULL
324 PARROT_WARN_UNUSED_RESULT
325 PMC *
Parrot_pcc_new_call_object(PARROT_INTERP)326 Parrot_pcc_new_call_object(PARROT_INTERP)
327 {
328 ASSERT_ARGS(Parrot_pcc_new_call_object)
329 return Parrot_pmc_new(interp, enum_class_CallContext);
330 }
331
332 /*
333
334 =back
335
336 =head1 SEE ALSO
337
338 F<include/parrot/interpreter.h>, F<src/call/ops.c>, F<src/pmc/sub.pmc>.
339
340 =cut
341
342 */
343
344 /*
345 * Local variables:
346 * c-file-style: "parrot"
347 * End:
348 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
349 */
350