- * encode an IR-node
- */
-static void encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth)
-{
- codec_env_t env;
-
- env.buf = buf;
- env.curr_id = 1; /* 0 is used for special purpose */
- env.options = status->options;
- env.dmp = NULL;
-
- if (env.options & OPT_ENC_GRAPH)
- env.id_set = new_set(addr_cmp, 32);
- else
- env.id_set = NULL;
-
- /* encode options if any */
- if (env.options) {
- put_tag(buf, VLC_TAG_OPTION);
- put_code(buf, env.options);
- }
-
- _encode_node(node, max_depth, &env);
-
- if (env.options & OPT_ENC_GRAPH)
- del_set(env.id_set);
-}
+ * Encodes an IR-node, recursive worker.
+ *
+ * @return reached depth
+ */
+static int _encode_node(ir_node *node, int max_depth, codec_env_t *env) {
+ addr_entry_t entry, *r_entry;
+ set_entry *s_entry;
+ int i, preds;
+ int res, depth;
+
+ ir_opcode code = get_irn_opcode(node);
+
+ /* insert the node into our ID map */
+ entry.addr = node;
+ entry.id = env->curr_id;
+
+ s_entry = set_hinsert(env->id_set, &entry, sizeof(entry), HASH_PTR(node));
+ r_entry = (addr_entry_t *)s_entry->dptr;
+
+ if (r_entry->id != env->curr_id) {
+ /* already in the map, add an REF */
+ put_tag(env->buf, VLC_TAG_REF);
+ put_code(env->buf, r_entry->id);
+
+ return max_depth;
+ } else {
+ /* a new entry, proceed */
+ ++env->curr_id;
+ } /* if */
+
+ put_code(env->buf, (unsigned)code);
+
+ /* do we need the mode ? */
+ if (env->options & OPT_WITH_MODE) {
+ ir_mode *mode = get_irn_mode(node);
+
+ if (mode)
+ put_code(env->buf, stat_find_mode_index(mode));
+ else
+ put_tag(env->buf, VLC_TAG_EMPTY);
+ } /* if */
+
+ /* do we need integer constants */
+ if (env->options & OPT_WITH_ICONST) {
+ if (code == iro_Const) {
+ tarval *tv = get_Const_tarval(node);
+
+ if (tarval_is_long(tv)) {
+ long v = get_tarval_long(tv);
+
+ put_tag(env->buf, VLC_TAG_ICONST);
+ put_code(env->buf, v);
+ } /* if */
+ } /* if */
+ } /* if */
+
+ --max_depth;
+
+ if (max_depth <= 0) {
+ put_code(env->buf, 0);
+ return max_depth;
+ } /* if */
+
+ preds = get_irn_arity(node);
+ put_code(env->buf, preds);
+
+ res = INT_MAX;
+ if (is_op_commutative(get_irn_op(node))) {
+ ir_node *l = get_binop_left(node);
+ ir_node *r = get_binop_right(node);
+ int opcode_diff = (int)get_irn_opcode(l) - (int)get_irn_opcode(r);
+
+ if (opcode_diff > 0) {
+ ir_node *t = l;
+ l = r;
+ r = t;
+ } else if (opcode_diff == 0 && l != r) {
+ /* Both nodes have the same opcode, but are different.
+ Need a better method here to decide which goes to the left side. */
+ } /* if */
+
+ /* special handling for commutative operators */
+ depth = _encode_node(l, max_depth, env);
+ if (depth < res)
+ res = depth;
+ depth = _encode_node(r, max_depth, env);
+ if (depth < res)
+ res = depth;
+ } else {
+ for (i = 0; i < preds; ++i) {
+ ir_node *n = get_irn_n(node, i);
+
+ depth = _encode_node(n, max_depth, env);
+ if (depth < res)
+ res = depth;
+ } /* for */
+ } /* if */
+ return res;
+} /* _encode_node */