===================================================================
@@ -1,3 +1,17 @@
+2009-07-06 Richard Henderson <rth@redhat.com>
+
+ * attribs.c (init_attributes): Allow '*' prefix for overrides.
+ (register_attribute): Likewise.
+ * builtin-attrs.def (ATTR_TM_REGPARM): New.
+ (ATTR_TM_NOTHROW_LIST, ATTR_TM_NORETURN_NOTHROW_LIST,
+ ATTR_TM_NOTHROW_NONNULL, ATTR_TM_CONST_NOTHROW_LIST,
+ ATTR_TM_PURE_NOTHROW_LIST): New.
+ * c-common.c (ignore_attribute): New.
+ (c_common_attribute_table): Add "*tm regparm".
+
+ * config/i386/i386.c (ix86_handle_tm_regparm_attribute): New.
+ (ix86_attribute_table): Add "*tm regparm".
+
2009-07-02 Richard Henderson <rth@redhat.com>
* c-typeck.c (c_finish_tm_atomic): Use build_stmt.
===================================================================
@@ -166,7 +166,8 @@ init_attributes (void)
gcc_assert (strcmp (attribute_tables[i][j].name,
attribute_tables[i][k].name));
}
- /* Check that no name occurs in more than one table. */
+ /* Check that no name occurs in more than one table. Names that
+ begin with '*' are exempt, and may be overridden. */
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
{
size_t j, k, l;
@@ -174,8 +175,9 @@ init_attributes (void)
for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
for (k = 0; attribute_tables[i][k].name != NULL; k++)
for (l = 0; attribute_tables[j][l].name != NULL; l++)
- gcc_assert (strcmp (attribute_tables[i][k].name,
- attribute_tables[j][l].name));
+ gcc_assert (attribute_tables[i][k].name[0] == '*'
+ || strcmp (attribute_tables[i][k].name,
+ attribute_tables[j][l].name));
}
#endif
@@ -202,7 +204,7 @@ register_attribute (const struct attribu
slot = htab_find_slot_with_hash (attribute_hash, &str,
substring_hash (str.str, str.length),
INSERT);
- gcc_assert (!*slot);
+ gcc_assert (!*slot || attr->name[0] == '*');
*slot = (void *) CONST_CAST (struct attribute_spec *, attr);
}
===================================================================
@@ -94,6 +94,7 @@ DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel
DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")
+DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm")
DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
@@ -192,6 +193,19 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3
#undef DEF_FORMAT_ATTRIBUTE_NOTHROW
#undef DEF_FORMAT_ATTRIBUTE_BOTH
+/* Transactional memory variants of the above. */
+
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_NORETURN_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_NONNULL,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_NONNULL)
+DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_PURE_NOTHROW_LIST)
+
/* Construct a tree for a format_arg attribute. */
#define DEF_FORMAT_ARG_ATTRIBUTE(FA) \
DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \
===================================================================
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void foo(void (*fn)(void))
+{
+ __tm_atomic {
+ fn();
+ }
+}
===================================================================
@@ -2895,13 +2895,18 @@ remove_eh_handler_and_replace (struct eh
}
}
-/* Splice REGION from the region tree and replace it by the outer region
- etc. */
+/* Splice REGION from the region tree and replace it by an outer region. */
static void
remove_eh_handler (struct eh_region_d *region)
{
- remove_eh_handler_and_replace (region, region->outer, true);
+ struct eh_region_d *outer;
+
+ for (outer = region->outer; outer; outer = outer->outer)
+ if (outer->type != ERT_TRANSACTION)
+ break;
+
+ remove_eh_handler_and_replace (region, outer, true);
}
/* Remove Eh region R that has turned out to have no code in its handler. */
===================================================================
@@ -530,6 +530,7 @@ static tree handle_type_generic_attribut
static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -830,6 +831,10 @@ const struct attribute_spec c_common_att
handle_target_attribute },
{ "optimize", 1, -1, true, false, false,
handle_optimize_attribute },
+ /* For internal use only. The leading '*' both prevents its usage in
+ source code and signals that it may be overridden by machine tables. */
+ { "*tm regparm", 0, 0, false, true, true,
+ ignore_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -7865,6 +7870,19 @@ handle_optimize_attribute (tree *node, t
return NULL_TREE;
}
+
+/* Ignore the given attribute. Used when this attribute may be usefully
+ overridden by the target, but is not used generically. */
+
+static tree
+ignore_attribute (tree *node, tree ARG_UNUSED (name), tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+
/* Check for valid arguments being passed to a function.
ATTRS is a list of attributes. There are NARGS arguments in the array
===================================================================
@@ -1,49 +1,49 @@
DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction",
- BT_FN_UINT_UINT, ATTR_NOTHROW_LIST)
+ BT_FN_UINT_UINT, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction",
- BT_FN_VOID, ATTR_NOTHROW_LIST)
+ BT_FN_VOID, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_ABORT, "_ITM_abortTransaction",
- BT_FN_INT, ATTR_NORETURN_NOTHROW_LIST)
+ BT_FN_INT, ATTR_TM_NORETURN_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_IRREVOKABLE, "_ITM_changeTransactionMode",
- BT_FN_INT, ATTR_NOTHROW_LIST)
+ BT_FN_INT, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY, "_ITM_memcpyRtWt",
- BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
+ BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_NOTHROW_NONNULL)
DEF_TM_BUILTIN (BUILT_IN_TM_MEMMOVE, "_ITM_memmoveRtWt",
- BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
+ BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_NOTHROW_NONNULL)
DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_IRR, "_ITM_getTMCloneOrIrrevokable",
- BT_FN_PTR_PTR, ATTR_NOTHROW_NONNULL)
+ BT_FN_PTR_PTR, ATTR_TM_NOTHROW_NONNULL)
DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe",
- BT_FN_PTR_PTR, ATTR_CONST_NOTHROW_LIST)
+ BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_1, "_ITM_WU1",
- BT_FN_VOID_VPTR_I1, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_2, "_ITM_WU2",
- BT_FN_VOID_VPTR_I2, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_4, "_ITM_WU4",
- BT_FN_VOID_VPTR_I4, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_8, "_ITM_WU8",
- BT_FN_VOID_VPTR_I8, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_FLOAT, "_ITM_WF",
- BT_FN_VOID_VPTR_FLOAT, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_DOUBLE, "_ITM_WD",
- BT_FN_VOID_VPTR_DOUBLE, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBLE, "_ITM_WE",
- BT_FN_VOID_VPTR_LDOUBLE, ATTR_NOTHROW_LIST)
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1",
- BT_FN_I1_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_I1_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2",
- BT_FN_I2_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_I2_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4",
- BT_FN_I4_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_I4_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8",
- BT_FN_I8_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_I8_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF",
- BT_FN_FLOAT_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD",
- BT_FN_DOUBLE_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE",
- BT_FN_LDOUBLE_VPTR, ATTR_PURE_NOTHROW_LIST)
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
===================================================================
@@ -4377,6 +4377,39 @@ ix86_handle_cconv_attribute (tree *node,
return NULL_TREE;
}
+/* The transactional memory builtins are implicitly regparm or fastcall
+ depending on the ABI. Override the generic do-nothing attribute that
+ these builtins were declared with, and replace it with one of the two
+ attributes that we expect elsewhere. */
+
+static tree
+ix86_handle_tm_regparm_attribute (tree *node, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
+{
+ tree alt;
+
+ /* In no case do we want to add the placeholder attribute. */
+ *no_add_attrs = true;
+
+ /* The 64-bit ABI is unchanged for transactional memory. */
+ if (TARGET_64BIT)
+ return NULL_TREE;
+
+ /* ??? Is there a better way to validate 32-bit windows? We have
+ cfun->machine->call_abi, but that seems to be set only for 64-bit. */
+ if (CHECK_STACK_LIMIT > 0)
+ alt = tree_cons (get_identifier ("fastcall"), NULL, NULL);
+ else
+ {
+ alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL);
+ alt = tree_cons (get_identifier ("regparm"), alt, NULL);
+ }
+ decl_attributes (node, alt, flags);
+
+ return NULL_TREE;
+}
+
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
@@ -30424,6 +30457,10 @@ static const struct attribute_spec ix86_
/* Sseregparm attribute says we are using x86_64 calling conventions
for FP arguments. */
{ "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
+ /* The transactional memory builtins are implicitly regparm or fastcall
+ depending on the ABI. Override the generic do-nothing attribute that
+ these builtins were declared with. */
+ { "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute },
/* force_align_arg_pointer says this function realigns the stack at entry. */
{ (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
false, true, true, ix86_handle_cconv_attribute },