cvsuser 03/11/15 20:31:40
Modified: imcc imc.h imc.c cfg.c parser_util.c pcc.c reg_alloc.c
unit.h
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.56 +32 -2 parrot/imcc/imc.h
Index: imc.h
===================================================================
RCS file: /cvs/public/parrot/imcc/imc.h,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -w -r1.55 -r1.56
--- imc.h 13 Nov 2003 07:03:23 -0000 1.55
+++ imc.h 16 Nov 2003 04:31:39 -0000 1.56
@@ -59,6 +59,7 @@
void imc_close_unit(struct Parrot_Interp *, IMC_Unit *);
void imc_free_unit(struct Parrot_Interp *, IMC_Unit *);
void imc_cleanup(struct Parrot_Interp *);
+void imc_pragma(char * str);
/*
* instructions.c
@@ -88,21 +89,50 @@
int imcc_vfprintf(FILE *fd, const char *format, va_list ap);
int imcc_fprintf(FILE *fd, const char *fmt, ...);
+
+/* Call convention independant API */
+
+/*
+ * sub.c
+ */
+void expand_sub(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void expand_sub_ret(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void expand_sub_call(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void sub_optimize(Parrot_Interp interpreter, IMC_Unit *);
+
+/* Call convention specific implementations (currently 2, FASTSUB and PCCSUB)*/
+
/*
* pcc.c
*/
void expand_pcc_sub(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
-void expand_pcc_sub_call(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
void expand_pcc_sub_ret(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
-void pcc_optimize(Parrot_Interp interpreter, IMC_Unit *);
+void expand_pcc_sub_call(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void pcc_sub_optimize(Parrot_Interp interpreter, IMC_Unit *);
int pcc_sub_reads(Instruction* ins, SymReg* r);
int pcc_sub_writes(Instruction* ins, SymReg* r);
+/*
+ * fastcall.c
+ */
+void expand_fast_sub(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void expand_fast_sub_ret(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void expand_fast_sub_call(Parrot_Interp interpreter, IMC_Unit *, Instruction *ins);
+void fast_sub_optimize(Parrot_Interp interpreter, IMC_Unit *);
+
+
/* globals */
+/* Compiler pragma options that may affect the whole module being compiled */
+struct _imc_pragmas {
+ int fastcall; /* Use low level branch op, pass/return on stack
+ * as opposed to pcc convention and invoke */
+ /* more to come */
+};
+EXTERN struct _imc_pragmas pragmas;
EXTERN char * sourcefile; /* current file */
EXTERN char * function; /* current function */
1.64 +13 -0 parrot/imcc/imc.c
Index: imc.c
===================================================================
RCS file: /cvs/public/parrot/imcc/imc.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -w -r1.63 -r1.64
--- imc.c 13 Nov 2003 07:05:00 -0000 1.63
+++ imc.c 16 Nov 2003 04:31:40 -0000 1.64
@@ -199,6 +199,19 @@
free(unit);
}
+/*
+ * Set a global compiler option. No fancy parsing needed.
+ */
+void
+imc_pragma(char * str)
+{
+#if IMC_TRACE
+ fprintf(stderr, "imc_pragma %s\n", str);
+#endif
+ if(!strcmp(str, "fastcall")) pragmas.fastcall = 1;
+ else return;
+ /* More options here */
+}
/*
1.53 +6 -4 parrot/imcc/cfg.c
Index: cfg.c
===================================================================
RCS file: /cvs/public/parrot/imcc/cfg.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -w -r1.52 -r1.53
--- cfg.c 13 Nov 2003 07:05:00 -0000 1.52
+++ cfg.c 16 Nov 2003 04:31:40 -0000 1.53
@@ -75,11 +75,12 @@
}
}
+ /* XXX FIXME: Now the way to check for a sub is unit->type */
ins = unit->instructions;
if (first && ins->type == ITLABEL && ins->r[1]) {
debug(interpreter, DEBUG_CFG, "pcc_sub %s nparams %d\n",
ins->r[0]->name, ins->r[1]->pcc_sub->nargs);
- expand_pcc_sub(interpreter, unit, ins);
+ expand_sub(interpreter, unit, ins);
}
ins->index = i = 0;
@@ -114,13 +115,14 @@
}
if (ins->opnum == -1 && (ins->type & ITPCCSUB)) {
if (first) {
+ /* XXX FIXME: Now the way to check for a sub is unit->type */
if (ins->type & ITLABEL) {
- expand_pcc_sub_ret(interpreter, unit, ins);
+ expand_sub_ret(interpreter, unit, ins);
ins->type &= ~ITLABEL;
}
else {
- /* if this is a pcc_sub_call expand it */
- expand_pcc_sub_call(interpreter, unit, ins);
+ /* if this is a sub call expand it */
+ expand_sub_call(interpreter, unit, ins);
}
ins->type &= ~ITPCCSUB;
}
1.48 +6 -1 parrot/imcc/parser_util.c
Index: parser_util.c
===================================================================
RCS file: /cvs/public/parrot/imcc/parser_util.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -w -r1.47 -r1.48
--- parser_util.c 13 Nov 2003 07:05:00 -0000 1.47
+++ parser_util.c 16 Nov 2003 04:31:40 -0000 1.48
@@ -199,6 +199,9 @@
return k;
}
+/*
+ * Return opcode value for op name
+ */
int
check_op(struct Parrot_Interp *interpreter, char *fullname,
char *name, SymReg *r[], int narg, int keyvec)
@@ -208,9 +211,11 @@
op_fullname(fullname, name, r, narg, keyvec);
op = interpreter->op_lib->op_code(fullname, 1);
return op;
-
}
+/*
+ * Is instruction a parrot opcode?
+ */
int
is_op(struct Parrot_Interp *interpreter, char *name)
{
1.32 +82 -10 parrot/imcc/pcc.c
Index: pcc.c
===================================================================
RCS file: /cvs/public/parrot/imcc/pcc.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -w -r1.31 -r1.32
--- pcc.c 4 Nov 2003 07:47:27 -0000 1.31
+++ pcc.c 16 Nov 2003 04:31:40 -0000 1.32
@@ -1,16 +1,37 @@
+/*
+ * pcc.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)
+ *
+ * see: docs/pdds/pdd03_calling_conventions.pod
+ *
+ * PCC Implementation by Leopold Toetsch
+ */
+
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "imc.h"
#include "parser.h"
+
/*
- * pcc.c - parrot calling conventions stuff
- *
- * s. docs/pdds/pdd03_calling_conventions.pod
- *
+ * 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)
@@ -183,6 +204,12 @@
return ins;
}
+
+/*
+ * Expand a PCC (Parrot Calling Convention) subroutine
+ * by generating the appropriate prologue and epilogue
+ * for parameter passing/returning.
+ */
void
expand_pcc_sub(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins)
{
@@ -194,7 +221,18 @@
SymReg *p3, *i0, *regs[IMCC_MAX_REGS], *label1, *label2;
char buf[128];
+#if IMC_TRACE
+ PIO_eprintf("expand_pcc_sub\n");
+#endif
+
sub = ins->r[1];
+
+ /* Don't generate any parameter checking code if there
+ * are no named arguments.
+ */
+ if(sub->pcc_sub->nargs <= 0)
+ goto NONAMEDPARAMS;
+
p3 = i0 = NULL;
label1 = label2 = NULL;
ps = pe = sub->pcc_sub->prototyped;
@@ -231,9 +269,9 @@
ins, sub, i0, NULL, i == 0, 0);
/* assign register to that param
*
- * if this subroutine calls another one,
- * new registers are ssigned, so that
- * they don't interfer with this subs params
+ * if this subroutine calls another subroutine
+ * new registers are assigned so that
+ * they don't interfer with this sub's params
*/
if (sub->pcc_sub->calls_a_sub) {
regs[0] = arg;
@@ -301,6 +339,8 @@
}
} /* proto */
+NONAMEDPARAMS: /* If no named params, don't generate any param code */
+
/*
* if we call out, the return cc in P1 must be saved
*/
@@ -311,6 +351,10 @@
}
}
+
+/*
+ * Expand a PCC sub return directive into its PASM instructions
+ */
void
expand_pcc_sub_ret(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins)
{
@@ -321,6 +365,10 @@
char buf[128];
int n_p3;
+#if IMC_TRACE
+ PIO_eprintf("expand_pcc_sub_ret\n");
+#endif
+
arg_count = ins->type & ITPCCYIELD ? 0 : 1;
for (i = 0; i < 4; i++)
next[i] = 5;
@@ -671,6 +719,11 @@
return ins;
}
+
+/*
+ * Expand a PCC subroutine call (IMC) into its PASM instructions
+ * This is the nuts and bolts of Perl6/Parrot routine call style
+ */
void
expand_pcc_sub_call(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins)
{
@@ -685,6 +738,10 @@
int tail_call;
int flatten;
+#if IMC_TRACE
+ PIO_eprintf("expand_pcc_sub_call\n");
+#endif
+
tail_call = check_tail_call(interpreter, unit, ins);
if (tail_call)
debug(interpreter, DEBUG_OPT1, "found tail call %I \n", ins);
@@ -982,15 +1039,16 @@
break;
}
}
+
/*
* special peephole optimizer for code generated mainly by
* above functions
*/
void
-pcc_optimize(Parrot_Interp interpreter, IMC_Unit * unit)
+pcc_sub_optimize(Parrot_Interp interpreter, IMC_Unit * unit)
{
Instruction *ins, *tmp;
- info(interpreter, 2, "\tpcc_optimize\n");
+ info(interpreter, 2, "\tpcc_sub_optimize\n");
for (ins = unit->instructions; ins; ins = ins->next) {
if (ins->opsize == 3 &&
ins->r[1]->type == VTCONST &&
@@ -1033,6 +1091,10 @@
}
}
+/*
+ * Check argument symbols of a sub and see which are used
+ * Return 0 if none are used, 1 if at least 1 symbol is used.
+ */
static int
pcc_args(Instruction* ins, SymReg* r)
{
@@ -1049,6 +1111,10 @@
return 0;
}
+/*
+ * Check return symbols of a sub and see which are used
+ * Return 0 if none are used, 1 if at least 1 symbol is used.
+ */
static int
pcc_ret(Instruction* ins, SymReg* r)
{
@@ -1065,6 +1131,9 @@
return 0;
}
+/*
+ * See if the sub writes to the symbol, checks args and returns
+ */
int
pcc_sub_writes(Instruction* ins, SymReg* r)
{
@@ -1073,6 +1142,9 @@
return pcc_ret(ins, r) || pcc_args(ins, r);
}
+/*
+ * See if the sub reads the symbol, checks args and returns
+ */
int
pcc_sub_reads(Instruction* ins, SymReg* r)
{
1.4 +1 -1 parrot/imcc/reg_alloc.c
Index: reg_alloc.c
===================================================================
RCS file: /cvs/public/parrot/imcc/reg_alloc.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -w -r1.3 -r1.4
--- reg_alloc.c 13 Nov 2003 07:05:00 -0000 1.3
+++ reg_alloc.c 16 Nov 2003 04:31:40 -0000 1.4
@@ -175,7 +175,7 @@
}
}
if (optimizer_level & OPT_SUB)
- pcc_optimize(interpreter, unit);
+ sub_optimize(interpreter, unit);
if (IMCC_INFO(interpreter)->debug & DEBUG_IMC)
dump_instructions(unit);
if (IMCC_INFO(interpreter)->verbose ||
1.5 +3 -2 parrot/imcc/unit.h
Index: unit.h
===================================================================
RCS file: /cvs/public/parrot/imcc/unit.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -w -r1.4 -r1.5
--- unit.h 13 Nov 2003 07:03:23 -0000 1.4
+++ unit.h 16 Nov 2003 04:31:40 -0000 1.5
@@ -11,8 +11,9 @@
typedef enum {
IMC_PASM = 0,
- IMC_SUB = 1,
- IMC_CLASS = 2
+ IMC_PCCSUB = 1,
+ IMC_FASTSUB = 2,
+ IMC_CLASS = 3
} IMC_Unit_Type;