Leopold Toetsch wrote:
2. Proposal for _keyed opcodes ------------------------------The thread with subject "pdd06_pasm, pdd08_keys: _keyed ops" clearly showes the shortcomings of the current _keyed opcodes and the implementation of these.[1]
The 3 operand keyed add @a[$i] = @b[3] + %h{"k"}:
add_p_ki_p_kic_p_kc
Attached is a proof of concept of my proposal.
A 6 operand 3 keyed op get's rewritten like so:
/* OP _p_k _p_k_p_k =>
* set py, p_k
* set pz, p_k
* new px, .PerlUndef
* OP px, py, pz
* set _p_k_px
*/
- It uses only set_ ops
- only imcc, but with pasm syntax in example
With an approach like this, we could cut down the VTABLE to roughly 1/3 of it's current size. The _keyed entrys would only consist of the set_.._keyed{,_int} variants plus exists_keyed and defined_keyed. And, we would never have the opcode explosion to 64 times of current size.
Attached is
- patch to imcc.y
- 3key.imc (example)
- a.pasm (output for above)
$ parrot a.pbc
300
leo
--- parrot/languages/imcc/imcc.y Mon Oct 21 13:56:24 2002
+++ parrot-leo/languages/imcc/imcc.y Mon Oct 21 17:34:18 2002
@@ -240,6 +240,100 @@
}
+static Instruction *
+multi_keyed(char *name, SymReg ** regs, int nr, int emit)
+{
+ int i, keys, kv, n;
+ char buf[16];
+ static int p = 0;
+ SymReg *preg[IMCC_MAX_REGS]; /* px,py,pz */
+ SymReg *nreg[IMCC_MAX_REGS];
+ Instruction * ins, *last;
+
+ /* count keys in keyvec */
+ kv = keyvec;
+ for (i = keys = 0; i < nr; i++, kv >>= 1)
+ if (kv & 1)
+ keys++;
+ if (keys <= 1)
+ return 0;
+ /* XXX what to do, if we don't emit instruction? */
+ assert(emit);
+ /* OP _p_k _p_k_p_k =>
+ * set py, p_k
+ * set pz, p_k
+ * new px, .PerlUndef
+ * OP px, py, pz
+ * set _p_k_px
+ */
+
+ kv = keyvec;
+ for (i = n = 0; i < nr; i++, kv >>= 1, n++) {
+ if (kv & 1) {
+ fataly(EX_SOFTWARE, "multi_keyed", line,"illegal key operand\n");
+ }
+ /* make a new P symbol */
+ while (1) {
+ sprintf(buf, "$P%d", ++p);
+ if (get_sym(buf) == 0)
+ break;
+ }
+ preg[n] = mk_symreg(buf, 'P');
+ kv >>= 1;
+ if (kv & 1) {
+ /* we have a keyed operand */
+ if (regs[i]->set != 'P') {
+ fataly(EX_SOFTWARE, "multi_keyed", line,"not an aggregate\n");
+ }
+ nargs = 3;
+ /* don't emit LHS yet */
+ if (i == 0) {
+ keyvec = 1 << 1;
+ nreg[0] = regs[i];
+ nreg[1] = regs[i+1];
+ nreg[2] = preg[n];
+ /* set p_k px */
+ ins = iANY(str_dup("set"), 0, nreg, 0);
+ }
+ else {
+ keyvec = 1 << 2;
+ nreg[0] = preg[n];
+ nreg[1] = regs[i];
+ nreg[2] = regs[i+1];
+ /* set py|z p_k */
+ iANY(str_dup("set"), 0, nreg, 1);
+ }
+ i++;
+ }
+ /* non keyed */
+ else {
+ nargs = 2;
+ keyvec = 0;
+ if (i == 0) {
+ nreg[0] = regs[i];
+ nreg[1] = preg[n];
+ /* set n, px */
+ ins = iANY(str_dup("set"), 0, nreg, 0);
+ }
+ else {
+ nreg[0] = preg[n];
+ nreg[1] = regs[i];
+ /* set px, n */
+ iANY(str_dup("set"), 0, nreg, 1);
+ }
+ }
+ }
+ /* make a new undef */
+ iNEW(preg[0], str_dup("PerlUndef"), 1);
+ /* emit the operand */
+ nargs = 3;
+ keyvec = 0;
+ iANY(name, 0, preg, 1);
+ /* emit the LHS op */
+ emitb(ins);
+ return ins;
+}
+
Instruction * iANY(char * name, char *fmt, SymReg **regs, int emit) {
char fullname[64];
int i;
@@ -247,6 +341,10 @@
int op;
Instruction * ins;
+ ins = multi_keyed(name, regs, nargs, emit);
+ if (ins)
+ return ins;
+
op_fullname(fullname, name, regs, nargs);
op = interpreter->op_lib->op_code(fullname, 1);
if (op >= 0) {
@@ -332,7 +430,6 @@
fataly(EX_SOFTWARE, "iANY", line,"op not found '%s' (%s<%d>)\n",
fullname, name, nargs);
}
- clear_state();
return ins;
}
@@ -384,7 +481,8 @@
pasmline: labels pasm_inst '\n' { $$ = 0; }
;
-pasm_inst: PARROT_OP pasm_args { $$ = iANY($1,0,regs,1); free($1); }
+pasm_inst: {clear_state();}
+ PARROT_OP pasm_args { $$ = iANY($2,0,regs,1); free($2); }
| /* none */ { $$ = 0;}
;
@@ -427,7 +525,8 @@
| statements statement
;
-statement: instruction
+statement: {clear_state(); }
+ instruction
;
labels: /* none */ { $$ = NULL; }
--- parrot/3key.imc Mon Oct 21 17:34:24 2002
+++ parrot-leo/3key.imc Mon Oct 21 15:57:17 2002
@@ -0,0 +1,14 @@
+.sub _main
+ P0 = new PerlArray
+ P1 = new PerlArray
+ P2 = new PerlArray
+ set P1[0], 100
+ set P2[1], 200
+ set I2, 1
+ add P0[2], P1[0], P2[I2]
+ set I0, P0[2]
+ print I0
+ print "\n"
+ end
+ret
+
--- parrot/a.pasm Mon Oct 21 17:34:24 2002
+++ parrot-leo/a.pasm Mon Oct 21 17:14:05 2002
@@ -0,0 +1,19 @@
+_main:
+ new P0, 10 # .PerlArray
+ new P1, 10 # .PerlArray
+ new P2, 10 # .PerlArray
+ set P1[0], 100
+ set P2[1], 200
+ set I2, 1
+ set P4, P1[0]
+ set P3, P2[I2]
+ new P1, 15 # .PerlUndef
+ add P1, P4, P3
+ set P0[2], P1
+ set I0, P0[2]
+ print I0
+ print "\n"
+ end
+ ret
+
+
