=head1 TITLE Calling convention abstraction =head1 ABSTRACT The current Parrot calling conventions as described in F are not covering major parts of our target languages. The scheme isn't extensible and uses a lot of resources (opcodes, runloop dispatches, registers) to achieve it's work. This proposal describes an abstract, extensible, and more efficient alternative to pdd03. =head1 DESCRIPTIOON All the work related to function calls is done by dedicated opcodes. No registers are reserved currently, but during the transition phase and possibly thereafter, registers are/may be used. This will be specified after the implementation of the compatibly scheme is completed. =head2 Opcodes New B opcodes: op args(inconst STR, ...) # call arguments op results(inconst STR, ...) # get return results op params(inconst STR, ...) # function parameters op returns(inconst STR, ...) # function return op yields(inconst STR, ...) # coroutine yield values The constant STR argument is a signature string denoting successional arguments to the opcode. An opcode to define return context: op results(inconst INT) # define return context And: op argcI(out INT) # amount of I args or returns op argcP(out INT) # amount of P op argcS(out INT) # amount of S op argcN(out INT) # amount of N =head2 Call opcodes cleanup While it's not strictly needed it's highly desirable to get rid of the current implicit register usage in call related opcodes. See also: I for an older discussion on that topic. op invoke(in PMC, in PMC) # $1 = sub/method, $2 = continuation op invoke(in STR, in PMC) # invocants are covered by args op invokecc(in PMC) # $1 = sub/meth, create continuation [1] op invokecc(in STR) # invocants are covered by args op tailcall(in PMC) # $1 = sub/method op tailcall(in STR) [1] if the called thing isa NCI PMC the creation of the continuation is skipped. =head2 Signature chars - current calling scheme coverage I ... INTVAL var i ... INTVAL constant N,n,S,s,P,p ... analog O ... single PMC invocant @ ... call: flatten array to next args =head2 Signature chars - possible extensions @ ... call: flatten params/results: make array % ... call: flatten **kw hash params(/results): make hash kX ... call: named arguments (key => X) OO ... call: 2 PMC invocants : ... call: end of invocants marker nX ... params: default arguments (name = X) ? ... params: optional part follows =P ... params/returns: clone P (or maybe cP) & ... ruby code block E.g. args "PP", P10, P20 # function call args "OIS", P5, I10, S30 # method call args "P:IS", P5, I10, S30 # same method call args "P@", P0, P1 # flatten P1, args become P0, *P1 args "%", P2 # P2 is a **kw hash args "kPkP", "$a", P0, "$b", P1 # named arguments "$a" => P0, ... params "ni", "$i", 1 # default argument "$i" = 1 params "P?PPP" # await 1 - 4 arguments passed in =head2 Return context results 0 # void results 1 # 1 return result results n # n return result results -1 # list context As the I opcode goes before the call, we can attach a perlish return context to the return continuation and make it available in the called function. =head2 Simple example .sub main @MAIN args "IN", I16, N16 [1] invokecc "foo" [2] results "I", I16 [3] .end .sub "foo" params "IN", I16, N16 [4] ... returns "I", 1 [5] .end =head2 Comparison with current syntax .sub main @MAIN set I0, 1 [1] set I1, 1 set I2, 0 set I3, 0 set I4, 1 set I5, I16 set N5, N16 set S1, "IN" invokecc "foo" [2] set I16, I5 [3] .end .sub "foo" set I16, I5 [4} set N16, N5 ... set I0, 1 [5] set I1, 1 set I2, 0 set I3, 0 set I4, 0 set I5, 1 returncc .end =head2 opcode and dispatch count comparison current scheme proposed scheme opcodes call/result 29 9 dispatches 10 3 opcodes param/ret 25 7 dispatches 9 2 opcodes overall 54 16 dispatches 19 5 =head2 Example main .sub main @MAIN params "@", P5 # argv array like now params "SS", S0, S1 # at least two string arguments params "S?SS", S0, S1, S2 # 1...3 string arguments params "IS", I20, S2 # 1st param as int, string =head1 Implementation notes =head2 Steps =over 4 =item * The opcodes "translate" their arguments according to the current calling conventions. =item * PIRs call/return syntax shortcuts emit the new opcodes =item * New Parrot API to access call related stuff replaces current explicit register access =item * convert existing PASM code to use new opcodes =back Abstraction finished. =head2 Implementations details: The new opcodes get some support by the ops-file compiler. The basic layout is: op args(inconst STR) { // internal variable declarations // user code VA_SWITCH { // big loop and switch case 'I': i = $N_I; // get Nth arg as INTVAL break; case 'i': i = $N_i; // get Nth arg as INTVAL constant break; case 'P': p = $N_P; // get Nth arg as PMC break; ... } // user code goto NEXT(2+N); } The VA_SWITCH is something like: STRING *sig = $1; // internal variable declaration size_t n, l; char *p; for (n = 0, p = sig->strstart, l = sig->strlen; n < l; ++n, ++p) { switch(*p) { // case statements go here } } The $N_I gets according to the I expanded to something like: IREG(2+n) aka REG_INT(cur_opcode[2+n]) similar to the current $1, $2, ... =head1 AUTHOR Leopold Toetsch =head1 SEE ALSO F