cvsuser 04/11/26 04:24:04
Modified: imcc imc.h optimizer.c parser_util.c
Log:
replace binary, unary, compare and branch opcodes - 2
* don't emit these ops with all constants any more
Revision Changes Path
1.71 +4 -0 parrot/imcc/imc.h
Index: imc.h
===================================================================
RCS file: /cvs/public/parrot/imcc/imc.h,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -r1.70 -r1.71
--- imc.h 26 Nov 2004 09:31:03 -0000 1.70
+++ imc.h 26 Nov 2004 12:24:04 -0000 1.71
@@ -203,6 +203,10 @@
void IMCC_itcall_sub(Interp* interpreter, SymReg* sub);
STRING * IMCC_string_from_reg(Interp *interpreter, SymReg *r);
+Instruction * IMCC_subst_constants_umix(Interp *, IMC_Unit * unit, char
*name,
+ SymReg **r, int n);
+Instruction * IMCC_subst_constants(Interp *, IMC_Unit * unit, char *name,
+ SymReg **r, int n, int *op);
#endif /* PARROT_IMCC_IMC_H_GUARD */
1.49 +142 -200 parrot/imcc/optimizer.c
Index: optimizer.c
===================================================================
RCS file: /cvs/public/parrot/imcc/optimizer.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- optimizer.c 26 Nov 2004 09:31:03 -0000 1.48
+++ optimizer.c 26 Nov 2004 12:24:04 -0000 1.49
@@ -55,9 +55,6 @@
static int dead_code_remove(Interp *interpreter, IMC_Unit *);
static void strength_reduce(Interp *interpreter, IMC_Unit *);
-static void subst_constants_mix(Interp *interpreter, IMC_Unit *);
-static void subst_constants_umix(Interp *interpreter, IMC_Unit *);
-static void subst_constants(Interp *interpreter, IMC_Unit *);
static int constant_propagation(Interp *interpreter, IMC_Unit *);
static int used_once(Interp *, IMC_Unit *);
@@ -71,9 +68,6 @@
{
info(interpreter, 2, "pre_optimize\n");
/* TODO integrate all in one pass */
- subst_constants_mix(interpreter, unit);
- subst_constants_umix(interpreter, unit);
- subst_constants(interpreter, unit);
strength_reduce(interpreter, unit);
if (!dont_optimize)
if_branch(interpreter, unit);
@@ -382,81 +376,37 @@
/*
- * rewrite e.g. add_n_nc_ic => add_n_nc_nc
- */
-static void
-subst_constants_mix(Interp *interpreter, IMC_Unit * unit)
-{
- Instruction *ins, *tmp;
- const char *ops[] = {
- "add", "sub", "mul", "div", "fdiv", "pow"
- };
- size_t i;
- char b[128];
- SymReg *r;
-
- info(interpreter, 2, "\tsubst_constants_mix\n");
- for (ins = unit->instructions; ins; ins = ins->next) {
- for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
- /* TODO compare ins->opnum with a list of instructions
- * containing add_n_nc_ic, ...
- */
- if (!strcmp(ins->op, ops[i]) && ins->opsize == 4 &&
- ins->r[1]->type == VTCONST &&
- ins->r[1]->set == 'N' &&
- ins->r[2]->type == VTCONST &&
- ins->r[2]->set == 'I') {
- debug(interpreter, DEBUG_OPT1, "opt1 %I => ", ins);
- strcpy(b, ins->r[2]->name);
- r = mk_const(str_dup(b), 'N');
- --ins->r[2]->use_count;
- ins->r[2] = r;
- tmp = INS(interpreter, unit, ins->op, "", ins->r, 3, 0, 0);
- debug(interpreter, DEBUG_OPT1, "%I\n", tmp);
- subst_ins(unit, ins, tmp, 1);
- ins = tmp;
- }
- }
- }
-}
-
-/*
* rewrite e.g. add_n_ic => add_n_nc
*/
-static void
-subst_constants_umix(Interp *interpreter, IMC_Unit * unit)
+Instruction *
+IMCC_subst_constants_umix(Interp *interpreter, IMC_Unit * unit, char *name,
+ SymReg **r, int n)
{
- Instruction *ins, *tmp;
+ Instruction *tmp;
const char *ops[] = {
- "add", "div", "mul", "sub", "fdiv"
+ "abs", "add", "div", "mul", "sub", "fdiv"
};
size_t i;
char b[128];
- SymReg *r;
- info(interpreter, 2, "\tsubst_constants_umix\n");
- for (ins = unit->instructions; ins; ins = ins->next) {
- for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
- /* TODO compare ins->opnum with a list of instructions
- * containing add_n_ic, ...
- */
- if (ins->opsize == 3 &&
- ins->r[0]->set == 'N' &&
- ins->r[1]->type == VTCONST &&
- ins->r[1]->set == 'I' &&
- !strcmp(ins->op, ops[i])) {
- debug(interpreter, DEBUG_OPT1, "opt1 %I => ", ins);
- strcpy(b, ins->r[1]->name);
- r = mk_const(str_dup(b), 'N');
- --ins->r[1]->use_count;
- ins->r[1] = r;
- tmp = INS(interpreter, unit, ins->op, "", ins->r, 2, 0, 0);
- debug(interpreter, DEBUG_OPT1, "%I\n", tmp);
- subst_ins(unit, ins, tmp, 1);
- ins = tmp;
- }
+ tmp = NULL;
+ for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
+ /* TODO compare ins->opnum with a list of opcodes
+ * containing add_n_ic, ...
+ */
+ if (n == 3 &&
+ r[0]->set == 'N' &&
+ r[1]->type == VTCONST &&
+ r[1]->set == 'I' &&
+ !strcmp(name, ops[i])) {
+ debug(interpreter, DEBUG_OPT1, "opt1 %s_nc_ic => ", name);
+ strcpy(b, r[1]->name);
+ r[1] = mk_const(str_dup(b), 'N');
+ tmp = INS(interpreter, unit, name, "", r, 2, -1, 0);
+ debug(interpreter, DEBUG_OPT1, "%I\n", tmp);
}
}
+ return tmp;
}
/*
@@ -465,30 +415,14 @@
* core evaluates the constants
*/
static int
-eval_ins(Interp *interpreter, Instruction *ins, size_t ops)
+eval_ins(Interp *interpreter, char *op, size_t ops, SymReg **r)
{
opcode_t eval[4], *pc;
- char op[20];
int opnum;
int i;
STRING *s;
op_info_t *op_info;
- /*
- * create instruction e.g. add_i_ic_ic => add_i_i_i
- * or if_ic_ic => if_i_ic
- */
- if (ops == 4)
- sprintf(op, "%s_%c_%c_%c", ins->op, tolower(ins->r[0]->set),
- tolower(ins->r[1]->set), tolower(ins->r[2]->set));
- else if (ops == 3)
- sprintf(op, "%s_%c_%c", ins->op, tolower(ins->r[0]->set),
- tolower(ins->r[1]->set));
- else if (ops == 2) /* e.g. eq_n_n_ic */
- sprintf(op, "%s_%c_%c_ic", ins->op, tolower(ins->r[0]->set),
- tolower(ins->r[1]->set));
- else /* if_x_ic */
- sprintf(op, "%s_%c_ic", ins->op, tolower(ins->r[0]->set));
opnum = interpreter->op_lib->op_code(op, 1);
if (opnum < 0)
fatal(1, "eval_ins", "op '%s' not found\n", op);
@@ -509,20 +443,20 @@
case PARROT_ARG_S:
eval[i] = i - 1; /* regs used are I0, I1, I2 */
if (ops <= 2 || i > 1) { /* fill source regs */
- switch (ins->r[i-1]->set) {
+ switch (r[i-1]->set) {
case 'I':
REG_INT(i-1) =
- (INTVAL)strtol(ins->r[i-1]->name, 0, 10);
+ (INTVAL)strtol(r[i-1]->name, 0, 10);
break;
case 'N':
s = string_from_cstring(interpreter,
- ins->r[i-1]->name, 0);
+ r[i-1]->name, 0);
REG_NUM(i-1) =
string_to_num(interpreter, s);
break;
case 'S':
REG_STR(i-1) =
- IMCC_string_from_reg(interpreter,
ins->r[i-1]);
+ IMCC_string_from_reg(interpreter, r[i-1]);
break;
}
}
@@ -548,13 +482,16 @@
* eq_ic_ic_ic => branch_ic / delete
* if_ic_ic => branch_ic / delete
*/
-static void
-subst_constants(Interp *interpreter, IMC_Unit * unit)
+
+Instruction *
+IMCC_subst_constants(Interp *interpreter, IMC_Unit * unit, char *name,
+ SymReg **r, int n, int *ok)
{
- Instruction *ins, *tmp;
+ Instruction *tmp;
const char *ops[] = {
- "add", "sub", "mul", "div", "fdiv", "cmod", "mod", "pow", "atan"
- "shr", "srl", "lsr",
+ "add", "sub", "mul", "div", "fdiv", "pow",
+ "cmod", "mod", "atan"
+ "shr", "srl", "lsr",
"band", "bor", "bxor",
"and", "or", "xor",
"iseq", "isne", "islt", "isle", "isgt", "isge", "cmp"
@@ -572,19 +509,12 @@
};
size_t i;
- char b[128], fmt[64];
- SymReg *r;
+ char b[128], fmt[64], op[20];
+ const char *debug_fmt;
int found, branched;
struct parrot_regs_t *bp;
Stack_Chunk_t *stack_p, *reg_stack;
- info(interpreter, 2, "\tsubst_constants\n");
-
- /* preserve registers */
- bp = interpreter->ctx.bp;
- reg_stack = interpreter->ctx.reg_stack;
- interpreter->ctx.bp = new_register_frame(interpreter,
- &interpreter->ctx.reg_stack);
/* construct a FLOATVAL_FMT with needed precision */
switch (NUMVAL_SIZE) {
@@ -601,113 +531,124 @@
break;
}
- for (ins = unit->instructions; ins; ins = ins->next) {
- found = 0;
- for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
- /* TODO compare ins->opnum with a list of opcodes
- * containing add_i_ic_ic, add_n_nc_nc ...
- */
- if (ins->opsize == 4 &&
- ins->r[1]->type == VTCONST &&
- ins->r[2]->type == VTCONST &&
- !strcmp(ins->op, ops[i])) {
- found = 4;
- break;
- }
- }
- for (i = 0; !found && i < sizeof(ops2)/sizeof(ops2[0]); i++) {
+ tmp = NULL;
+ found = 0;
+ for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
+ /* TODO compare ins->opnum with a list of opcodes
+ * containing add_i_ic_ic, add_n_nc_nc ...
+ */
+ if (n == 4 &&
+ r[1]->type == VTCONST &&
+ r[2]->type == VTCONST &&
+ !strcmp(name, ops[i])) {
+ found = 4;
/*
- * abs_i_ic ...
+ * create instruction e.g. add_i_ic_ic => add_i_i_i
*/
- if (ins->opsize == 3 &&
- ins->r[1]->type == VTCONST &&
- !strcmp(ins->op, ops2[i])) {
- found = 3;
- break;
- }
+ sprintf(op, "%s_%c_%c_%c", name, tolower(r[0]->set),
+ tolower(r[1]->set), tolower(r[2]->set));
+ debug_fmt = "opt %s_x_xc_xc => ";
+ break;
}
- for (i = 0; !found && i < sizeof(ops3)/sizeof(ops3[0]); i++) {
- /*
- * eq_xc_xc_labelc ...
- */
- if (ins->opsize == 4 &&
- ins->r[0]->type == VTCONST &&
- ins->r[1]->type == VTCONST &&
- !strcmp(ins->op, ops3[i])) {
- found = 2;
- break;
- }
+ }
+ for (i = 0; !found && i < sizeof(ops2)/sizeof(ops2[0]); i++) {
+ /*
+ * abs_i_ic ...
+ */
+ if (n == 3 &&
+ r[1]->type == VTCONST &&
+ !strcmp(name, ops2[i])) {
+ found = 3;
+ sprintf(op, "%s_%c_%c", name, tolower(r[0]->set),
+ tolower(r[1]->set));
+ debug_fmt = "opt %s_x_xc => ";
+ break;
}
- for (i = 0; !found && i < sizeof(ops4)/sizeof(ops4[0]); i++) {
- /*
- * if_xc_labelc, unless
- */
- if (ins->opsize == 3 &&
- ins->r[0]->type == VTCONST &&
- !strcmp(ins->op, ops4[i])) {
- found = 1;
- break;
- }
+ }
+ for (i = 0; !found && i < sizeof(ops3)/sizeof(ops3[0]); i++) {
+ /*
+ * eq_xc_xc_labelc ...
+ */
+ if (n == 4 &&
+ r[0]->type == VTCONST &&
+ r[1]->type == VTCONST &&
+ !strcmp(name, ops3[i])) {
+ found = 2;
+ sprintf(op, "%s_%c_%c_ic", name, tolower(r[0]->set),
+ tolower(r[1]->set));
+ debug_fmt = "opt %s_xc_xc_ic => ";
+ break;
}
-
- if (!found)
- continue;
- debug(interpreter, DEBUG_OPT1, "opt1 %I => ", ins);
- /* we construct a parrot instruction
- * here and let parrot do the calculation in a
- * separate context and make a constant
- * from the result
+ }
+ for (i = 0; !found && i < sizeof(ops4)/sizeof(ops4[0]); i++) {
+ /*
+ * if_xc_labelc, unless
*/
- branched = eval_ins(interpreter, ins, found);
+ if (n == 3 &&
+ r[0]->type == VTCONST &&
+ !strcmp(name, ops4[i])) {
+ found = 1;
+ sprintf(op, "%s_%c_ic", name, tolower(r[0]->set));
+ debug_fmt = "opt %s_xc_ic => ";
+ break;
+ }
+ }
+
+ if (!found) {
+ *ok = 0;
+ return NULL;
+ }
+ /* preserve registers */
+ bp = interpreter->ctx.bp;
+ reg_stack = interpreter->ctx.reg_stack;
+ interpreter->ctx.bp = new_register_frame(interpreter,
+ &interpreter->ctx.reg_stack);
+
+ debug(interpreter, DEBUG_OPT1, debug_fmt, name);
+ /* we construct a parrot instruction
+ * here and let parrot do the calculation in a
+ * separate context and make a constant
+ * from the result
+ */
+ branched = eval_ins(interpreter, op, found, r);
+ /*
+ * for math ops result is in I0/N0
+ * if it was a branch with constant args, the result is
+ * the return value
+ */
+ if (found <= 2) {
/*
- * for math ops result is in I0/N0
- * if it was a branch with constant args, the result is
- * the return value
+ * create a branch or delete instruction
*/
- if (found <= 2) {
- /*
- * emit a branch or delete instruction
- */
- if (branched) {
- --ins->r[0]->use_count;
- if (found == 2)
- --ins->r[1]->use_count;
- ins->r[0] = ins->r[found];
- tmp = INS(interpreter, unit, "branch", "", ins->r,
- 1, 0, 0);
- }
- else {
- debug(interpreter, DEBUG_OPT1, "deleted\n");
- ins = delete_ins(unit, ins, 1);
- ins = ins->prev ? ins->prev : unit->instructions;
- tmp = NULL;
- }
+ if (branched) {
+ r[0] = r[found];
+ tmp = INS(interpreter, unit, "branch", "", r,
+ 1, -1, 0);
}
else {
- /*
- * emit set x, constant
- */
- switch (ins->r[0]->set) {
- case 'I':
- sprintf(b, INTVAL_FMT, REG_INT(0));
- break;
- case 'N':
- sprintf(b, fmt, REG_NUM(0));
- break;
- }
- r = mk_const(str_dup(b), ins->r[0]->set);
- --ins->r[1]->use_count;
- if (ins->opsize == 4)
- --ins->r[2]->use_count;
- ins->r[1] = r;
- tmp = INS(interpreter, unit, "set", "", ins->r, 2, 0, 0);
+ debug(interpreter, DEBUG_OPT1, "deleted\n");
}
- if (tmp) {
- debug(interpreter, DEBUG_OPT1, "%I\n", tmp);
- subst_ins(unit, ins, tmp, 1);
- ins = tmp;
+ }
+ else {
+ /*
+ * create set x, constant
+ */
+ switch (r[0]->set) {
+ case 'I':
+ sprintf(b, INTVAL_FMT, REG_INT(0));
+ break;
+ case 'N':
+ sprintf(b, fmt, REG_NUM(0));
+ break;
}
+ r[1] = mk_const(str_dup(b), r[0]->set);
+ tmp = INS(interpreter, unit, "set", "", r,
+ 2, -1, 0);
+ }
+ if (tmp) {
+ debug(interpreter, DEBUG_OPT1, "%I\n", tmp);
}
+ *ok = 1;
/*
* restore and recycle register frame
*/
@@ -715,6 +656,7 @@
interpreter->ctx.bp = bp;
interpreter->ctx.reg_stack = reg_stack;
add_to_fp_cache(interpreter, stack_p);
+ return tmp;
}
1.87 +148 -115 parrot/imcc/parser_util.c
Index: parser_util.c
===================================================================
RCS file: /cvs/public/parrot/imcc/parser_util.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -r1.86 -r1.87
--- parser_util.c 25 Nov 2004 14:01:31 -0000 1.86
+++ parser_util.c 26 Nov 2004 12:24:04 -0000 1.87
@@ -284,140 +284,173 @@
int dirs = 0;
int op;
Instruction * ins;
+ op_info_t * op_info;
+ char format[128];
+ int len;
#if 1
+ if (keyvec >= 0) { /* XXX see below */
ins = multi_keyed(interpreter, unit, name, r, n, keyvec, emit);
if (ins)
return ins;
+ }
#endif
- op_fullname(fullname, name, r, n, keyvec);
+ if (keyvec == -1)
+ op_fullname(fullname, name, r, n, 0); /* XXX */
+ else
+ op_fullname(fullname, name, r, n, keyvec);
op = interpreter->op_lib->op_code(fullname, 1);
if (op < 0) /* maybe we got a fullname */
op = interpreter->op_lib->op_code(name, 1);
if (op < 0) /* still wrong, try to find an existing op */
op = try_find_op(interpreter, unit, name, r, n, keyvec, emit);
+ /*
+ * XXX the opcodes still exists, so the op number is >= 0
+ * but we want to replace the ops and sub_constants is using
+ * INS which gives nice recursion.
+ * If coming from subst_constants keyvec := -1 therefore
+ * XXX
+ */
+ if (keyvec == -1)
+ keyvec = 0;
else
- strcpy(fullname, name);
- if (op >= 0) {
- op_info_t * op_info = &interpreter->op_info_table[op];
- char format[128];
- int len;
-
- *format = '\0';
- /* info->arg_count is offset by one, first is opcode
- * build instruction format
- * set LV_in / out flags */
- if (n != op_info->arg_count-1)
- fataly(EX_SOFTWARE, sourcefile, line,
- "arg count mismatch: op #%d '%s' needs %d given %d",
- op, fullname, op_info->arg_count-1, n);
- for (i = 0; i < op_info->arg_count-1; i++) {
- switch (op_info->dirs[i+1]) {
- case PARROT_ARGDIR_INOUT:
- dirs |= 1 << (16 + i);
- /* go on */
- case PARROT_ARGDIR_IN:
- dirs |= 1 << i ;
- break;
-
- case PARROT_ARGDIR_OUT:
- dirs |= 1 << (16 + i);
- break;
-
- default:
- assert(0);
- };
- if (keyvec & KEY_BIT(i)) {
- len = strlen(format);
- len -= 2;
- format[len] = '\0';
- strcat(format, "[%s], ");
- }
+
+ if (1 || op < 0) {
+ int ok;
+ /* check mixed constants */
+ ins = IMCC_subst_constants_umix(interpreter, unit, name, r, n + 1);
+ if (ins)
+ goto found_ins;
+ /* and finally multiple constants */
+ ins = IMCC_subst_constants(interpreter, unit, name, r, n + 1, &ok);
+ if (ok) {
+ if (ins)
+ goto found_ins;
else
- strcat(format, "%s, ");
+ return NULL;
}
- len = strlen(format);
- if (len >= 2)
+ if (op < 0)
+ strcpy(fullname, name);
+ }
+ else
+ strcpy(fullname, name);
+ if (op < 0) {
+ fataly(EX_SOFTWARE, sourcefile, line,"op not found '%s' (%s<%d>)\n",
+ fullname, name, n);
+ }
+ op_info = &interpreter->op_info_table[op];
+
+ *format = '\0';
+ /* info->arg_count is offset by one, first is opcode
+ * build instruction format
+ * set LV_in / out flags */
+ if (n != op_info->arg_count-1)
+ fataly(EX_SOFTWARE, sourcefile, line,
+ "arg count mismatch: op #%d '%s' needs %d given %d",
+ op, fullname, op_info->arg_count-1, n);
+ for (i = 0; i < op_info->arg_count-1; i++) {
+ switch (op_info->dirs[i+1]) {
+ case PARROT_ARGDIR_INOUT:
+ dirs |= 1 << (16 + i);
+ /* go on */
+ case PARROT_ARGDIR_IN:
+ dirs |= 1 << i ;
+ break;
+
+ case PARROT_ARGDIR_OUT:
+ dirs |= 1 << (16 + i);
+ break;
+
+ default:
+ assert(0);
+ };
+ if (keyvec & KEY_BIT(i)) {
+ len = strlen(format);
len -= 2;
- format[len] = '\0';
- if (fmt && *fmt)
- strcpy(format, fmt);
- memset(r + n, 0, sizeof(*r) * (IMCC_MAX_REGS - n));
+ format[len] = '\0';
+ strcat(format, "[%s], ");
+ }
+ else
+ strcat(format, "%s, ");
+ }
+ len = strlen(format);
+ if (len >= 2)
+ len -= 2;
+ format[len] = '\0';
+ if (fmt && *fmt)
+ strcpy(format, fmt);
+ memset(r + n, 0, sizeof(*r) * (IMCC_MAX_REGS - n));
#if 1
- debug(interpreter, DEBUG_PARSER,"%s %s\t%s\n", name, format,
fullname);
+ debug(interpreter, DEBUG_PARSER,"%s %s\t%s\n", name, format, fullname);
#endif
- /* make the instruction */
+ /* make the instruction */
- ins = _mk_instruction(name, format, r, dirs);
- ins->keys |= keyvec;
- /* fill iin oplib's info */
- ins->opnum = op;
- ins->opsize = op_info->arg_count;
- /* mark end as absolute branch */
- if (!strcmp(name, "end")) {
- ins->type |= ITBRANCH | IF_goto;
- }
- else if (!strcmp(name, "warningson")) {
- /* emit a debug seg, if this op is seen */
- PARROT_WARNINGS_on(interpreter, PARROT_WARNINGS_ALL_FLAG);
- }
- else if (!strcmp(name, "loadlib")) {
- SymReg *r1 = r[1]; /* lib name */
- STRING *lib;
- if (r1->type == VTCONST) {
- /*
- * XXX we should not read in dynamic PMC classes
- * OTOH we have to load dynamic opcodes
- * to get at the opcode information
- */
- lib = string_from_cstring(interpreter, r1->name + 1,
- strlen(r1->name) - 2);
- Parrot_load_lib(interpreter, lib, NULL);
- }
- }
- else if (!memcmp(name, "invoke", 6) ||
- !memcmp(name, "callmethod", 10)) {
- if (cur_unit->type & IMC_PCCSUB)
- cur_unit->instructions->r[1]->pcc_sub->calls_a_sub |= 1;
- }
- /* set up branch flags */
- /*
- * mark registers that are labels
- */
- for (i = 0; i < op_info->arg_count-1; i++) {
- if (op_info->labels[i+1])
- ins->type |= ITBRANCH | (1 << i);
- else {
- if (r[i]->type == VTADDRESS)
- fataly(EX_SOFTWARE, sourcefile, line,
- "undefined identifier '%s'\n", r[i]->name);
- }
- }
- if (op_info->jump && op_info->jump != PARROT_JUMP_ENEXT) {
- ins->type |= ITBRANCH;
- if (!strcmp(name, "branch"))
- ins->type |= IF_goto;
- else if (!strcmp(fullname, "jump_i") ||
- !strcmp(fullname, "jsr_i") ||
- !strcmp(fullname, "branch_i") ||
- !strcmp(fullname, "bsr_i"))
- dont_optimize = 1;
- }
- else if (!strcmp(name, "set") && n == 2) {
- /* set Px, Py: both PMCs have the same address */
- if (r[0]->set == r[1]->set &&
- (r[1]->type & VTREGISTER))
- ins->type |= ITALIAS;
- }
- else if (!strcmp(name, "compile"))
- ++has_compile;
-
- if (emit)
- emitb(unit, ins);
- } else {
- fataly(EX_SOFTWARE, sourcefile, line,"op not found '%s' (%s<%d>)\n",
- fullname, name, n);
+ ins = _mk_instruction(name, format, r, dirs);
+ ins->keys |= keyvec;
+ /* fill iin oplib's info */
+ ins->opnum = op;
+ ins->opsize = op_info->arg_count;
+ /* mark end as absolute branch */
+ if (!strcmp(name, "end")) {
+ ins->type |= ITBRANCH | IF_goto;
+ }
+ else if (!strcmp(name, "warningson")) {
+ /* emit a debug seg, if this op is seen */
+ PARROT_WARNINGS_on(interpreter, PARROT_WARNINGS_ALL_FLAG);
+ }
+ else if (!strcmp(name, "loadlib")) {
+ SymReg *r1 = r[1]; /* lib name */
+ STRING *lib;
+ if (r1->type == VTCONST) {
+ /*
+ * XXX we should not read in dynamic PMC classes
+ * OTOH we have to load dynamic opcodes
+ * to get at the opcode information
+ */
+ lib = string_from_cstring(interpreter, r1->name + 1,
+ strlen(r1->name) - 2);
+ Parrot_load_lib(interpreter, lib, NULL);
+ }
+ }
+ else if (!memcmp(name, "invoke", 6) ||
+ !memcmp(name, "callmethod", 10)) {
+ if (cur_unit->type & IMC_PCCSUB)
+ cur_unit->instructions->r[1]->pcc_sub->calls_a_sub |= 1;
}
+ /* set up branch flags */
+ /*
+ * mark registers that are labels
+ */
+ for (i = 0; i < op_info->arg_count-1; i++) {
+ if (op_info->labels[i+1])
+ ins->type |= ITBRANCH | (1 << i);
+ else {
+ if (r[i]->type == VTADDRESS)
+ fataly(EX_SOFTWARE, sourcefile, line,
+ "undefined identifier '%s'\n", r[i]->name);
+ }
+ }
+ if (op_info->jump && op_info->jump != PARROT_JUMP_ENEXT) {
+ ins->type |= ITBRANCH;
+ if (!strcmp(name, "branch"))
+ ins->type |= IF_goto;
+ else if (!strcmp(fullname, "jump_i") ||
+ !strcmp(fullname, "jsr_i") ||
+ !strcmp(fullname, "branch_i") ||
+ !strcmp(fullname, "bsr_i"))
+ dont_optimize = 1;
+ }
+ else if (!strcmp(name, "set") && n == 2) {
+ /* set Px, Py: both PMCs have the same address */
+ if (r[0]->set == r[1]->set &&
+ (r[1]->type & VTREGISTER))
+ ins->type |= ITALIAS;
+ }
+ else if (!strcmp(name, "compile"))
+ ++has_compile;
+found_ins:
+ if (emit)
+ emitb(unit, ins);
return ins;
}