There are several cut-and-pasted loops in expand_asm_stmt that could be parameterized by the functions used to access the particular operands. The patch below does that.
Tested on x86_64-unknown-linux-gnu. OK to commit? -Nathan * stmt.c (chain_asm_ops): New function. (expand_asm_stmt): Call it. diff --git a/gcc/stmt.c b/gcc/stmt.c index 1a9f9e5..1fc09e9 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1114,13 +1114,34 @@ expand_asm_operands (tree string, tree outputs, tree inputs, free_temp_slots (); } +/* Return the operands of STMT, a GIMPLE_ASM, as described by OP_FN and + N_OPS connected via TREE_CHAIN. */ + +static tree +chain_asm_ops (const_gimple stmt, unsigned (*n_ops) (const_gimple), + tree (*op_fn) (const_gimple, unsigned)) +{ + unsigned i, n; + tree ret = NULL_TREE, t; + + n = (*n_ops) (stmt); + if (n > 0) + { + t = ret = (*op_fn) (stmt, 0); + for (i = 1; i < n; i++) + t = TREE_CHAIN (t) = (*op_fn) (stmt, i); + } + + return ret; +} + void expand_asm_stmt (gimple stmt) { int noutputs; - tree outputs, tail, t; + tree outputs, tail; tree *o; - size_t i, n; + size_t i; const char *s; tree str, out, in, cl, labels; location_t locus = gimple_location (stmt); @@ -1128,41 +1149,10 @@ expand_asm_stmt (gimple stmt) /* Meh... convert the gimple asm operands into real tree lists. Eventually we should make all routines work on the vectors instead of relying on TREE_CHAIN. */ - out = NULL_TREE; - n = gimple_asm_noutputs (stmt); - if (n > 0) - { - t = out = gimple_asm_output_op (stmt, 0); - for (i = 1; i < n; i++) - t = TREE_CHAIN (t) = gimple_asm_output_op (stmt, i); - } - - in = NULL_TREE; - n = gimple_asm_ninputs (stmt); - if (n > 0) - { - t = in = gimple_asm_input_op (stmt, 0); - for (i = 1; i < n; i++) - t = TREE_CHAIN (t) = gimple_asm_input_op (stmt, i); - } - - cl = NULL_TREE; - n = gimple_asm_nclobbers (stmt); - if (n > 0) - { - t = cl = gimple_asm_clobber_op (stmt, 0); - for (i = 1; i < n; i++) - t = TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i); - } - - labels = NULL_TREE; - n = gimple_asm_nlabels (stmt); - if (n > 0) - { - t = labels = gimple_asm_label_op (stmt, 0); - for (i = 1; i < n; i++) - t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i); - } + out = chain_asm_ops (stmt, gimple_asm_noutputs, gimple_asm_output_op); + in = chain_asm_ops (stmt, gimple_asm_ninputs, gimple_asm_input_op); + cl = chain_asm_ops (stmt, gimple_asm_nclobbers, gimple_asm_clobber_op); + labels = chain_asm_ops (stmt, gimple_asm_nlabels, gimple_asm_label_op); s = gimple_asm_string (stmt); str = build_string (strlen (s), s);