cvsuser 03/11/15 20:28:10
Added: imcc sub.c fastcall.c
Log:
More IMCC rearchitecture.
* .sub directive now deprecates .pcc_sub directive.
.sub now uses PCC convention by default.
* All other .pcc directives are still used but will
be eventually deprecated.
* Modularize calling conventions and add generic API.
sub.c is the generic API and wraps pcc.c and fastcall.c
* Add stubs for a 2nd FASTCALL convention which can be enabled by
compiler pragma. Currently fastcall does not work.
* Add .pragma directive to the lexer.
* Add check for 0 arguments in PCC subs to skip code generate for proto/nonproto
argument checking if there are no args. (Leo check this if it is the right
thing to do?)
* Various comments and optional tracing added to existing code.
Revision Changes Path
1.1 parrot/imcc/sub.c
Index: sub.c
===================================================================
/*
* sub.c
*
* Calling Conventions API for generating subs definitions, calls, etc.
*
* Called by the code generators, optimizers and flow graph code which
* are mostly independant of the low-level call conventions.
*
* Depending on compiler pragmas this API will callout to one of several
* supported code generators. (see pcc.c or fastcall.c)
*
* The default is PCC (prototyped and non-prototyped).
* PCC (Parrot Calling Convention) is the default for Perl6 and other
* languages that want to interface with Perl6 on Parrot. PCC works
* well with continuations and co-routines.
*
* Plans are for a FASTCALL convention which can be enabled with:
* .pragma fastcall
* which will allow library developers (or non-Perl languages) to turn
* on very efficient calling conventions. It could also be used for internal
* libs that do not callout to PCC routines, but present PCC entry points
* for the module itself.
*
* Currently the only fully functional convention is PCC but the generic
* API allows us to experiment with calling conventions side by
* side without completely breaking IMCC everytime we tweak something.
* The side effect is the subroutine code generators and optimizers can be
* very modular and less interlocked to a specific convention.
*
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "imc.h"
#include "parser.h"
/*
* Expand a subroutine definition depending on the active
* calling convention. (FAST or PCC)
*/
void
expand_sub(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
/* IMC_FASTSUB */
#if IMC_TRACE
PIO_eprintf("expand_sub\n");
#endif
/* For expand sub, we check the unit->type only, since the
* pragma might be overridden.
*/
if(pragmas.fastcall) {
expand_fast_sub(interp, unit, ins);
}
/* IMC_PCCSUB */
else {
expand_pcc_sub(interp, unit, ins);
}
}
/*
* Expand return instructions depending on active
* calling convention (FAST or PCC).
*/
void
expand_sub_ret(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
#if IMC_TRACE
PIO_eprintf("expand_sub_ret\n");
#endif
/* IMC_FASTSUB */
if(pragmas.fastcall) {
expand_fast_sub_ret(interp, unit, ins);
}
/* IMC_PCCSUB */
else {
expand_pcc_sub_ret(interp, unit, ins);
}
}
/*
* Expand a sub call depending on active calling convention.
* (FAST or PCC).
*/
void
expand_sub_call(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
#if IMC_TRACE
PIO_eprintf("expand_sub_call\n");
#endif
/* IMC_FASTSUB */
if(pragmas.fastcall) {
expand_fast_sub_call(interp, unit, ins);
}
/* IMC_PCCSUB */
else {
expand_pcc_sub_call(interp, unit, ins);
}
}
/*
* Peephole optimizer for subroutine Unit depending on its calling convention.
* Currently the same optimizer works for both.
*/
void
sub_optimize(Parrot_Interp interp, IMC_Unit * unit)
{
/* IMC_FASTSUB */
if(pragmas.fastcall) {
pcc_sub_optimize(interp, unit);
}
/* IMC_PCCSUB */
else {
pcc_sub_optimize(interp, unit);
}
}
1.1 parrot/imcc/fastcall.c
Index: fastcall.c
===================================================================
/*
* fastcall.c
*
* A specific call convention implementation. Called by the generic
* API for subs (see sub.c).
*
* FASTCALL convention can be enabled with:
* .pragma fastcall
* at the start of an IMC module.
*
* This will allow library developers (or non-Perl languages) to turn
* on very efficient optimizations and a lightweight calling convention.
* It could also be used for internal libs that do not callout to PCC
* routines, but present PCC entry points for the module itself.
*
* XXX FIXME: FASTCALL is not currently finished and may not be completely
* compatible with PCC convention. (ie. you can't mix and match, for now at least)
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "imc.h"
#include "parser.h"
/* XXX FIXME: This call convention is not finished, so using
* .pragma fastcall will cause IMCC to exit.
*/
/*
* Utilty instruction routine. Creates and inserts an instruction
* into the current block in one call.
*/
static Instruction *
insINS(struct Parrot_Interp *interpreter, IMC_Unit * unit, Instruction *ins,
char *name, SymReg **regs, int n)
{
Instruction *tmp = INS(interpreter, unit, name, NULL, regs, n, 0, 0);
insert_ins(unit, ins, tmp);
return tmp;
}
/*
* XXX Unimplemented. (Proof of concept only)
*
* Expand a FASTCALL sub, whatever that happens to be. Currently
* it means passing and returning arguments on the stack
* Enabled by .pragma fastcall
*/
void
expand_fast_sub(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
SymReg *arg, *sub, *regs[IMCC_MAX_REGS];
int i, n;
#if IMC_TRACE
PIO_eprintf("expand_fast_sub\n");
#endif
sub = ins->r[1];
n = sub->pcc_sub->nargs;
for (i = 0; i < n; i++) {
regs[0] = arg = sub->pcc_sub->args[i];
ins = insINS(interp, unit, ins, "restore", regs, 1);
}
}
/*
* XXX Unimplemented. (Proof of concept only)
*/
void
expand_fast_sub_ret(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
SymReg *sub, *ret, *regs[IMCC_MAX_REGS];
int i;
#if IMC_TRACE
PIO_eprintf("expand_fast_sub_ret\n");
#endif
sub = ins->r[1];
for (i = 0; i < sub->pcc_sub->nret; i++) {
regs[0] = ret = sub->pcc_sub->ret[i];
ins = insINS(interp, unit, ins, "save", regs, 1);
}
}
/*
* XXX Unimplemented. (Proof of concept only)
* Currently not compatible with .pcc_call since .pcc_call
* uses an identifier (not a label) as its argument.
* We need to hide the call implementation and have each call convention
* generate necessary code.
*/
void
expand_fast_sub_call(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
{
SymReg *sub, *ret, *arg, *regs[IMCC_MAX_REGS];
int i;
#if IMC_TRACE
PIO_eprintf("expand_fast_sub_call\n");
#endif
sub = ins->r[0];
for(i = 0; i < sub->pcc_sub->nargs; i++) {
regs[0] = arg = sub->pcc_sub->args[i];
ins = insINS(interp, unit, ins, "save", regs, 1);
}
regs[0] = sub->pcc_sub->sub;
ins = insINS(interp, unit, ins, "bsr", regs, 1);
/* XXX: Only supports prototyped subs for now */
for(i = 0; i < sub->pcc_sub->nret; i++) {
ret = sub->pcc_sub->ret[i];
regs[0] = mk_temp_reg(ret->set);
ins = insINS(interp, unit, ins, "restore", regs, 1);
}
}