Index: gcc/testsuite/gcc.dg/gimple/gimple_asm1.c =================================================================== --- gcc/testsuite/gcc.dg/gimple/gimple_asm1.c (revision 0) +++ gcc/testsuite/gcc.dg/gimple/gimple_asm1.c (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +/* Test GIMPLE_ASSIGN. */ + +void asm1() +{ + int a=10, b; + asm ("movl %1, %%eax; " + "movl %%eax, %0;" + :"=r"(b) /* output */ + :"r"(a) /* input */ + :"%eax" /* clobbered register */ + ); +} +/* { dg-final { scan-tree-dump-times "asm \{" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "movl %1, %%eax; movl %%eax, %0;" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times ":b" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times ":a" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times ":\\\"%eax\\\"" 1 "gimple"} } */ + Index: gcc/testsuite/gcc.dg/gimple/gimple_asm2.c =================================================================== --- gcc/testsuite/gcc.dg/gimple/gimple_asm2.c (revision 0) +++ gcc/testsuite/gcc.dg/gimple/gimple_asm2.c (revision 0) @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +/* Test GIMPLE_ASSIGN. */ + +void asm2() +{ + int a=10, b; + asm ("movl %1, %%eax; " + "movl %%eax, %0;" + : /* output */ + : /* input */ + :"%eax" /* clobbered register */ + ); +} +/* { dg-final { scan-tree-dump-times "asm \{" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "movl %1, %%eax; movl %%eax, %0;" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times ":\\\"%eax\\\"" 1 "gimple"} } */ Index: gcc/testsuite/gcc.dg/gimple/gimple_asm.c =================================================================== --- gcc/testsuite/gcc.dg/gimple/gimple_asm.c (revision 0) +++ gcc/testsuite/gcc.dg/gimple/gimple_asm.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +/* Test GIMPLE_ASSIGN. */ + +void asm0() +{ + asm("movl %ecx %eax"); +} +/* { dg-final { scan-tree-dump-times "asm \{" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "movl %ecx %eax" 1 "gimple"} } */ + + Index: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c (revision 127164) +++ gcc/gimple-pretty-print.c (working copy) @@ -360,6 +360,41 @@ dump_gimple_try (pretty_printer *buffer, pp_character (buffer, '}'); } +/* Dump a GIMPLE_ASM tuple on the pretty_printer BUFFER, SPC spaces of + indent. FLAGS specifies details to show in the dump (see TDF_* in + tree.h). */ + +static void +dump_gimple_asm (pretty_printer *buffer, gimple gs, int spc, int flags) +{ + unsigned int i; + newline_and_indent (buffer, spc); + pp_string (buffer, "asm {"); + newline_and_indent (buffer, spc + 2); + + pp_string (buffer, gimple_asm_string (gs)); + + newline_and_indent (buffer, spc); + pp_string (buffer, "}"); + + if(gimple_asm_ninputs (gs) + || gimple_asm_noutputs (gs) + || gimple_asm_nclobbered (gs)) + { + pp_string (buffer, ":"); + for (i = 0; i < gimple_asm_ninputs (gs); i++) + dump_generic_node (buffer, gimple_asm_input_op (gs,i),spc, flags, false); + newline_and_indent (buffer, spc); + pp_string (buffer, ":"); + for (i = 0; i < gimple_asm_noutputs (gs); i++) + dump_generic_node (buffer, gimple_asm_output_op (gs,i),spc, flags, false); + newline_and_indent (buffer, spc); + pp_string (buffer, ":"); + for (i = 0; i < gimple_asm_nclobbered (gs); i++) + dump_generic_node (buffer, gimple_asm_clobber_op (gs,i),spc, flags, false); + } +} + /* Dump the gimple statement GS on the pretty_printer BUFFER, SPC spaces of indent. FLAGS specifies details to show in the dump (see @@ -373,6 +408,11 @@ dump_gimple_stmt (pretty_printer *buffer switch (gimple_code (gs)) { + + case GIMPLE_ASM: + dump_gimple_asm (buffer, gs, spc, flags); + break; + case GIMPLE_ASSIGN: dump_gimple_assign (buffer, gs, spc, flags); break; Index: gcc/ChangeLog.tuples =================================================================== --- gcc/ChangeLog.tuples (revision 127164) +++ gcc/ChangeLog.tuples (working copy) @@ -1,3 +1,18 @@ +2007-08-02 Chris Matthews + + * gimplify.c (gimplify_asm_expr): Created new gimple tuple. + * gimple-pretty-printer.c (dump_gimple_asm): Added function to dump a + GIMPLE_ASM statement. + (dump_gimple_stmt): Updated to use the dump_gimple_asm function. + * gimple.c (gss_for_code): Made asm statements return as with_mem_ops. + (build_gimple_with_ops): Asm statements are added as a specal case for + allocation because they have extra fields that are not allocated correctly + in the current generic op allocator. + (build_gimple_asm_1): Added a helper function to setup the basics of a + GIMPLE_ASM tuple. + (build_gimple_asm_vec): Create a GIMPLE_ASM tuple from vector arguments. + (build_gimple_asm): Changed to call the new helper function. + 2007-08-01 Diego Novillo * gimplify.c (gimplify_switch_expr): Remove switch_body_seq_. Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c (revision 127164) +++ gcc/gimplify.c (working copy) @@ -4113,7 +4113,15 @@ gimplify_asm_expr (tree *expr_p, gimple_ const char *constraint; bool allows_mem, allows_reg, is_inout; enum gimplify_status ret, tret; - + + gimple stmt; + VEC(tree, gc) *inputs; + VEC(tree, gc) *outputs; + VEC(tree, gc) *clobbers; + inputs = VEC_alloc (tree, gc, 5); + outputs = VEC_alloc (tree, gc, 5); + clobbers = VEC_alloc (tree, gc, 5); + ret = GS_ALL_DONE; for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link)) { @@ -4139,6 +4147,8 @@ gimplify_asm_expr (tree *expr_p, gimple_ ret = tret; } + VEC_safe_push (tree, gc, outputs, TREE_VALUE (link)); + if (is_inout) { /* An input/output operand. To give the optimizers more @@ -4271,8 +4281,15 @@ gimplify_asm_expr (tree *expr_p, gimple_ if (tret == GS_ERROR) ret = tret; } + VEC_safe_push (tree, gc, inputs, TREE_VALUE (link)); } - + + for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link)) + VEC_safe_push (tree, gc, clobbers, TREE_VALUE (link)); + + stmt = build_gimple_asm_vec (TREE_STRING_POINTER (ASM_STRING(expr)), + inputs, outputs, clobbers); + gimple_add (pre_p, stmt); return ret; } Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 127164) +++ gcc/gimple.c (working copy) @@ -82,12 +82,12 @@ gss_for_code (enum gimple_code code) { case GIMPLE_ASSIGN: case GIMPLE_CALL: + case GIMPLE_ASM: case GIMPLE_RETURN: return GSS_WITH_MEM_OPS; case GIMPLE_COND: case GIMPLE_GOTO: case GIMPLE_LABEL: case GIMPLE_SWITCH: return GSS_WITH_OPS; - case GIMPLE_ASM: return GSS_ASM; case GIMPLE_BIND: return GSS_BIND; case GIMPLE_CATCH: return GSS_CATCH; case GIMPLE_EH_FILTER: return GSS_EH_FILTER; @@ -120,7 +120,9 @@ build_gimple_with_ops (enum gimple_code gimple s; enum gimple_statement_structure_enum gss = gss_for_code (code); - if (gss == GSS_WITH_OPS) + if (code == GIMPLE_ASM) + s = ggc_alloc_cleared (sizeof (struct gimple_statement_asm)); + else if (gss == GSS_WITH_OPS) s = ggc_alloc_cleared (sizeof (struct gimple_statement_with_ops)); else if (gss == GSS_WITH_MEM_OPS) s = ggc_alloc_cleared (sizeof (struct gimple_statement_with_memory_ops)); @@ -322,6 +324,53 @@ build_gimple_bind (tree vars, gimple_seq return p; } +/* Helper function to set the simple fields of a asm stmt. */ + +gimple +build_gimple_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, + unsigned nclobbers) +{ + gimple p; + p = build_gimple_with_ops (GIMPLE_ASM, 0, ninputs + noutputs + nclobbers); + + p->gimple_asm.ni = ninputs; + p->gimple_asm.no = noutputs; + p->gimple_asm.nc = nclobbers; + p->gimple_asm.string = string; + + return p; +} + +/* Construct a GIMPLE_ASM statement. + + STRING is the assembly code. + NINPUT is the number of register inputs. + NOUTPUT is the number of register outputs. + NCLOBBERS is the number of clobbered registers. + INPUTS is a vector of the input register parameters. + OUTPUTS is a vector of the output register parameters. + CLOBBERS is a vector of the clobbered register parameters. + */ + +gimple +build_gimple_asm_vec (const char *string, VEC(tree,gc)* inputs, + VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers) +{ + gimple p; + unsigned int i; + p = build_gimple_asm_1(string, VEC_length(tree, inputs), + VEC_length(tree, outputs), VEC_length(tree, clobbers)); + + for (i = 0; i < VEC_length (tree, inputs); i++) + gimple_asm_set_input_op (p, i, VEC_index (tree, inputs, i)); + for (i = 0; i < VEC_length (tree, outputs); i++) + gimple_asm_set_output_op (p, i, VEC_index (tree, outputs, i)); + for (i = 0; i < VEC_length (tree, clobbers); i++) + gimple_asm_set_clobber_op (p, i, VEC_index (tree, clobbers, i)); + + return p; +} + /* Construct a GIMPLE_ASM statement. STRING is the assembly code. @@ -337,14 +386,8 @@ build_gimple_asm (const char *string, un gimple p; unsigned i; va_list ap; - - p = ggc_alloc_cleared (sizeof (struct gimple_statement_asm) - + sizeof (tree) * (ninputs + noutputs + nclobbers - 1)); - set_gimple_code (p, GIMPLE_ASM); - p->gimple_asm.ni = ninputs; - p->gimple_asm.no = noutputs; - p->gimple_asm.nc = nclobbers; - p->gimple_asm.string = string; + + p = build_gimple_asm_1(string, ninputs, noutputs, nclobbers); va_start (ap, nclobbers); Index: gcc/gimple.h =================================================================== --- gcc/gimple.h (revision 127164) +++ gcc/gimple.h (working copy) @@ -396,6 +396,9 @@ extern gimple build_gimple_nop (void); extern gimple build_gimple_bind (tree, gimple_seq); extern gimple build_gimple_asm (const char *, unsigned, unsigned, unsigned, ...); +extern gimple build_gimple_asm_vec (const char *, VEC(tree,gc) * , + VEC(tree,gc) *, VEC(tree,gc) *); +extern gimple build_gimple_asm_1 (const char *, unsigned, unsigned, unsigned); extern gimple build_gimple_catch (tree, gimple_seq); extern gimple build_gimple_eh_filter (tree, gimple_seq); extern gimple build_gimple_try (gimple_seq, gimple_seq, unsigned int);