static void gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2) { dfvm_insn_t *insn; dfvm_value_t *val1, *val2; dfvm_value_t *jmp1 = NULL, *jmp2 = NULL; int reg1 = -1, reg2 = -1; /* Create code for the LHS and RHS of the relation */ reg1 = gen_entity(dfw, st_arg1, &jmp1); reg2 = gen_entity(dfw, st_arg2, &jmp2); /* Then combine them in a DFVM insruction */ insn = dfvm_insn_new(op); val1 = dfvm_value_new(REGISTER); val1->value.numeric = reg1; val2 = dfvm_value_new(REGISTER); val2->value.numeric = reg2; insn->arg1 = val1; insn->arg2 = val2; dfw_append_insn(dfw, insn); /* If either of the relation argumnents need an "exit" instruction * to jump to (on failure), mark them */ if (jmp1) { jmp1->value.numeric = dfw->next_insn_id; } if (jmp2) { jmp2->value.numeric = dfw->next_insn_id; } }
/* returns register number */ static int dfw_append_mk_range(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp) { int hf_reg, reg; stnode_t *entity; dfvm_insn_t *insn; dfvm_value_t *val; entity = sttype_range_entity(node); /* XXX, check if p_jmp logic is OK */ hf_reg = gen_entity(dfw, entity, p_jmp); insn = dfvm_insn_new(MK_RANGE); val = dfvm_value_new(REGISTER); val->value.numeric = hf_reg; insn->arg1 = val; val = dfvm_value_new(REGISTER); reg =dfw->next_register++; val->value.numeric = reg; insn->arg2 = val; val = dfvm_value_new(DRANGE); val->value.drange = sttype_range_drange(node); insn->arg3 = val; sttype_range_remove_drange(node); dfw_append_insn(dfw, insn); return reg; }
/* returns register number that the functions's result will be in. */ static int dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp) { GSList *params; int i, num_params, reg; dfvm_value_t **jmps; dfvm_insn_t *insn; dfvm_value_t *val1, *val2, *val; params = sttype_function_params(node); num_params = g_slist_length(params); /* Array to hold the instructions that need to jump to * an instruction if they fail. */ jmps = (dfvm_value_t **)g_malloc(num_params * sizeof(dfvm_value_t*)); /* Create the new DFVM instruction */ insn = dfvm_insn_new(CALL_FUNCTION); val1 = dfvm_value_new(FUNCTION_DEF); val1->value.funcdef = sttype_function_funcdef(node); insn->arg1 = val1; val2 = dfvm_value_new(REGISTER); val2->value.numeric = dfw->next_register++; insn->arg2 = val2; insn->arg3 = NULL; insn->arg4 = NULL; i = 0; while (params) { jmps[i] = NULL; reg = gen_entity(dfw, (stnode_t *)params->data, &jmps[i]); val = dfvm_value_new(REGISTER); val->value.numeric = reg; switch(i) { case 0: insn->arg3 = val; break; case 1: insn->arg4 = val; break; default: g_assert_not_reached(); } params = params->next; i++; } dfw_append_insn(dfw, insn); /* If any of our parameters failed, send them to * our own failure instruction. This *has* to be done * after we caled dfw_append_insn above so that * we know what the next DFVM insruction is, via * dfw->next_insn_id */ for (i = 0; i < num_params; i++) { if (jmps[i]) { jmps[i]->value.numeric = dfw->next_insn_id; } } /* We need another instruction to jump to another exit * place, if the call() of our function failed for some reaosn */ insn = dfvm_insn_new(IF_FALSE_GOTO); g_assert(p_jmp); *p_jmp = dfvm_value_new(INSN_NUMBER); insn->arg1 = *p_jmp; dfw_append_insn(dfw, insn); g_free(jmps); return val2->value.numeric; }