NAME
docs/pdds/pdd03_calling_conventions.pod - Parrot Calling Conventions
ABSTRACT
This PDD describes Parrot's inter-routine calling conventions.
AND NOW FOR SOMETHING COMPLETELY DIFFERENT
This document's current contents are a complete change of direction from the original direction of Parrot design. Brand new and/or improved! Share and enjoy!
DESCRIPTION
This document describes how to pass arguments from registers to subroutines, and how subroutines can extract their parameters into registers for use.
Since Parrot's calling conventions are continuation-based, there is arguably very little difference between a call and a return. Because of this, the conversion rules are the same regardless of whether code is invoking a subroutine or a return continuation.
Common Features of Argument/Return Opcodes
XXX FIXME: PIR should have pretty syntactical sugar around this, but it doesn't. Document here what it should look like.
There are four opcodes involved in parameter and return value propagation:
set_args
, for passing arguments;set_returns
, for returning values;get_params
, for accepting parameters; andget_results
, for accepting return values.
The common syntax of these opcodes is:
<set_opcode> "(flags0, flags1, ..., flagsN)", VAL0, VAL1, ... VALN
<get_opcode> "(flags0, flags1, ..., flagsN)", REG0, REG1, ... REGN
The flags string is a literal quoted string denoting a list of zero or more comma-separated integers. The list as a whole may be surrounded by parentheses. Integers may be specified either in decimal, or if prefixed with "0b"/"0x", in binary/hexadecimal. There must be exactly one integer for each value or register given.
Flag Words; Common Flag Word Bits
Each integer in the flag string controls the processing of the corresponding value or register.
These bits of each flag word have common meanings for all argument/ return-value opcodes:
0b0011 TYPE
0b00 = I
0b01 = S
0b10 = P
0b11 = N
You can just set these bits (as well as the CONSTANT bit below) to zero as the assembler calculates the correct setting depending on the given arguments.
Passing Arguments, Returning Values
Just before calling a subroutine with invokecc
or calling a method with <call_methodcc>, use the set_args
opcode to tell Parrot where the subroutine's or method's arguments will come from and how they should be expanded by the target.
Similarly, just before returning from such a subroutine or method, use the set_returns
opcode to tell Parrot where the return values will come from and how to expand them for the caller's use.
Flag Word Bits For 'Setting'
These bits of each flag word have these meanings specific to set_args
and set_returns
:
0b00100 CONSTANT
the value is a literal constant, not a register
(also set by the assembler, if a onstant is given)
0b01000 FLATTEN
If this bit is set on a PMC value, then the PMC must
be an aggregate or a scalar containing a reference to
an aggregate. The contents of the aggregate, rather
than the aggregate itself, will be passed.
The meaning of this bit is undefined when applied to
integer, number, and string values.
0b10000 MAY_FLATTEN
If this bit is set on a PMC value, and the PMC is
an aggregate or a scalar containing a reference to
an aggregate, _and_ when the called function has a
slurpy flag on the corresponding parameter, then
the content of this aggregate is flattened.
0b100000 OPTIONAL
Optional arguments are not considered in an
argument count mismatch.
0b1000000 OPT_FLAG
A INT argument with this bit set receives a bit 1/0,
if the preceeding I<OPTIONAL> was passed or not.
0b000000000
INVOCANT
INVOCANT2
0b000000000
NAMED
0b000000000
LEXICAL
0b000000000
COPY
0b000000000
WRITABLE
Accepting Parameters, Accepting Return Values
As the first opcode in a subroutine that will be called with invokecc
or a method that will be called with <call_methodcc>, use the get_params
opcode to tell Parrot where the subroutine's or method's arguments should be stored and how they should be expanded.
Similarly, just before (yes, before) calling such a subroutine or method, use the get_results
opcode to tell Parrot where the return values should be stored and how to expand them for your use.
NOTE: It should be obvious, but in case it's not: You must name only registers as targets of these opcodes, not constants. (You can't store anything into a constant. That would make it a variable.)
Flag Word Bits For 'Getting'
These bits of each flag word have these meanings specific to get_params
and get_results
:
0b1000 FLATTEN
If this bit is set on a PMC register, then the PMC
will be populated with an aggregate (e.g. Array)
that will contain all of the remaining values that
have not already been stored in other registers.
All such values will be converted to PMCs according
to the detailed rules below, and those PMCs will be
stored into the new aggregate.
The meaning of this bit is undefined when applied to
integer, number, and string registers.
Overflow
If too many values are provided to fit into the given target registers, Parrot will throw an exception. Note that if the final target is a P register with the FLATTEN flag bit, then this exception can never occur.
XXX - FIXME - which exception? We really could use an exception subsystem. Oh, wait, that's my job. Never mind. --Chip
Underflow
If too few values are provided so that some target registers are left unset, this too results in an exception.
Type Conversions
Unlike the set_*
opcodes, the get_*
opcodes must perform conversion from one register type to another. Here are the conversion rules:
When the target is an I, N, or S register, storage will behave like an
assign
(standard conversion).When the target and source are both P registers, storage will behave like a
set
(pass by reference).When the target is a P register and the source is an integer, the P will be set to a new .Integer which has been
assign
ed the given integer.When the target is a P register and the source is a number, the P will be set to a new .Float which has been
assign
ed the given number.When the target is a P register and the source is a string, the P will be set to a new .String which has been
assign
ed the given string.
BUGS
Required features are missing:
Type checking
Default values
Optional parameters
Named parameters
Specific exceptions to throw for specific errors.
Also, PIR should have pretty syntactical sugar around the get and set opcodes, but it doesn't. This document should specify what that looks like, too.
REFERENCES
None.
VERSION
2.0
CURRENT
Maintainer: Chip Salzenberg
Class: Internals
PDD Number: 03
Version: 2.0
Status: Overhauled
Last Modified: 13 June 2005
PDD Format: 1
Language: English
HISTORY
- Version 2.0
-
13 June 2005
- Version 1.4
-
17 November 2003
- Version 1.3
-
2 May 2003
- Version 1,2
-
11 March 2003
- Version 1.1
-
16 September 2002
- version 1
-
None. First version
CHANGES
- Version 2.0
-
Meet the new boss, definitely not the same as the old boss. All the register-window fixed-register-number ideas are gone. In their place are specialized conversion opcodes.
- Version 1.4
-
Unified call and return, tossed useless stuff
- Version 1.3
-
No longer use the stack, with overflow going into the array in P3.
Clarified some muddy language.
- Version 1.2
-
Dropped the number of registers passed in and out of subs.
- Version 1.1
-
We now call with a frame, rather than pushing on the stack, and we return frames, rather than returning a stack. We also pass in context information for the return.
- Version 1.0
-
None. First version