[rfc] Fix PR52770 (supoport throwing asms)

2012-03-30 Thread Michael Matz
Hi,

So here's an extended variant of my hack that implements throwing asms.  
Like rth proposed I've added a new pseudo clobber, throw:

int f (void)
{
  int x, y;
  x = 1;
  y = 2;
  try {
__asm__ ( : =r(x), =r(y) : : throw);
  } catch (...) {
return 2+x+y;
  }
  return x+y;
}

The patch handles multiple output arguments by doing the same we do for 
calls, i.e. introducing new temporaries.  For gimple this clobber is 
retained and hence a throwing asm can be simply recognized by searching 
for it.  For RTL I've added a new flag to mark the ASM_OPERANDS rtx.  
Without such marking we would have to treat every asm as potentially 
throwing in insn_could_throw_p, and rely on the REG_EH_REGION notes to 
mark them as non-throwing.  Instead of auditing all MEM_VOLATILE_P uses on 
asms to see if they require handling throwing I've settled on simply 
implying the volatile bit for throwing asms.

Not yet regstrapped, so no rfa, but does this seem sane?


Ciao,
Michael.

Index: tree-eh.c
===
--- tree-eh.c   (revision 183716)
+++ tree-eh.c   (working copy)
@@ -1990,6 +1990,44 @@ lower_eh_constructs_2 (struct leh_state
}
   break;
 
+case GIMPLE_ASM:
+  /* Similar to normal LHS handling above, replace outputs
+ with new temporaries.  */
+  if (stmt_could_throw_p (stmt)
+  gimple_code (stmt) == GIMPLE_ASM)
+   {
+ unsigned noutputs;
+ unsigned i;
+
+ noutputs = gimple_asm_noutputs (stmt);
+ for (i = 0; i  noutputs; i++)
+   {
+ tree link, op;
+ link = gimple_asm_output_op (stmt, i);
+ op = TREE_VALUE (link);
+ if (!tree_could_throw_p (op)
+  is_gimple_reg_type (TREE_TYPE (op)))
+   {
+ tree tmp = create_tmp_var (TREE_TYPE (op), NULL);
+ gimple s = gimple_build_assign (op, tmp);
+ gimple_set_location (s, gimple_location (stmt));
+ gimple_set_block (s, gimple_block (stmt));
+ TREE_VALUE (link) = tmp;
+ if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
+ || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
+   DECL_GIMPLE_REG_P (tmp) = 1;
+ gsi_insert_after (gsi, s, GSI_SAME_STMT);
+   }
+   }
+   }
+  /* Look for things that can throw exceptions, and record them.  */
+  if (state-cur_region  stmt_could_throw_p (stmt))
+   {
+ record_stmt_eh_region (state-cur_region, stmt);
+ note_eh_region_may_contain_throw (state-cur_region);
+   }
+  break;
+
 case GIMPLE_COND:
 case GIMPLE_GOTO:
 case GIMPLE_RETURN:
@@ -2639,6 +2677,8 @@ stmt_could_throw_p (gimple stmt)
   return stmt_could_throw_1_p (stmt);
 
 case GIMPLE_ASM:
+  if (gimple_asm_can_throw_p (stmt))
+   return true;
   if (!cfun-can_throw_non_call_exceptions)
 return false;
   return gimple_asm_volatile_p (stmt);
Index: varasm.c
===
--- varasm.c(revision 183716)
+++ varasm.c(working copy)
@@ -834,9 +834,10 @@ set_user_assembler_name (tree decl, cons
 
 /* Decode an `asm' spec for a declaration as a register name.
Return the register number, or -1 if nothing specified,
-   or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
+   or -2 if the ASMSPEC is not `cc', `memory' or `throw' and is not recognized,
or -3 if ASMSPEC is `cc' and is not recognized,
-   or -4 if ASMSPEC is `memory' and is not recognized.
+   or -4 if ASMSPEC is `memory' and is not recognized,
+   or -5 if ASMSPEC is `throw' and is not recognized.
Accept an exact spelling or a decimal number.
Prefixes such as % are optional.  */
 
@@ -902,6 +903,9 @@ decode_reg_name_and_count (const char *a
   }
 #endif /* ADDITIONAL_REGISTER_NAMES */
 
+  if (!strcmp (asmspec, throw))
+   return -5;
+
   if (!strcmp (asmspec, memory))
return -4;
 
Index: rtl.h
===
--- rtl.h   (revision 183716)
+++ rtl.h   (working copy)
@@ -266,7 +266,8 @@ struct GTY((chain_next (RTX_NEXT (%h)
  1 in a CALL_INSN if it is a sibling call.
  1 in a SET that is for a return.
  In a CODE_LABEL, part of the two-bit alternate entry field.
- 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.c.  */
+ 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.c.
+ 1 in an ASM_OPERANDS is ASM_OPERANDS_THROW_P.  */
   unsigned int jump : 1;
   /* In a CODE_LABEL, part of the two-bit alternate entry field.
  1 in a MEM if it cannot trap.
@@ -1317,6 +1318,8 @@ do {  
\
 #define ASM_OPERANDS_LABEL_LENGTH(RTX) XCVECLEN (RTX, 5, ASM_OPERANDS)
 #define ASM_OPERANDS_LABEL(RTX, N) XCVECEXP (RTX, 5, 

Re: [rfc] Fix PR52770 (supoport throwing asms)

2012-03-30 Thread Richard Henderson
On 03/30/2012 12:37 PM, Michael Matz wrote:
 Not yet regstrapped, so no rfa, but does this seem sane?

It definitely seems plausible.  I can't immediately think of
anything you might have forgotten.


r~


Re: [rfc] Fix PR52770 (supoport throwing asms)

2012-03-30 Thread Richard Henderson
On 03/30/2012 12:43 PM, Richard Henderson wrote:
 On 03/30/2012 12:37 PM, Michael Matz wrote:
 Not yet regstrapped, so no rfa, but does this seem sane?
 
 It definitely seems plausible.  I can't immediately think of
 anything you might have forgotten.

Stating the obvious, but you'd do well to add at least an
x86 test case that does a call to a local function which does throw.


r~