Parser and some front-end stuff, like tree definitions, etc.
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c (.../trunk) (revision 180744)
+++ gcc/c-parser.c (.../branches/transactional-memory) (revision
180773)
@@ -195,6 +195,9 @@ typedef struct GTY(()) c_parser {
undesirable to bind an identifier to an Objective-C class, even
if a class with that name exists. */
BOOL_BITFIELD objc_need_raw_identifier : 1;
+ /* Nonzero if we're processing a __transaction statement. The value
+ is 1 | TM_STMT_ATTR_*. */
+ unsigned int in_transaction : 4;
/* True if we are in a context where the Objective-C "Property
attribute"
keywords are valid. */
BOOL_BITFIELD objc_property_attr_context : 1;
@@ -1169,6 +1172,9 @@ static struct c_expr c_parser_postfix_ex
static struct c_expr c_parser_postfix_expression_after_primary
(c_parser *,
location_t loc,
struct c_expr);
+static tree c_parser_transaction (c_parser *, enum rid);
+static struct c_expr c_parser_transaction_expression (c_parser *, enum
rid);
+static tree c_parser_transaction_cancel (c_parser *);
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
@@ -3365,6 +3371,66 @@ c_parser_simple_asm_expr (c_parser *pars
return str;
}
+static tree
+c_parser_attribute_any_word (c_parser *parser)
+{
+ tree attr_name = NULL_TREE;
+
+ if (c_parser_next_token_is (parser, CPP_KEYWORD))
+ {
+ /* ??? See comment above about what keywords are accepted here. */
+ bool ok;
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_STATIC:
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_INT128:
+ case RID_CONST:
+ case RID_EXTERN:
+ case RID_REGISTER:
+ case RID_TYPEDEF:
+ case RID_SHORT:
+ case RID_INLINE:
+ case RID_NORETURN:
+ case RID_VOLATILE:
+ case RID_SIGNED:
+ case RID_AUTO:
+ case RID_RESTRICT:
+ case RID_COMPLEX:
+ case RID_THREAD:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_DFLOAT32:
+ case RID_DFLOAT64:
+ case RID_DFLOAT128:
+ case RID_BOOL:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
+ case RID_TRANSACTION_ATOMIC:
+ case RID_TRANSACTION_CANCEL:
+ ok = true;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ return NULL_TREE;
+
+ /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
+ attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
+ }
+ else if (c_parser_next_token_is (parser, CPP_NAME))
+ attr_name = c_parser_peek_token (parser)->value;
+
+ return attr_name;
+}
+
/* Parse (possibly empty) attributes. This is a GNU extension.
attributes:
@@ -3425,57 +3491,10 @@ c_parser_attributes (c_parser *parser)
c_parser_consume_token (parser);
continue;
}
- if (c_parser_next_token_is (parser, CPP_KEYWORD))
- {
- /* ??? See comment above about what keywords are
- accepted here. */
- bool ok;
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_STATIC:
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_INT128:
- case RID_CONST:
- case RID_EXTERN:
- case RID_REGISTER:
- case RID_TYPEDEF:
- case RID_SHORT:
- case RID_INLINE:
- case RID_NORETURN:
- case RID_VOLATILE:
- case RID_SIGNED:
- case RID_AUTO:
- case RID_RESTRICT:
- case RID_COMPLEX:
- case RID_THREAD:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- case RID_BOOL:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- ok = true;
- break;
- default:
- ok = false;
- break;
- }
- if (!ok)
- break;
- /* Accept __attribute__((__const)) as __attribute__((const))
- etc. */
- attr_name
- = ridpointers[(int) c_parser_peek_token (parser)->keyword];
- }
- else
- attr_name = c_parser_peek_token (parser)->value;
+
+ attr_name = c_parser_attribute_any_word (parser);
+ if (attr_name == NULL)
+ break;
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
{
@@ -4346,7 +4365,14 @@ c_parser_label (c_parser *parser)
atomic-directive expression-statement
ordered-construct:
- ordered-directive structured-block */
+ ordered-directive structured-block
+
+ Transactional Memory:
+
+ statement:
+ transaction-statement
+ transaction-cancel-statement
+*/
static void
c_parser_statement (c_parser *parser)
@@ -4437,6 +4463,14 @@ c_parser_statement_after_labels (c_parse
case RID_ASM:
stmt = c_parser_asm_statement (parser);
break;
+ case RID_TRANSACTION_ATOMIC:
+ case RID_TRANSACTION_RELAXED:
+ stmt = c_parser_transaction (parser,
+ c_parser_peek_token (parser)->keyword);
+ break;
+ case RID_TRANSACTION_CANCEL:
+ stmt = c_parser_transaction_cancel (parser);
+ goto expect_semicolon;
case RID_AT_THROW:
gcc_assert (c_dialect_objc ());
c_parser_consume_token (parser);
@@ -5762,6 +5796,11 @@ c_parser_cast_expression (c_parser *pars
unary-operator: one of
__extension__ __real__ __imag__
+ Transactional Memory:
+
+ unary-expression:
+ transaction-expression
+
In addition, the GNU syntax treats ++ and -- as unary operators, so
they may be applied to cast expressions with errors for non-lvalues
given later. */
@@ -5869,6 +5908,10 @@ c_parser_unary_expression (c_parser *par
op = c_parser_cast_expression (parser, NULL);
op = default_function_array_conversion (exp_loc, op);
return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+ case RID_TRANSACTION_ATOMIC:
+ case RID_TRANSACTION_RELAXED:
+ return c_parser_transaction_expression (parser,
+ c_parser_peek_token (parser)->keyword);
default:
return c_parser_postfix_expression (parser);
}
@@ -10469,6 +10512,212 @@ c_parser_omp_threadprivate (c_parser *pa
c_parser_skip_to_pragma_eol (parser);
}
+/* Parse a transaction attribute (GCC Extension).
+
+ transaction-attribute:
+ attributes
+ [ [ any-word ] ]
+
+ The transactional memory language description is written for C++,
+ and uses the C++0x attribute syntax. For compatibility, allow the
+ bracket style for transactions in C as well. */
+
+static tree
+c_parser_transaction_attributes (c_parser *parser)
+{
+ tree attr_name, attr = NULL;
+
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ return c_parser_attributes (parser);
+
+ if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ return NULL_TREE;
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+ goto error1;
+
+ attr_name = c_parser_attribute_any_word (parser);
+ if (attr_name)
+ {
+ c_parser_consume_token (parser);
+ attr = build_tree_list (attr_name, NULL_TREE);
+ }
+ else
+ c_parser_error (parser, "expected identifier");
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+ error1:
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+ return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement
+ (GCC Extension).
+
+ transaction-statement:
+ __transaction_atomic attributes[opt] compound-statement
+ __transaction_relaxed compound-statement
+
+ Note that the only valid attribute is: "outer".
+*/
+
+static tree
+c_parser_transaction (c_parser *parser, enum rid keyword)
+{
+ unsigned int old_in = parser->in_transaction;
+ unsigned int this_in = 1, new_in;
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree stmt, attrs;
+
+ gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+ || keyword == RID_TRANSACTION_RELAXED)
+ && c_parser_next_token_is_keyword (parser, keyword));
+ c_parser_consume_token (parser);
+
+ if (keyword == RID_TRANSACTION_RELAXED)
+ this_in |= TM_STMT_ATTR_RELAXED;
+ else
+ {
+ attrs = c_parser_transaction_attributes (parser);
+ if (attrs)
+ this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+ }
+
+ /* Keep track if we're in the lexical scope of an outer transaction. */
+ new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+ parser->in_transaction = new_in;
+ stmt = c_parser_compound_statement (parser);
+ parser->in_transaction = old_in;
+
+ if (flag_tm)
+ stmt = c_finish_transaction (loc, stmt, this_in);
+ else
+ error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+ "%<__transaction_atomic%> without transactional memory support
enabled"
+ : "%<__transaction_relaxed %> "
+ "without transactional memory support enabled"));
+
+ return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression
+ (GCC Extension).
+
+ transaction-expression:
+ __transaction_atomic ( expression )
+ __transaction_relaxed ( expression )
+*/
+
+static struct c_expr
+c_parser_transaction_expression (c_parser *parser, enum rid keyword)
+{
+ struct c_expr ret;
+ unsigned int old_in = parser->in_transaction;
+ unsigned int this_in = 1;
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree attrs;
+
+ gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+ || keyword == RID_TRANSACTION_RELAXED)
+ && c_parser_next_token_is_keyword (parser, keyword));
+ c_parser_consume_token (parser);
+
+ if (keyword == RID_TRANSACTION_RELAXED)
+ this_in |= TM_STMT_ATTR_RELAXED;
+ else
+ {
+ attrs = c_parser_transaction_attributes (parser);
+ if (attrs)
+ this_in |= parse_tm_stmt_attr (attrs, 0);
+ }
+
+ parser->in_transaction = this_in;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree expr = c_parser_expression (parser).value;
+ ret.original_type = TREE_TYPE (expr);
+ ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
+ if (this_in & TM_STMT_ATTR_RELAXED)
+ TRANSACTION_EXPR_RELAXED (ret.value) = 1;
+ SET_EXPR_LOCATION (ret.value, loc);
+ ret.original_code = TRANSACTION_EXPR;
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<(%>");
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
+ }
+ parser->in_transaction = old_in;
+
+ if (!flag_tm)
+ error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+ "%<__transaction_atomic%> without transactional memory support
enabled"
+ : "%<__transaction_relaxed %> "
+ "without transactional memory support enabled"));
+
+ return ret;
+}
+
+/* Parse a __transaction_cancel statement (GCC Extension).
+
+ transaction-cancel-statement:
+ __transaction_cancel attributes[opt] ;
+
+ Note that the only valid attribute is "outer".
+*/
+
+static tree
+c_parser_transaction_cancel(c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree attrs;
+ bool is_outer = false;
+
+ gcc_assert (c_parser_next_token_is_keyword (parser,
RID_TRANSACTION_CANCEL));
+ c_parser_consume_token (parser);
+
+ attrs = c_parser_transaction_attributes (parser);
+ if (attrs)
+ is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+ if (!flag_tm)
+ {
+ error_at (loc, "%<__transaction_cancel%> without "
+ "transactional memory support enabled");
+ goto ret_error;
+ }
+ else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+ {
+ error_at (loc, "%<__transaction_cancel%> within a "
+ "%<__transaction_relaxed%>");
+ goto ret_error;
+ }
+ else if (is_outer)
+ {
+ if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+ && !is_tm_may_cancel_outer (current_function_decl))
+ {
+ error_at (loc, "outer %<__transaction_cancel%> not "
+ "within outer %<__transaction_atomic%>");
+ error_at (loc, " or a %<transaction_may_cancel_outer%> function");
+ goto ret_error;
+ }
+ }
+ else if (parser->in_transaction == 0)
+ {
+ error_at (loc, "%<__transaction_cancel%> not within "
+ "%<__transaction_atomic%>");
+ goto ret_error;
+ }
+
+ return add_stmt (build_tm_abort_call (loc, is_outer));
+
+ ret_error:
+ return build1 (NOP_EXPR, void_type_node, error_mark_node);
+}
/* Parse a single source file. */
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h (.../trunk) (revision 180744)
+++ gcc/c-tree.h (.../branches/transactional-memory) (revision
180773)
@@ -595,6 +595,7 @@ extern tree c_begin_omp_task (void);
extern tree c_finish_omp_task (location_t, tree, tree);
extern tree c_finish_omp_clauses (tree);
extern tree c_build_va_arg (location_t, tree, tree);
+extern tree c_finish_transaction (location_t, tree, int);
extern tree c_build_vec_perm_expr (location_t, tree, tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c (.../trunk) (revision 180744)
+++ gcc/c-typeck.c (.../branches/transactional-memory) (revision
180773)
@@ -2716,6 +2716,9 @@ build_function_call_vec (location_t loc,
return tem;
name = DECL_NAME (function);
+
+ if (flag_tm)
+ tm_malloc_replacement (function);
fundecl = function;
}
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
@@ -10921,6 +10924,19 @@ c_finish_omp_clauses (tree clauses)
return clauses;
}
+/* Create a transaction node. */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+ tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+ if (flags & TM_STMT_ATTR_OUTER)
+ TRANSACTION_EXPR_OUTER (stmt) = 1;
+ if (flags & TM_STMT_ATTR_RELAXED)
+ TRANSACTION_EXPR_RELAXED (stmt) = 1;
+ return add_stmt (stmt);
+}
+
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c (.../trunk) (revision 180744)
+++ gcc/c-family/c-common.c (.../branches/transactional-memory)
(revision 180773)
@@ -357,6 +357,8 @@ static tree handle_returns_twice_attribu
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
static tree handle_deprecated_attribute (tree *, tree, tree, int,
bool *);
@@ -372,6 +374,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 tree handle_no_split_stack_attribute (tree *, tree, tree, int,
bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
@@ -472,6 +475,9 @@ const struct c_common_resword c_common_r
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
{ "__thread", RID_THREAD, 0 },
+ { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 },
+ { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 },
+ { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
@@ -664,6 +670,20 @@ const struct attribute_spec c_common_att
handle_no_limit_stack_attribute, false },
{ "pure", 0, 0, true, false, false,
handle_pure_attribute, false },
+ { "transaction_callable", 0, 0, false, true, false,
+ handle_tm_attribute, false },
+ { "transaction_unsafe", 0, 0, false, true, false,
+ handle_tm_attribute, false },
+ { "transaction_safe", 0, 0, false, true, false,
+ handle_tm_attribute, false },
+ { "transaction_may_cancel_outer", 0, 0, false, true, false,
+ handle_tm_attribute, false },
+ /* ??? These two attributes didn't make the transition from the
+ Intel language document to the multi-vendor language document. */
+ { "transaction_pure", 0, 0, false, true, false,
+ handle_tm_attribute, false },
+ { "transaction_wrap", 1, 1, true, false, false,
+ handle_tm_wrap_attribute, false },
/* For internal use (marking of builtins) only. The name contains space
to prevent its usage in source code. */
{ "no vops", 0, 0, true, false, false,
@@ -705,6 +725,10 @@ const struct attribute_spec c_common_att
handle_target_attribute, false },
{ "optimize", 1, -1, true, false, false,
handle_optimize_attribute, false },
+ /* 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, false },
{ "no_split_stack", 0, 0, true, false, false,
handle_no_split_stack_attribute, false },
/* For internal use (marking of builtins and runtime functions) only.
@@ -7290,6 +7314,223 @@ handle_pure_attribute (tree *node, tree
return NULL_TREE;
}
+/* Digest an attribute list destined for a transactional memory statement.
+ ALLOWED is the set of attributes that are allowed for this statement;
+ return the attribute we parsed. Multiple attributes are never
allowed. */
+
+int
+parse_tm_stmt_attr (tree attrs, int allowed)
+{
+ tree a_seen = NULL;
+ int m_seen = 0;
+
+ for ( ; attrs ; attrs = TREE_CHAIN (attrs))
+ {
+ tree a = TREE_PURPOSE (attrs);
+ int m = 0;
+
+ if (is_attribute_p ("outer", a))
+ m = TM_STMT_ATTR_OUTER;
+
+ if ((m & allowed) == 0)
+ {
+ warning (OPT_Wattributes, "%qE attribute directive ignored", a);
+ continue;
+ }
+
+ if (m_seen == 0)
+ {
+ a_seen = a;
+ m_seen = m;
+ }
+ else if (m_seen == m)
+ warning (OPT_Wattributes, "%qE attribute duplicated", a);
+ else
+ warning (OPT_Wattributes, "%qE attribute follows %qE", a, a_seen);
+ }
+
+ return m_seen;
+}
+
+/* Transform a TM attribute name into a maskable integer and back.
+ Note that NULL (i.e. no attribute) is mapped to UNKNOWN, corresponding
+ to how the lack of an attribute is treated. */
+
+int
+tm_attr_to_mask (tree attr)
+{
+ if (attr == NULL)
+ return 0;
+ if (is_attribute_p ("transaction_safe", attr))
+ return TM_ATTR_SAFE;
+ if (is_attribute_p ("transaction_callable", attr))
+ return TM_ATTR_CALLABLE;
+ if (is_attribute_p ("transaction_pure", attr))
+ return TM_ATTR_PURE;
+ if (is_attribute_p ("transaction_unsafe", attr))
+ return TM_ATTR_IRREVOCABLE;
+ if (is_attribute_p ("transaction_may_cancel_outer", attr))
+ return TM_ATTR_MAY_CANCEL_OUTER;
+ return 0;
+}
+
+tree
+tm_mask_to_attr (int mask)
+{
+ const char *str;
+ switch (mask)
+ {
+ case TM_ATTR_SAFE:
+ str = "transaction_safe";
+ break;
+ case TM_ATTR_CALLABLE:
+ str = "transaction_callable";
+ break;
+ case TM_ATTR_PURE:
+ str = "transaction_pure";
+ break;
+ case TM_ATTR_IRREVOCABLE:
+ str = "transaction_unsafe";
+ break;
+ case TM_ATTR_MAY_CANCEL_OUTER:
+ str = "transaction_may_cancel_outer";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return get_identifier (str);
+}
+
+/* Return the first TM attribute seen in LIST. */
+
+tree
+find_tm_attribute (tree list)
+{
+ for (; list ; list = TREE_CHAIN (list))
+ {
+ tree name = TREE_PURPOSE (list);
+ if (tm_attr_to_mask (name) != 0)
+ return name;
+ }
+ return NULL_TREE;
+}
+
+/* Handle the TM attributes; arguments as in struct attribute_spec.handler.
+ Here we accept only function types, and verify that none of the other
+ function TM attributes are also applied. */
+/* ??? We need to accept class types for C++, but not C. This greatly
+ complicates this function, since we can no longer rely on the extra
+ processing given by function_type_required. */
+
+static tree
+handle_tm_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ /* Only one path adds the attribute; others don't. */
+ *no_add_attrs = true;
+
+ switch (TREE_CODE (*node))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ /* Only tm_callable and tm_safe apply to classes. */
+ if (tm_attr_to_mask (name) & ~(TM_ATTR_SAFE | TM_ATTR_CALLABLE))
+ goto ignored;
+ /* FALLTHRU */
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node));
+ if (old_name == name)
+ ;
+ else if (old_name != NULL_TREE)
+ error ("type was previously declared %qE", old_name);
+ else
+ *no_add_attrs = false;
+ }
+ break;
+
+ case POINTER_TYPE:
+ {
+ enum tree_code subcode = TREE_CODE (TREE_TYPE (*node));
+ if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
+ {
+ tree fn_tmp = TREE_TYPE (*node);
+ decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
+ *node = build_pointer_type (fn_tmp);
+ break;
+ }
+ }
+ /* FALLTHRU */
+
+ default:
+ /* If a function is next, pass it on to be tried next. */
+ if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+ return tree_cons (name, args, NULL);
+
+ ignored:
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle the TM_WRAP attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_tm_wrap_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree decl = *node;
+
+ /* We don't need the attribute even on success, since we
+ record the entry in an external table. */
+ *no_add_attrs = true;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ else
+ {
+ tree wrap_decl = TREE_VALUE (args);
+ if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
+ && TREE_CODE (wrap_decl) != VAR_DECL
+ && TREE_CODE (wrap_decl) != FUNCTION_DECL)
+ error ("%qE argument not an identifier", name);
+ else
+ {
+ if (TREE_CODE (wrap_decl) == IDENTIFIER_NODE)
+ wrap_decl = lookup_name (wrap_decl);
+ if (wrap_decl && TREE_CODE (wrap_decl) == FUNCTION_DECL)
+ {
+ if (lang_hooks.types_compatible_p (TREE_TYPE (decl),
+ TREE_TYPE (wrap_decl)))
+ record_tm_replacement (wrap_decl, decl);
+ else
+ error ("%qD is not compatible with %qD", wrap_decl, decl);
+ }
+ else
+ error ("transaction_wrap argument is not a function");
+ }
+ }
+
+ 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 * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
/* Handle a "no vops" attribute; arguments as in
struct attribute_spec.handler. */
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h (.../trunk) (revision 180744)
+++ gcc/c-family/c-common.h (.../branches/transactional-memory)
(revision 180773)
@@ -110,6 +110,9 @@ enum rid
as a normal identifier. */
RID_CXX_COMPAT_WARN,
+ /* GNU transactional memory extension */
+ RID_TRANSACTION_ATOMIC, RID_TRANSACTION_RELAXED, RID_TRANSACTION_CANCEL,
+
/* Too many ways of getting the name of a function as a string */
RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
@@ -1068,6 +1071,28 @@ c_tree_chain_next (tree t)
return NULL;
}
+/* Mask used by tm_stmt_attr. */
+#define TM_STMT_ATTR_OUTER 2
+#define TM_STMT_ATTR_ATOMIC 4
+#define TM_STMT_ATTR_RELAXED 8
+
+extern int parse_tm_stmt_attr (tree, int);
+
+/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these
+ are ordered specifically such that more restrictive attributes are
+ at lower bit positions. This fact is known by the C++ tm attribute
+ inheritance code such that least bit extraction (mask & -mask) results
+ in the most restrictive attribute. */
+#define TM_ATTR_SAFE 1
+#define TM_ATTR_CALLABLE 2
+#define TM_ATTR_PURE 4
+#define TM_ATTR_IRREVOCABLE 8
+#define TM_ATTR_MAY_CANCEL_OUTER 16
+
+extern int tm_attr_to_mask (tree);
+extern tree tm_mask_to_attr (int);
+extern tree find_tm_attribute (tree);
+
/* A suffix-identifier value doublet that represents user-defined literals
for C++-0x. */
struct GTY(()) tree_userdef_literal {
Index: gcc/builtin-attrs.def
===================================================================
--- gcc/builtin-attrs.def (.../trunk) (revision 180744)
+++ gcc/builtin-attrs.def (.../branches/transactional-memory) (revision
180773)
@@ -96,6 +96,8 @@ 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_IDENT (ATTR_TM_TMPURE, "transaction_pure")
DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
@@ -227,6 +229,26 @@ 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_TMPURE_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_TMPURE_NOTHROW_LIST,
+ ATTR_PURE, ATTR_NULL, ATTR_TM_TMPURE_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_CONST_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
+
+/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown
in. */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+/* Same attributes used for BUILT_IN_FREE except with TM_PURE thrown
in. */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_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, \
Index: gcc/print-tree.c
===================================================================
--- gcc/print-tree.c (.../trunk) (revision 180744)
+++ gcc/print-tree.c (.../branches/transactional-memory) (revision
180773)
@@ -424,6 +424,8 @@ print_node (FILE *file, const char *pref
fputs (" built-in", file);
if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
fputs (" static-chain", file);
+ if (TREE_CODE (node) == FUNCTION_DECL && DECL_IS_TM_CLONE (node))
+ fputs (" tm-clone", file);
if (code == FIELD_DECL && DECL_PACKED (node))
fputs (" packed", file);
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (.../trunk) (revision 180744)
+++ gcc/common.opt (.../branches/transactional-memory) (revision
180773)
@@ -1190,6 +1190,10 @@ floop-block
Common Report Var(flag_loop_block) Optimization
Enable Loop Blocking transformation
+fgnu-tm
+Common Report Var(flag_tm)
+Enable support for GNU transactional memory
+
floop-flatten
Common Report Var(flag_loop_flatten) Optimization
Enable Loop Flattening transformation
Index: gcc/gtm-builtins.def
===================================================================
--- gcc/gtm-builtins.def (.../trunk) (revision 0)
+++ gcc/gtm-builtins.def (.../branches/transactional-memory) (revision
180773)
@@ -0,0 +1,208 @@
+DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction",
+ BT_FN_UINT_UINT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction",
+ BT_FN_VOID, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT_EH, "_ITM_commitTransactionEH",
+ BT_FN_VOID_PTR, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_ABORT, "_ITM_abortTransaction",
+ BT_FN_INT, ATTR_TM_NORETURN_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_IRREVOCABLE, "_ITM_changeTransactionMode",
+ BT_FN_INT_INT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY, "_ITM_memcpyRtWt",
+ BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMMOVE, "_ITM_memmoveRtWt",
+ BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMSET, "_ITM_memsetW",
+ BT_FN_PTR_PTR_INT_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_IRR, "_ITM_getTMCloneOrIrrevocable",
+ BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe",
+ BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+
+/* Memory allocation builtins. */
+DEF_TM_BUILTIN (BUILT_IN_TM_MALLOC, "_ITM_malloc",
+ BT_FN_PTR_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_CALLOC, "_ITM_calloc",
+ BT_FN_PTR_SIZE_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_FREE, "_ITM_free",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LIST)
+
+/* Logging builtins. */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_1, "_ITM_LU1",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_2, "_ITM_LU2",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_4, "_ITM_LU4",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_8, "_ITM_LU8",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_FLOAT, "_ITM_LF",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_DOUBLE, "_ITM_LD",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_LDOUBLE, "_ITM_LE",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG, "_ITM_LB",
+ BT_FN_VOID_VPTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M64, "__builtin__ITM_LM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M128, "__builtin__ITM_LM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M256, "__builtin__ITM_LM256")
+
+/* Writes.
+
+ Note: The writes must follow the following order: STORE, WAR, WAW.
+ The TM optimizations depend on this order.
+
+ BUILT_IN_TM_STORE_1 must be the first builtin.
+ BUILTIN_TM_LOAD_STORE_P depends on this. */
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_1, "_ITM_WU1",
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_1, "_ITM_WaRU1",
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_1, "_ITM_WaWU1",
+ 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_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_2, "_ITM_WaRU2",
+ BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_2, "_ITM_WaWU2",
+ 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_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_4, "_ITM_WaRU4",
+ BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_4, "_ITM_WaWU4",
+ 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_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_8, "_ITM_WaRU8",
+ BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_8, "_ITM_WaWU8",
+ 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_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_FLOAT, "_ITM_WaRF",
+ BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_FLOAT, "_ITM_WaWF",
+ 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_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_DOUBLE, "_ITM_WaRD",
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_DOUBLE, "_ITM_WaWD",
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M64, "__builtin__ITM_WM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M64, "__builtin__ITM_WaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M64, "__builtin__ITM_WaWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M128, "__builtin__ITM_WM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M128, "__builtin__ITM_WaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M128, "__builtin__ITM_WaWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M256, "__builtin__ITM_WM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M256, "__builtin__ITM_WaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M256, "__builtin__ITM_WaWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBLE, "_ITM_WE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_LDOUBLE, "_ITM_WaRE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_LDOUBLE, "_ITM_WaWE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+/* Note: BUILT_IN_TM_STORE_WAW_LDOUBLE must be the last TM store.
+ BUILTIN_TM_STORE_P depends on this. */
+
+/* Reads.
+
+ Note: The reads must follow the following order: LOAD, RAR, RAW, RFW.
+ The TM optimizations depend on this order. */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_1, "_ITM_RaRU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_1, "_ITM_RaWU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_1, "_ITM_RfWU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_2, "_ITM_RaRU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_2, "_ITM_RaWU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_2, "_ITM_RfWU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_4, "_ITM_RaRU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_4, "_ITM_RaWU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_4, "_ITM_RfWU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_8, "_ITM_RaRU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_8, "_ITM_RaWU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_8, "_ITM_RfWU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_FLOAT, "_ITM_RaRF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_FLOAT, "_ITM_RaWF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_FLOAT, "_ITM_RfWF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD",
+ BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_DOUBLE, "_ITM_RaRD",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_DOUBLE, "_ITM_RaWD",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_DOUBLE, "_ITM_RfWD",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M64, "__builtin__ITM_RM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M64, "__builtin__ITM_RfWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M128, "__builtin__ITM_RM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M128, "__builtin__ITM_RfWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M256, "__builtin__ITM_RM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M256, "__builtin__ITM_RfWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_LDOUBLE, "_ITM_RaRE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_LDOUBLE, "_ITM_RaWE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_LDOUBLE, "_ITM_RfWE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* Note: BUILT_IN_TM_LOAD_RFW_LDOUBLE must be the last TM load as well
+ as the last builtin. BUILTIN_TM_LOAD_STORE_P and BUILTIN_TM_LOAD_P
+ depend on this. */
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c (.../trunk) (revision 180744)
+++ gcc/tree-pretty-print.c (.../branches/transactional-memory)
(revision 180773)
@@ -2264,6 +2264,26 @@ dump_generic_node (pretty_printer *buffe
is_expr = false;
break;
+ case TRANSACTION_EXPR:
+ if (TRANSACTION_EXPR_OUTER (node))
+ pp_string (buffer, "__transaction_atomic [[outer]]");
+ else if (TRANSACTION_EXPR_RELAXED (node))
+ pp_string (buffer, "__transaction_relaxed");
+ else
+ pp_string (buffer, "__transaction_atomic");
+ if (!(flags & TDF_SLIM) && TRANSACTION_EXPR_BODY (node))
+ {
+ newline_and_indent (buffer, spc);
+ pp_character (buffer, '{');
+ newline_and_indent (buffer, spc + 2);
+ dump_generic_node (buffer, TRANSACTION_EXPR_BODY (node),
+ spc + 2, flags, false);
+ newline_and_indent (buffer, spc);
+ pp_character (buffer, '}');
+ }
+ is_expr = false;
+ break;
+
case REDUC_MAX_EXPR:
pp_string (buffer, " REDUC_MAX_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags,
false);
Index: gcc/target.def
===================================================================
--- gcc/target.def (.../trunk) (revision 180744)
+++ gcc/target.def (.../branches/transactional-memory) (revision
180773)
@@ -1003,6 +1003,22 @@ DEFHOOK
(enum machine_mode mode, const_tree type, int misalignment, bool
is_packed),
default_builtin_support_vector_misalignment)
+/* Return the builtin decl needed to load a vector of TYPE. */
+DEFHOOK
+(builtin_tm_load,
+ "",
+ tree,
+ (tree),
+ default_builtin_tm_load_store)
+
+/* Return the builtin decl needed to store a vector of TYPE. */
+DEFHOOK
+(builtin_tm_store,
+ "",
+ tree,
+ (tree),
+ default_builtin_tm_load_store)
+
/* Returns the preferred mode for SIMD operations for the specified
scalar mode. */
DEFHOOK
Index: gcc/tree.def
===================================================================
--- gcc/tree.def (.../trunk) (revision 180744)
+++ gcc/tree.def (.../branches/transactional-memory) (revision
180773)
@@ -1076,6 +1076,10 @@ DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "om
/* OpenMP clauses. */
DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0)
+/* TRANSACTION_EXPR tree code.
+ Operand 0: BODY: contains body of the transaction. */
+DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1)
+
/* Reduction operations.
Operations that take a vector of elements and "reduce" it to a scalar
result (e.g. summing the elements of the vector, finding the
minimum over