Hello everyone, We are working on the project to not allow memory_order_consume gets automatically promoted to memory_order_acquire. In implementing memory_order_consume, the problem comes when tracing dependencies at the C/C++ source level. We are first targeting to trace the dependencies only for the pointer types at C source level. To mark the pointers at C source level, we thought of introducing a new qualifier _Dependent_ptr, for only pointer type variables. We believe adding this qualifier will allow us to trace dependencies and not break any of the pointer optimizations.
For start, we have implemented the _Dependent_ptr qualifier in the GCC C front-end. The patch is given in this link: https://github.com/AKG001/gcc/commit/fb4187bc3872a50880159232cf336f0a03505fa8 and given below also. We have also prepared some testcases for checking whether _Dependent_ptr parses correctly or not. A simple test case is present on this https://github.com/AKG001/gcc/commit/193a040df649d773fab5cb5e2698e9729dfd2b97 Some litmus test cases from the document ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf) are present in this commit https://github.com/AKG001/gcc/commit/b4c3c55b11597bde8ea5b297343ab349caedb6a4 For litmus test cases, the file name convention is: <document name>_<figure in the document>.c Full set of testcases are present in this repository https://github.com/AKG001/test/. The .original files are also present for each test case. Command used to generate .original file: ./<build directory where cc1 is>cc1 -fdump-tree-original <file name>.c We request the community to give us their valuable feedback. Also, let us know if something is wrong or can be done in a better way. Thanks, Akshat ------------------------------------------------------------------------------------------------------------------------------------------------------- commit fb4187bc3872a50880159232cf336f0a03505fa8 Author: Akshat Garg <xks...@gmail.com> Date: Sat Jun 8 15:06:23 2019 +0530 Add _Dependent_ptr qualifier diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 4057be3..6d37851 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -345,6 +345,7 @@ const struct c_common_resword c_common_reswords[] = { "_Alignas", RID_ALIGNAS, D_CONLY }, { "_Alignof", RID_ALIGNOF, D_CONLY }, { "_Atomic", RID_ATOMIC, D_CONLY }, + { "_Dependent_ptr", RID_DEPENDENT_PTR, 0 }, { "_Bool", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, @@ -7845,6 +7846,7 @@ keyword_is_type_qualifier (enum rid keyword) case RID_VOLATILE: case RID_RESTRICT: case RID_ATOMIC: + case RID_DEPENDENT_PTR: return true; default: return false; diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 1cf2cae..a4c7e03 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -68,7 +68,7 @@ enum rid RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN, RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE, RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT, - RID_NORETURN, RID_ATOMIC, + RID_NORETURN, RID_ATOMIC, RID_DEPENDENT_PTR, /* C extensions */ RID_COMPLEX, RID_THREAD, RID_SAT, diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index b10599f..3ac3a21 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -3189,6 +3189,7 @@ check_format_types (const substring_loc &fmt_loc, && (TYPE_READONLY (cur_type) || TYPE_VOLATILE (cur_type) || TYPE_ATOMIC (cur_type) + || TYPE_DEPENDENT_PTR (cur_type) || TYPE_RESTRICT (cur_type))) warning (OPT_Wformat_, "extra type qualifiers in format " "argument (argument %d)", diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index 3e25624..e034a8f 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -181,6 +181,8 @@ pp_c_cv_qualifiers (c_pretty_printer *pp, int qualifiers, bool func_type) if (qualifiers & TYPE_QUAL_ATOMIC) pp_c_ws_string (pp, "_Atomic"); + if (qualifiers & TYPE_QUAL_DEPENDENT_PTR) + pp_c_ws_string (pp, "_Dependent_ptr"); if (qualifiers & TYPE_QUAL_CONST) pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const"); if (qualifiers & TYPE_QUAL_VOLATILE) diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c index 96bb2e2..6632447 100644 --- a/gcc/c/c-aux-info.c +++ b/gcc/c/c-aux-info.c @@ -284,6 +284,8 @@ gen_type (const char *ret_val, tree t, formals_style style) case POINTER_TYPE: if (TYPE_ATOMIC (t)) ret_val = concat ("_Atomic ", ret_val, NULL); + if (TYPE_DEPENDENT_PTR (t)) + ret_val = concat ("_Dependent_ptr ", ret_val, NULL); if (TYPE_READONLY (t)) ret_val = concat ("const ", ret_val, NULL); if (TYPE_VOLATILE (t)) @@ -427,6 +429,8 @@ gen_type (const char *ret_val, tree t, formals_style style) } if (TYPE_ATOMIC (t)) ret_val = concat ("_Atomic ", ret_val, NULL); + if (TYPE_DEPENDENT_PTR (t)) + ret_val = concat ("_Dependent_ptr ", ret_val, NULL); if (TYPE_READONLY (t)) ret_val = concat ("const ", ret_val, NULL); if (TYPE_VOLATILE (t)) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 87ce853..91f0140 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -4540,6 +4540,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) && (declspecs->const_p || declspecs->volatile_p || declspecs->atomic_p + || declspecs->dependent_ptr_p || declspecs->restrict_p || declspecs->address_space)) { @@ -4668,6 +4669,7 @@ quals_from_declspecs (const struct c_declspecs *specs) | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0) | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0) | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0) + | (specs->dependent_ptr_p ? TYPE_QUAL_DEPENDENT_PTR : 0) | (ENCODE_QUAL_ADDR_SPACE (specs->address_space))); gcc_assert (!specs->type && !specs->decl_attr @@ -5833,6 +5835,7 @@ grokdeclarator (const struct c_declarator *declarator, int restrictp; int volatilep; int atomicp; + int dependent_ptrp; int type_quals = TYPE_UNQUALIFIED; tree name = NULL_TREE; bool funcdef_flag = false; @@ -5999,6 +6002,7 @@ grokdeclarator (const struct c_declarator *declarator, restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type); volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type); atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type); + dependent_ptrp = declspecs->dependent_ptr_p + TYPE_DEPENDENT_PTR (element_type); as1 = declspecs->address_space; as2 = TYPE_ADDR_SPACE (element_type); address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1; @@ -6011,6 +6015,8 @@ grokdeclarator (const struct c_declarator *declarator, pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>"); if (atomicp > 1) pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>"); + if (dependent_ptrp > 1) + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Dependent_ptr%>"); if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2) error_at (loc, "conflicting named address spaces (%s vs %s)", @@ -6027,6 +6033,7 @@ grokdeclarator (const struct c_declarator *declarator, | (restrictp ? TYPE_QUAL_RESTRICT : 0) | (volatilep ? TYPE_QUAL_VOLATILE : 0) | (atomicp ? TYPE_QUAL_ATOMIC : 0) + | (dependent_ptrp ? TYPE_QUAL_DEPENDENT_PTR : 0) | ENCODE_QUAL_ADDR_SPACE (address_space)); if (type_quals != TYPE_QUALS (element_type)) orig_qual_type = NULL_TREE; @@ -6038,6 +6045,13 @@ grokdeclarator (const struct c_declarator *declarator, if (declspecs->atomic_p && TREE_CODE (type) == ARRAY_TYPE) error_at (loc, "%<_Atomic%>-qualified array type"); + /* Applying the _Dependent_ptr qualifier to an array type (through the use + of typedefs or typeof) must be detected here. If the qualifier + is introduced later, any appearance of applying it to an array is + actually applying it to an element of that array. */ + if (declspecs->dependent_ptr_p && TREE_CODE (type) == ARRAY_TYPE) + error_at (loc, "%<_Dependent_ptr%>-qualified array type"); + /* Warn about storage classes that are invalid for certain kinds of declarations (parameters, typenames, etc.). */ @@ -7209,7 +7223,11 @@ grokdeclarator (const struct c_declarator *declarator, /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ int extern_ref = !initialized && storage_class == csc_extern; - + + /* _Dependent_ptr qualifier only reserved for pointer type variable */ + if ((type_quals & TYPE_QUAL_DEPENDENT_PTR) && (!POINTER_TYPE_P (type))) + error_at (loc, "invalid use of %<_Dependent_ptr%>"); + type = c_build_qualified_type (type, type_quals, orig_qual_type, orig_qual_indirect); @@ -10172,6 +10190,12 @@ declspecs_add_qual (location_t loc, prev_loc = specs->locations[cdw_atomic]; specs->locations[cdw_atomic] = loc; break; + case RID_DEPENDENT_PTR: + dupe = specs->dependent_ptr_p; + specs->dependent_ptr_p = true; + prev_loc = specs->locations[cdw_dependent_ptr]; + specs->locations[cdw_dependent_ptr] = loc; + break; default: gcc_unreachable (); } diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 84ee576..19412d2 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -498,6 +498,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_TYPEOF: case RID_CONST: case RID_ATOMIC: + case RID_DEPENDENT_PTR: case RID_VOLATILE: case RID_RESTRICT: case RID_ATTRIBUTE: @@ -601,6 +602,7 @@ c_token_is_qualifier (c_token *token) case RID_RESTRICT: case RID_ATTRIBUTE: case RID_ATOMIC: + case RID_DEPENDENT_PTR: return true; default: return false; @@ -682,6 +684,7 @@ c_token_starts_declspecs (c_token *token) case RID_SAT: case RID_ALIGNAS: case RID_ATOMIC: + case RID_DEPENDENT_PTR: case RID_AUTO_TYPE: return true; default: @@ -2860,6 +2863,11 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, else declspecs_add_qual (loc, specs, value); break; + case RID_DEPENDENT_PTR: + attrs_ok = true; + declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + break; case RID_CONST: case RID_VOLATILE: case RID_RESTRICT: @@ -4270,6 +4278,7 @@ c_parser_attribute_any_word (c_parser *parser) case RID_TRANSACTION_ATOMIC: case RID_TRANSACTION_CANCEL: case RID_ATOMIC: + case RID_DEPENDENT_PTR: case RID_AUTO_TYPE: case RID_INT_N_0: case RID_INT_N_1: diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 346f46a..7c67a63 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -279,6 +279,7 @@ enum c_declspec_word { cdw_volatile, cdw_restrict, cdw_atomic, + cdw_dependent_ptr, cdw_saturating, cdw_alignas, cdw_address_space, @@ -387,6 +388,8 @@ struct c_declspecs { BOOL_BITFIELD restrict_p : 1; /* Whether "_Atomic" was specified. */ BOOL_BITFIELD atomic_p : 1; + /* Whether "_Dependent_ptr" was specified. */ + BOOL_BITFIELD dependent_ptr_p : 1; /* Whether "_Sat" was specified. */ BOOL_BITFIELD saturating_p : 1; /* Whether any alignment specifier (even with zero alignment) was diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 81b66a1..68b210d 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -334,6 +334,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent, fputs (" readonly", file); if (TYPE_P (node) && TYPE_ATOMIC (node)) fputs (" atomic", file); + if (TYPE_P (node) && TYPE_DEPENDENT_PTR (node)) + fputs (" dependent_ptr", file); if (!TYPE_P (node) && TREE_CONSTANT (node)) fputs (" constant", file); else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node)) diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 26cfa7e..20d6b31 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -546,7 +546,8 @@ enum cv_qualifier { TYPE_QUAL_CONST = 0x1, TYPE_QUAL_VOLATILE = 0x2, TYPE_QUAL_RESTRICT = 0x4, - TYPE_QUAL_ATOMIC = 0x8 + TYPE_QUAL_ATOMIC = 0x8, + TYPE_QUAL_DEPENDENT_PTR = 0x10 }; /* Standard named or nameless data types of the C compiler. */ @@ -570,6 +571,8 @@ enum tree_index { TI_ATOMICDI_TYPE, TI_ATOMICTI_TYPE, + TI_DEPENDENT_PTR, + TI_UINT16_TYPE, TI_UINT32_TYPE, TI_UINT64_TYPE, @@ -973,7 +976,8 @@ struct GTY(()) tree_base { unsigned user_align : 1; unsigned nameless_flag : 1; unsigned atomic_flag : 1; - unsigned spare0 : 3; + unsigned dependent_ptr_flag : 1; + unsigned spare0 : 2; unsigned spare1 : 8; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 455579c..449906c 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1464,6 +1464,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, if (quals & TYPE_QUAL_ATOMIC) pp_string (pp, "atomic "); + if (quals & TYPE_QUAL_DEPENDENT_PTR) + pp_string (pp, "dependent_ptr "); if (quals & TYPE_QUAL_CONST) pp_string (pp, "const "); else if (quals & TYPE_QUAL_VOLATILE) @@ -1816,6 +1818,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, if (quals & TYPE_QUAL_ATOMIC) pp_string (pp, "atomic "); + if (quals & TYPE_QUAL_DEPENDENT_PTR) + pp_string (pp, "dependent_ptr "); if (quals & TYPE_QUAL_CONST) pp_string (pp, "const "); if (quals & TYPE_QUAL_VOLATILE) diff --git a/gcc/tree.c b/gcc/tree.c index 43ce44f..4bc3c8e 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6333,6 +6333,7 @@ set_type_quals (tree type, int type_quals) TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0; TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0; TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; + TYPE_DEPENDENT_PTR (type) = (type_quals & TYPE_QUAL_DEPENDENT_PTR) != 0; TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0; TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals); } diff --git a/gcc/tree.h b/gcc/tree.h index 5b50941..1e712dc 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2051,6 +2051,9 @@ extern machine_mode vector_type_mode (const_tree); /* Nonzero in a type considered atomic as a whole. */ #define TYPE_ATOMIC(NODE) (TYPE_CHECK (NODE)->base.u.bits.atomic_flag) +/* Nonzero in a type considered dependent_ptr as a whole. */ +#define TYPE_DEPENDENT_PTR(NODE) (TYPE_CHECK (NODE)->base.u.bits.dependent_ptr_flag) + /* Means this type is const-qualified. */ #define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag) @@ -2081,6 +2084,7 @@ extern machine_mode vector_type_mode (const_tree); ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \ | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \ | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \ + | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR) \ | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \ | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE))))) @@ -2089,6 +2093,7 @@ extern machine_mode vector_type_mode (const_tree); ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \ | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \ | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \ + | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR) \ | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))) /* The same as TYPE_QUALS without the address space and atomic @@ -3877,6 +3882,8 @@ tree_strip_any_location_wrapper (tree exp) #define atomicDI_type_node global_trees[TI_ATOMICDI_TYPE] #define atomicTI_type_node global_trees[TI_ATOMICTI_TYPE] +#define dependent_ptrTI_type_node global_trees[TI_DEPENDENT_PTR] + #define uint16_type_node global_trees[TI_UINT16_TYPE] #define uint32_type_node global_trees[TI_UINT32_TYPE] #define uint64_type_node global_trees[TI_UINT64_TYPE] --------------------------------------------------------------------------------------------------------------------------------------------------------------