From patchwork Thu Nov 3 19:03:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 16/n: trans-mem: compiler parser/front-end Date: Thu, 03 Nov 2011 09:03:36 -0000 From: Aldy Hernandez X-Patchwork-Id: 123495 Message-Id: <4EB2E588.1040806@redhat.com> To: gcc-patches Parser and some front-end stuff, like tree definitions, etc. minimum over 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 % 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