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