diff --git a/.gcc.metadata b/.gcc.metadata deleted file mode 100644 index 2a15f01..0000000 --- a/.gcc.metadata +++ /dev/null @@ -1,3 +0,0 @@ -b7245af5eab1d4055b6590b6e4f5fb3b7f6c24bf SOURCES/gcc-8.5.0-20210514.tar.xz -3bdb3cc01fa7690a0e20ea5cfffcbe690f7665eb SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz -ce8eb83be0ac37fb5d5388df455a980fe37b4f13 SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz diff --git a/.gitignore b/.gitignore index b425f7a..1ebafbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -SOURCES/gcc-8.5.0-20210514.tar.xz -SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz -SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz +gcc-14.2.1-20250110.tar.xz +isl-0.24.tar.bz2 +newlib-cygwin-d45261f62a15f8abd94a1031020b9a9f455e4eed.tar.xz +nvptx-tools-87ce9dc5999e5fca2e1d3478a30888d9864c9804.tar.xz diff --git a/SOURCES/gcc8-RHEL-32886.patch b/SOURCES/gcc8-RHEL-32886.patch deleted file mode 100644 index 5ba9026..0000000 --- a/SOURCES/gcc8-RHEL-32886.patch +++ /dev/null @@ -1,59 +0,0 @@ -2024-04-18 Jakub Jelinek - - * tree-vect-stmts.c (vectorizable_call): For j == 0 use - vargs.safe_grow (nargs) rather than vargs.create (nargs), for j != 0 - remove vargs.truncate (0). Instead of vargs.quick_push store into - vargs[i]. Use vargs[i] instead of gimple_call_arg (new_stmt, i) - if j != 0. - - * gcc.c-torture/compile/20240418.c: New test. - ---- gcc/tree-vect-stmts.c.jj 2021-04-22 15:48:48.228178359 +0200 -+++ gcc/tree-vect-stmts.c 2024-04-18 13:21:46.104061529 +0200 -@@ -3242,9 +3242,7 @@ vectorizable_call (gimple *gs, gimple_st - { - /* Build argument list for the vectorized call. */ - if (j == 0) -- vargs.create (nargs); -- else -- vargs.truncate (0); -+ vargs.safe_grow (nargs); - - if (slp_node) - { -@@ -3252,7 +3250,7 @@ vectorizable_call (gimple *gs, gimple_st - vec vec_oprnds0; - - for (i = 0; i < nargs; i++) -- vargs.quick_push (gimple_call_arg (stmt, i)); -+ vargs[i] = gimple_call_arg (stmt, i); - vect_get_slp_defs (vargs, slp_node, &vec_defs); - vec_oprnds0 = vec_defs[0]; - -@@ -3314,13 +3312,10 @@ vectorizable_call (gimple *gs, gimple_st - vec_oprnd0 - = vect_get_vec_def_for_operand (op, stmt); - else -- { -- vec_oprnd0 = gimple_call_arg (new_stmt, i); -- vec_oprnd0 -- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0); -- } -+ vec_oprnd0 -+ = vect_get_vec_def_for_stmt_copy (dt[i], vargs[i]); - -- vargs.quick_push (vec_oprnd0); -+ vargs[i] = vec_oprnd0; - } - - if (gimple_call_internal_p (stmt) ---- gcc/testsuite/gcc.c-torture/compile/20240418.c.jj 2024-04-18 13:24:10.180065661 +0200 -+++ gcc/testsuite/gcc.c-torture/compile/20240418.c 2024-04-18 13:19:12.166194018 +0200 -@@ -0,0 +1,7 @@ -+void -+foo (signed char *p, unsigned long long *q) -+{ -+ int i; -+ for (i = 0; i <= 64; i++) -+ *p++ = __builtin_popcountll (*q++); -+} diff --git a/SOURCES/gcc8-Wbidi-chars.patch b/SOURCES/gcc8-Wbidi-chars.patch deleted file mode 100644 index 988defe..0000000 --- a/SOURCES/gcc8-Wbidi-chars.patch +++ /dev/null @@ -1,1644 +0,0 @@ -commit 51c500269bf53749b107807d84271385fad35628 -Author: Marek Polacek -Date: Wed Oct 6 14:33:59 2021 -0400 - - libcpp: Implement -Wbidi-chars for CVE-2021-42574 [PR103026] - - From a link below: - "An issue was discovered in the Bidirectional Algorithm in the Unicode - Specification through 14.0. It permits the visual reordering of - characters via control sequences, which can be used to craft source code - that renders different logic than the logical ordering of tokens - ingested by compilers and interpreters. Adversaries can leverage this to - encode source code for compilers accepting Unicode such that targeted - vulnerabilities are introduced invisibly to human reviewers." - - More info: - https://nvd.nist.gov/vuln/detail/CVE-2021-42574 - https://trojansource.codes/ - - This is not a compiler bug. However, to mitigate the problem, this patch - implements -Wbidi-chars=[none|unpaired|any] to warn about possibly - misleading Unicode bidirectional control characters the preprocessor may - encounter. - - The default is =unpaired, which warns about improperly terminated - bidirectional control characters; e.g. a LRE without its corresponding PDF. - The level =any warns about any use of bidirectional control characters. - - This patch handles both UCNs and UTF-8 characters. UCNs designating - bidi characters in identifiers are accepted since r204886. Then r217144 - enabled -fextended-identifiers by default. Extended characters in C/C++ - identifiers have been accepted since r275979. However, this patch still - warns about mixing UTF-8 and UCN bidi characters; there seems to be no - good reason to allow mixing them. - - We warn in different contexts: comments (both C and C++-style), string - literals, character constants, and identifiers. Expectedly, UCNs are ignored - in comments and raw string literals. The bidirectional control characters - can nest so this patch handles that as well. - - I have not included nor tested this at all with Fortran (which also has - string literals and line comments). - - Dave M. posted patches improving diagnostic involving Unicode characters. - This patch does not make use of this new infrastructure yet. - - PR preprocessor/103026 - - gcc/c-family/ChangeLog: - - * c.opt (Wbidi-chars, Wbidi-chars=): New option. - - gcc/ChangeLog: - - * doc/invoke.texi: Document -Wbidi-chars. - - libcpp/ChangeLog: - - * include/cpplib.h (enum cpp_bidirectional_level): New. - (struct cpp_options): Add cpp_warn_bidirectional. - (enum cpp_warning_reason): Add CPP_W_BIDIRECTIONAL. - * internal.h (struct cpp_reader): Add warn_bidi_p member - function. - * init.c (cpp_create_reader): Set cpp_warn_bidirectional. - * lex.c (bidi): New namespace. - (get_bidi_utf8): New function. - (get_bidi_ucn): Likewise. - (maybe_warn_bidi_on_close): Likewise. - (maybe_warn_bidi_on_char): Likewise. - (_cpp_skip_block_comment): Implement warning about bidirectional - control characters. - (skip_line_comment): Likewise. - (forms_identifier_p): Likewise. - (lex_identifier): Likewise. - (lex_string): Likewise. - (lex_raw_string): Likewise. - - gcc/testsuite/ChangeLog: - - * c-c++-common/Wbidi-chars-1.c: New test. - * c-c++-common/Wbidi-chars-2.c: New test. - * c-c++-common/Wbidi-chars-3.c: New test. - * c-c++-common/Wbidi-chars-4.c: New test. - * c-c++-common/Wbidi-chars-5.c: New test. - * c-c++-common/Wbidi-chars-6.c: New test. - * c-c++-common/Wbidi-chars-7.c: New test. - * c-c++-common/Wbidi-chars-8.c: New test. - * c-c++-common/Wbidi-chars-9.c: New test. - * c-c++-common/Wbidi-chars-10.c: New test. - * c-c++-common/Wbidi-chars-11.c: New test. - * c-c++-common/Wbidi-chars-12.c: New test. - * c-c++-common/Wbidi-chars-13.c: New test. - * c-c++-common/Wbidi-chars-14.c: New test. - * c-c++-common/Wbidi-chars-15.c: New test. - * c-c++-common/Wbidi-chars-16.c: New test. - * c-c++-common/Wbidi-chars-17.c: New test. - -diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt -index f591b39be5a..cf922812198 100644 ---- a/gcc/c-family/c.opt -+++ b/gcc/c-family/c.opt -@@ -334,6 +334,30 @@ Wbad-function-cast - C ObjC Var(warn_bad_function_cast) Warning - Warn about casting functions to incompatible types. - -+Wbidi-chars -+C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none) -+; -+ -+Wbidi-chars= -+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) -+-Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters. -+ -+; Required for these enum values. -+SourceInclude -+cpplib.h -+ -+Enum -+Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) -+ - Wbool-compare - C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) - Warn about boolean expression compared with an integer value different from true/false. -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 78ca7738df2..cc85c53aede 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -264,7 +264,8 @@ Objective-C and Objective-C++ Dialects}. - -Walloc-zero -Walloc-size-larger-than=@var{n} - -Walloca -Walloca-larger-than=@var{n} @gol - -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol ---Wno-attributes -Wbool-compare -Wbool-operation @gol -+-Wno-attributes -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol -+-Wbool-compare -Wbool-operation @gol - -Wno-builtin-declaration-mismatch @gol - -Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol - -Wc++-compat -Wc++11-compat -Wc++14-compat @gol -@@ -5606,6 +5607,23 @@ Warn about declarations using the @code{alias} and similar attributes whose - target is incompatible with the type of the alias. @xref{Function Attributes, - ,Declaring Attributes of Functions}. - -+@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} -+@opindex Wbidi-chars= -+@opindex Wbidi-chars -+@opindex Wno-bidi-chars -+Warn about possibly misleading UTF-8 bidirectional control characters in -+comments, string literals, character constants, and identifiers. Such -+characters can change left-to-right writing direction into right-to-left -+(and vice versa), which can cause confusion between the logical order and -+visual order. This may be dangerous; for instance, it may seem that a piece -+of code is not commented out, whereas it in fact is. -+ -+There are three levels of warning supported by GCC@. The default is -+@option{-Wbidi-chars=unpaired}, which warns about improperly terminated -+bidi contexts. @option{-Wbidi-chars=none} turns the warning off. -+@option{-Wbidi-chars=any} warns about any use of bidirectional control -+characters. -+ - @item -Wbool-compare - @opindex Wno-bool-compare - @opindex Wbool-compare -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-1.c b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c -new file mode 100644 -index 00000000000..34f5ac19271 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c -@@ -0,0 +1,12 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+ -+int main() { -+ int isAdmin = 0; -+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */ -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("You are an admin.\n"); -+ /* end admins only ‮ { ⁦*/ -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c -new file mode 100644 -index 00000000000..3f851b69e65 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c -@@ -0,0 +1,27 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* More nesting testing. */ -+ -+/* RLE‫ LRI⁦ PDF‬ PDI⁩*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int LRE_\u202a_PDF_\u202c; -+int LRE_\u202a_PDF_\u202c_LRE_\u202a_PDF_\u202c; -+int LRE_\u202a_LRI_\u2066_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLE_\u202b_RLI_\u2067_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLE_\u202b_RLI_\u2067_PDI_\u2069_PDF_\u202c; -+int FSI_\u2068_LRO_\u202d_PDI_\u2069_PDF_\u202c; -+int FSI_\u2068; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int FSI_\u2068_PDI_\u2069; -+int FSI_\u2068_FSI_\u2068_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDF_\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_FSI_\u2068_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c -new file mode 100644 -index 00000000000..44d044d82de ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c -@@ -0,0 +1,9 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test that we warn when mixing UCN and UTF-8. */ -+ -+const char *s1 = "LRE_‪_PDF_\u202c"; -+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */ -+const char *s2 = "LRE_\u202a_PDF_‬"; -+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-12.c b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c -new file mode 100644 -index 00000000000..b07eec1da91 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c -@@ -0,0 +1,19 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile { target { c || c++11 } } } */ -+/* { dg-options "-Wbidi-chars=any" } */ -+/* Test raw strings. */ -+ -+const char *s1 = R"(a b c LRE‪ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+const char *s2 = R"(a b c RLE‫ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+const char *s3 = R"(a b c LRO‭ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+const char *s4 = R"(a b c RLO‮ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+const char *s7 = R"(a b c FSI⁨ 1 2 3 PDI⁩ x y) z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+const char *s8 = R"(a b c PDI⁩ x y )z"; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+const char *s9 = R"(a b c PDF‬ x y z)"; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-13.c b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c -new file mode 100644 -index 00000000000..b2dd9fde752 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c -@@ -0,0 +1,17 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile { target { c || c++11 } } } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test raw strings. */ -+ -+const char *s1 = R"(a b c LRE‪ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s2 = R"(a b c RLE‫ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s3 = R"(a b c LRO‭ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s4 = R"(a b c FSI⁨ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s5 = R"(a b c LRI⁦ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s6 = R"(a b c RLI⁧ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c -new file mode 100644 -index 00000000000..ba5f75d9553 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c -@@ -0,0 +1,38 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs, -+ or RLOs. */ -+ -+/* LRI_⁦_LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩ -+// LRI_⁦_RLO_‮_RLE_‫_RLE_‫_PDI_⁩ -+// LRI_⁦_RLO_‮_RLE_‫_PDI_⁩ -+// FSI_⁨_RLO_‮_PDI_⁩ -+// FSI_⁨_FSI_⁨_RLO_‮_PDI_⁩ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069; -+int LRI_\u2066_LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int PDI_\u2069; -+int LRI_\u2066_PDI_\u2069; -+int RLI_\u2067_PDI_\u2069; -+int LRE_\u202a_LRI_\u2066_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int LRI_\u2066_LRE_\u202a_PDF_\u202c_PDI_\u2069; -+int LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; -+int RLI_\u2067_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int FSI_\u2068_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLO_\u202e_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_PDI_\u2069_RLI_\u2067; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int FSI_\u2068_PDF_\u202c_PDI_\u2069; -+int FSI_\u2068_FSI_\u2068_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-15.c b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c -new file mode 100644 -index 00000000000..a0ce8ff5e2c ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c -@@ -0,0 +1,59 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test unpaired bidi control chars in multiline comments. */ -+ -+/* -+ * LRE‪ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * RLE‫ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * LRO‭ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * RLO‮ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * LRI⁦ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * RLI⁧ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* -+ * FSI⁨ end -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* LRE‪ -+ PDF‬ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+/* FSI⁨ -+ PDI⁩ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+ -+/* LRE<‪> -+ * -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-3 } */ -+ -+/* -+ * LRE<‪> -+ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+ -+/* -+ * -+ * LRE<‪> */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* RLI<⁧> */ /* PDI<⁩> */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRE<‪> */ /* PDF<‬> */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c -new file mode 100644 -index 00000000000..baa0159861c ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c -@@ -0,0 +1,26 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=any" } */ -+/* Test LTR/RTL chars. */ -+ -+/* LTR<‎> */ -+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ -+// LTR<‎> -+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ -+/* RTL<‏> */ -+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ -+// RTL<‏> -+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ -+ -+const char *s1 = "LTR<‎>"; -+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ -+const char *s2 = "LTR\u200e"; -+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ -+const char *s3 = "LTR\u200E"; -+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ -+const char *s4 = "RTL<‏>"; -+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ -+const char *s5 = "RTL\u200f"; -+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ -+const char *s6 = "RTL\u200F"; -+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c -new file mode 100644 -index 00000000000..07cb4321f96 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c -@@ -0,0 +1,30 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test LTR/RTL chars. */ -+ -+/* LTR<‎> */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// LTR<‎> -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* RTL<‏> */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// RTL<‏> -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int ltr_\u200e; -+/* { dg-error "universal character " "" { target *-*-* } .-1 } */ -+int rtl_\u200f; -+/* { dg-error "universal character " "" { target *-*-* } .-1 } */ -+ -+const char *s1 = "LTR<‎>"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+const char *s2 = "LTR\u200e"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+const char *s3 = "LTR\u200E"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+const char *s4 = "RTL<‏>"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+const char *s5 = "RTL\u200f"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+const char *s6 = "RTL\u200F"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-2.c b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c -new file mode 100644 -index 00000000000..2340374f276 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c -@@ -0,0 +1,9 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+ -+int main() { -+ /* Say hello; newline⁧/*/ return 0 ; -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("Hello world.\n"); -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-3.c b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c -new file mode 100644 -index 00000000000..9dc7edb6e64 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c -@@ -0,0 +1,11 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+ -+int main() { -+ const char* access_level = "user"; -+ if (__builtin_strcmp(access_level, "user‮ ⁦// Check if admin⁩ ⁦")) { -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("You are an admin.\n"); -+ } -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c -new file mode 100644 -index 00000000000..49f856b9bfe ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c -@@ -0,0 +1,172 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */ -+/* Test all bidi chars in various contexts (identifiers, comments, -+ string literals, character constants), both UCN and UTF-8. The bidi -+ chars here are properly terminated, except for the character constants. */ -+ -+/* a b c LRE‪ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ -+/* Same but C++ comments instead. */ -+// a b c LRE‪ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDI⁩ x y z -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDI⁩ x y -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDI⁩ x y z -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ -+/* Here we're closing an unopened context, warn when =any. */ -+/* a b c PDI⁩ x y z */ -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+/* a b c PDF‬ x y z */ -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+// a b c PDI⁩ x y z -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+// a b c PDF‬ x y z -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+/* Multiline comments. */ -+/* a b c PDI⁩ x y z -+ */ -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */ -+/* a b c PDF‬ x y z -+ */ -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDI⁩ x y z -+ */ -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDF‬ x y z -+ */ -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDI⁩ x y z */ -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+/* first -+ a b c PDF‬ x y z */ -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c PDI⁩ x y z"; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c PDF‬ x y z"; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+} -+ -+void -+g2 () -+{ -+ const char c1 = '\u202a'; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char c2 = '\u202A'; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char c3 = '\u202b'; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char c4 = '\u202B'; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char c5 = '\u202d'; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char c6 = '\u202D'; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char c7 = '\u202e'; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char c8 = '\u202E'; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char c9 = '\u2066'; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char c10 = '\u2067'; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char c11 = '\u2068'; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+} -+ -+int A\u202cY; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+int A\u202CY2; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+int d\u202ae\u202cf; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int d\u202Ae\u202cf2; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int d\u202be\u202cf; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+int d\u202Be\u202cf2; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+int d\u202de\u202cf; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+int d\u202De\u202cf2; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+int d\u202ee\u202cf; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+int d\u202Ee\u202cf2; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+int d\u2066e\u2069f; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+int d\u2067e\u2069f; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+int d\u2068e\u2069f; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+int X\u2069; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c -new file mode 100644 -index 00000000000..f5776806c79 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c -@@ -0,0 +1,172 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */ -+/* Test all bidi chars in various contexts (identifiers, comments, -+ string literals, character constants), both UCN and UTF-8. The bidi -+ chars here are properly terminated, except for the character constants. */ -+ -+/* a b c LRE‪ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* Same but C++ comments instead. */ -+// a b c LRE‪ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDI⁩ x y -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* Here we're closing an unopened context, warn when =any. */ -+/* a b c PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* Multiline comments. */ -+/* a b c PDI⁩ x y z -+ */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ -+/* a b c PDF‬ x y z -+ */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDI⁩ x y z -+ */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDF‬ x y z -+ */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ -+/* first -+ a b c PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* first -+ a b c PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+void -+g2 () -+{ -+ const char c1 = '\u202a'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c2 = '\u202A'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c3 = '\u202b'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c4 = '\u202B'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c5 = '\u202d'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c6 = '\u202D'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c7 = '\u202e'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c8 = '\u202E'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c9 = '\u2066'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c10 = '\u2067'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c11 = '\u2068'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+int A\u202cY; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int A\u202CY2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+int d\u202ae\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Ae\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202be\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Be\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202de\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202De\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202ee\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Ee\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2066e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2067e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2068e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int X\u2069; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c -new file mode 100644 -index 00000000000..a65d6faf60e ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c -@@ -0,0 +1,130 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test nesting of bidi chars in various contexts. */ -+ -+/* Terminated by the wrong char: */ -+/* a b c LRE‪ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDI⁩ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDF‬ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* LRE‪ PDF‬ */ -+/* LRE‪ LRE‪ PDF‬ PDF‬ */ -+/* PDF‬ LRE‪ PDF‬ */ -+/* LRE‪ PDF‬ LRE‪ PDF‬ */ -+/* LRE‪ LRE‪ PDF‬ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* PDF‬ LRE‪ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+// a b c LRE‪ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDI⁩ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+// LRE‪ PDF‬ -+// LRE‪ LRE‪ PDF‬ PDF‬ -+// PDF‬ LRE‪ PDF‬ -+// LRE‪ PDF‬ LRE‪ PDF‬ -+// LRE‪ LRE‪ PDF‬ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// PDF‬ LRE‪ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c LRE\u202a 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c RLE‫ 1 2 3 PDI⁩ x y "; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLE\u202b 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRO‭ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c LRO\u202d 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c RLO‮ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c RLO\u202e 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c LRI⁦ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s10 = "a b c LRI\u2066 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c RLI⁧ 1 2 3 PDF‬ x y z\ -+ "; -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+ const char *s12 = "a b c RLI\u2067 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c FSI⁨ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c FSI\u2068 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s15 = "PDF‬ LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s16 = "PDF\u202c LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s17 = "LRE‪ PDF‬"; -+ const char *s18 = "LRE\u202a PDF\u202c"; -+ const char *s19 = "LRE‪ LRE‪ PDF‬ PDF‬"; -+ const char *s20 = "LRE\u202a LRE\u202a PDF\u202c PDF\u202c"; -+ const char *s21 = "PDF‬ LRE‪ PDF‬"; -+ const char *s22 = "PDF\u202c LRE\u202a PDF\u202c"; -+ const char *s23 = "LRE‪ LRE‪ PDF‬"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s24 = "LRE\u202a LRE\u202a PDF\u202c"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s25 = "PDF‬ LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s26 = "PDF\u202c LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s27 = "PDF‬ LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s28 = "PDF\u202c LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+int A\u202aB\u2069C; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202bB\u2069c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202db\u2069c2; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202eb\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u2066b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u2067b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u2068b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int A\u202aB\u202c; -+int A\u202aA\u202aB\u202cB\u202c; -+int a_\u202C_\u202a_\u202c; -+int a_\u202a_\u202c_\u202a_\u202c_; -+int a_\u202a_\u202c_\u202a_; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c -new file mode 100644 -index 00000000000..d012d420ec0 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c -@@ -0,0 +1,9 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=any" } */ -+/* Test we ignore UCNs in comments. */ -+ -+// a b c \u202a 1 2 3 -+// a b c \u202A 1 2 3 -+/* a b c \u202a 1 2 3 */ -+/* a b c \u202A 1 2 3 */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c -new file mode 100644 -index 00000000000..4f54c5092ec ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c -@@ -0,0 +1,13 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=any" } */ -+/* Test \u vs \U. */ -+ -+int a_\u202A; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\u202a_2; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\U0000202A_3; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\U0000202a_4; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c -new file mode 100644 -index 00000000000..e2af1b1ca97 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c -@@ -0,0 +1,29 @@ -+/* PR preprocessor/103026 */ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidi-chars=unpaired" } */ -+/* Test that we properly separate bidi contexts (comment/identifier/character -+ constant/string literal). */ -+ -+/* LRE ->‪<- */ int pdf_\u202c_1; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLE ->‫<- */ int pdf_\u202c_2; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRO ->‭<- */ int pdf_\u202c_3; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLO ->‮<- */ int pdf_\u202c_4; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRI ->⁦<-*/ int pdi_\u2069_1; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLI ->⁧<- */ int pdi_\u2069_12; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* FSI ->⁨<- */ int pdi_\u2069_3; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+const char *s1 = "LRE\u202a"; /* PDF ->‬<- */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRE ->‪<- */ const char *s2 = "PDF\u202c"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s3 = "LRE\u202a"; int pdf_\u202c_5; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int lre_\u202a; const char *s4 = "PDF\u202c"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h -index 3ad52d5e01e..e0dcb7f0529 100644 ---- a/libcpp/include/cpplib.h -+++ b/libcpp/include/cpplib.h -@@ -305,6 +305,17 @@ enum cpp_normalize_level { - normalized_none - }; - -+/* The possible bidirectional control characters checking levels, from least -+ restrictive to most. */ -+enum cpp_bidirectional_level { -+ /* No checking. */ -+ bidirectional_none, -+ /* Only detect unpaired uses of bidirectional control characters. */ -+ bidirectional_unpaired, -+ /* Detect any use of bidirectional control characters. */ -+ bidirectional_any -+}; -+ - /* This structure is nested inside struct cpp_reader, and - carries all the options visible to the command line. */ - struct cpp_options -@@ -506,6 +517,10 @@ struct cpp_options - /* True if warn about differences between C++98 and C++11. */ - bool cpp_warn_cxx11_compat; - -+ /* Nonzero if bidirectional control characters checking is on. See enum -+ cpp_bidirectional_level. */ -+ unsigned char cpp_warn_bidirectional; -+ - /* Dependency generation. */ - struct - { -@@ -1063,7 +1078,8 @@ enum { - CPP_W_PEDANTIC, - CPP_W_C90_C99_COMPAT, - CPP_W_CXX11_COMPAT, -- CPP_W_EXPANSION_TO_DEFINED -+ CPP_W_EXPANSION_TO_DEFINED, -+ CPP_W_BIDIRECTIONAL - }; - - /* Output a diagnostic of some kind. */ -diff --git a/libcpp/init.c b/libcpp/init.c -index ca3fbaa5c05..5c15da82ff8 100644 ---- a/libcpp/init.c -+++ b/libcpp/init.c -@@ -208,6 +208,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, - = ENABLE_CANONICAL_SYSTEM_HEADERS; - CPP_OPTION (pfile, ext_numeric_literals) = 1; - CPP_OPTION (pfile, warn_date_time) = 0; -+ CPP_OPTION (pfile, cpp_warn_bidirectional) = bidirectional_unpaired; - - /* Default CPP arithmetic to something sensible for the host for the - benefit of dumb users like fix-header. */ -diff --git a/libcpp/internal.h b/libcpp/internal.h -index 4f74f995cec..53b4c0f4af7 100644 ---- a/libcpp/internal.h -+++ b/libcpp/internal.h -@@ -576,6 +576,13 @@ struct cpp_reader - /* If non-null, the lexer will use this location for the next token - instead of getting a location from the linemap. */ - source_location *forced_token_location_p; -+ -+ /* Returns true iff we should warn about UTF-8 bidirectional control -+ characters. */ -+ bool warn_bidi_p () const -+ { -+ return CPP_OPTION (this, cpp_warn_bidirectional) != bidirectional_none; -+ } - }; - - /* Character classes. Based on the more primitive macros in safe-ctype.h. -diff --git a/libcpp/lex.c b/libcpp/lex.c -index a408f912c5c..ea7f75e842e 100644 ---- a/libcpp/lex.c -+++ b/libcpp/lex.c -@@ -1164,6 +1164,324 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) - } - } - -+namespace bidi { -+ enum kind { -+ NONE, LRE, RLE, LRO, RLO, LRI, RLI, FSI, PDF, PDI, LTR, RTL -+ }; -+ -+ /* All the UTF-8 encodings of bidi characters start with E2. */ -+ const uchar utf8_start = 0xe2; -+ -+ /* A vector holding currently open bidi contexts. We use a char for -+ each context, its LSB is 1 if it represents a PDF context, 0 if it -+ represents a PDI context. The next bit is 1 if this context was open -+ by a bidi character written as a UCN, and 0 when it was UTF-8. */ -+ semi_embedded_vec vec; -+ -+ /* Close the whole comment/identifier/string literal/character constant -+ context. */ -+ void on_close () -+ { -+ vec.truncate (0); -+ } -+ -+ /* Pop the last element in the vector. */ -+ void pop () -+ { -+ unsigned int len = vec.count (); -+ gcc_checking_assert (len > 0); -+ vec.truncate (len - 1); -+ } -+ -+ /* Return the context of the Ith element. */ -+ kind ctx_at (unsigned int i) -+ { -+ return (vec[i] & 1) ? PDF : PDI; -+ } -+ -+ /* Return which context is currently opened. */ -+ kind current_ctx () -+ { -+ unsigned int len = vec.count (); -+ if (len == 0) -+ return NONE; -+ return ctx_at (len - 1); -+ } -+ -+ /* Return true if the current context comes from a UCN origin, that is, -+ the bidi char which started this bidi context was written as a UCN. */ -+ bool current_ctx_ucn_p () -+ { -+ unsigned int len = vec.count (); -+ gcc_checking_assert (len > 0); -+ return (vec[len - 1] >> 1) & 1; -+ } -+ -+ /* We've read a bidi char, update the current vector as necessary. */ -+ void on_char (kind k, bool ucn_p) -+ { -+ switch (k) -+ { -+ case LRE: -+ case RLE: -+ case LRO: -+ case RLO: -+ vec.push (ucn_p ? 3u : 1u); -+ break; -+ case LRI: -+ case RLI: -+ case FSI: -+ vec.push (ucn_p ? 2u : 0u); -+ break; -+ /* PDF terminates the scope of the last LRE, RLE, LRO, or RLO -+ whose scope has not yet been terminated. */ -+ case PDF: -+ if (current_ctx () == PDF) -+ pop (); -+ break; -+ /* PDI terminates the scope of the last LRI, RLI, or FSI whose -+ scope has not yet been terminated, as well as the scopes of -+ any subsequent LREs, RLEs, LROs, or RLOs whose scopes have not -+ yet been terminated. */ -+ case PDI: -+ for (int i = vec.count () - 1; i >= 0; --i) -+ if (ctx_at (i) == PDI) -+ { -+ vec.truncate (i); -+ break; -+ } -+ break; -+ case LTR: -+ case RTL: -+ /* These aren't popped by a PDF/PDI. */ -+ break; -+ [[likely]] case NONE: -+ break; -+ default: -+ abort (); -+ } -+ } -+ -+ /* Return a descriptive string for K. */ -+ const char *to_str (kind k) -+ { -+ switch (k) -+ { -+ case LRE: -+ return "U+202A (LEFT-TO-RIGHT EMBEDDING)"; -+ case RLE: -+ return "U+202B (RIGHT-TO-LEFT EMBEDDING)"; -+ case LRO: -+ return "U+202D (LEFT-TO-RIGHT OVERRIDE)"; -+ case RLO: -+ return "U+202E (RIGHT-TO-LEFT OVERRIDE)"; -+ case LRI: -+ return "U+2066 (LEFT-TO-RIGHT ISOLATE)"; -+ case RLI: -+ return "U+2067 (RIGHT-TO-LEFT ISOLATE)"; -+ case FSI: -+ return "U+2068 (FIRST STRONG ISOLATE)"; -+ case PDF: -+ return "U+202C (POP DIRECTIONAL FORMATTING)"; -+ case PDI: -+ return "U+2069 (POP DIRECTIONAL ISOLATE)"; -+ case LTR: -+ return "U+200E (LEFT-TO-RIGHT MARK)"; -+ case RTL: -+ return "U+200F (RIGHT-TO-LEFT MARK)"; -+ default: -+ abort (); -+ } -+ } -+} -+ -+/* Parse a sequence of 3 bytes starting with P and return its bidi code. */ -+ -+static bidi::kind -+get_bidi_utf8 (const unsigned char *const p) -+{ -+ gcc_checking_assert (p[0] == bidi::utf8_start); -+ -+ if (p[1] == 0x80) -+ switch (p[2]) -+ { -+ case 0xaa: -+ return bidi::LRE; -+ case 0xab: -+ return bidi::RLE; -+ case 0xac: -+ return bidi::PDF; -+ case 0xad: -+ return bidi::LRO; -+ case 0xae: -+ return bidi::RLO; -+ case 0x8e: -+ return bidi::LTR; -+ case 0x8f: -+ return bidi::RTL; -+ default: -+ break; -+ } -+ else if (p[1] == 0x81) -+ switch (p[2]) -+ { -+ case 0xa6: -+ return bidi::LRI; -+ case 0xa7: -+ return bidi::RLI; -+ case 0xa8: -+ return bidi::FSI; -+ case 0xa9: -+ return bidi::PDI; -+ default: -+ break; -+ } -+ -+ return bidi::NONE; -+} -+ -+/* Parse a UCN where P points just past \u or \U and return its bidi code. */ -+ -+static bidi::kind -+get_bidi_ucn (const unsigned char *p, bool is_U) -+{ -+ /* 6.4.3 Universal Character Names -+ \u hex-quad -+ \U hex-quad hex-quad -+ where \unnnn means \U0000nnnn. */ -+ -+ if (is_U) -+ { -+ if (p[0] != '0' || p[1] != '0' || p[2] != '0' || p[3] != '0') -+ return bidi::NONE; -+ /* Skip 4B so we can treat \u and \U the same below. */ -+ p += 4; -+ } -+ -+ /* All code points we are looking for start with 20xx. */ -+ if (p[0] != '2' || p[1] != '0') -+ return bidi::NONE; -+ else if (p[2] == '2') -+ switch (p[3]) -+ { -+ case 'a': -+ case 'A': -+ return bidi::LRE; -+ case 'b': -+ case 'B': -+ return bidi::RLE; -+ case 'c': -+ case 'C': -+ return bidi::PDF; -+ case 'd': -+ case 'D': -+ return bidi::LRO; -+ case 'e': -+ case 'E': -+ return bidi::RLO; -+ default: -+ break; -+ } -+ else if (p[2] == '6') -+ switch (p[3]) -+ { -+ case '6': -+ return bidi::LRI; -+ case '7': -+ return bidi::RLI; -+ case '8': -+ return bidi::FSI; -+ case '9': -+ return bidi::PDI; -+ default: -+ break; -+ } -+ else if (p[2] == '0') -+ switch (p[3]) -+ { -+ case 'e': -+ case 'E': -+ return bidi::LTR; -+ case 'f': -+ case 'F': -+ return bidi::RTL; -+ default: -+ break; -+ } -+ -+ return bidi::NONE; -+} -+ -+/* We're closing a bidi context, that is, we've encountered a newline, -+ are closing a C-style comment, or are at the end of a string literal, -+ character constant, or identifier. Warn if this context was not -+ properly terminated by a PDI or PDF. P points to the last character -+ in this context. */ -+ -+static void -+maybe_warn_bidi_on_close (cpp_reader *pfile, const uchar *p) -+{ -+ if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired -+ && bidi::vec.count () > 0) -+ { -+ const source_location loc -+ = linemap_position_for_column (pfile->line_table, -+ CPP_BUF_COLUMN (pfile->buffer, p)); -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "unpaired UTF-8 bidirectional control character " -+ "detected"); -+ } -+ /* We're done with this context. */ -+ bidi::on_close (); -+} -+ -+/* We're at the beginning or in the middle of an identifier/comment/string -+ literal/character constant. Warn if we've encountered a bidi character. -+ KIND says which bidi character it was; P points to it in the character -+ stream. UCN_P is true iff this bidi character was written as a UCN. */ -+ -+static void -+maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind, -+ bool ucn_p) -+{ -+ if (__builtin_expect (kind == bidi::NONE, 1)) -+ return; -+ -+ const unsigned char warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional); -+ -+ if (warn_bidi != bidirectional_none) -+ { -+ const source_location loc -+ = linemap_position_for_column (pfile->line_table, -+ CPP_BUF_COLUMN (pfile->buffer, p)); -+ /* It seems excessive to warn about a PDI/PDF that is closing -+ an opened context because we've already warned about the -+ opening character. Except warn when we have a UCN x UTF-8 -+ mismatch. */ -+ if (kind == bidi::current_ctx ()) -+ { -+ if (warn_bidi == bidirectional_unpaired -+ && bidi::current_ctx_ucn_p () != ucn_p) -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "UTF-8 vs UCN mismatch when closing " -+ "a context by \"%s\"", bidi::to_str (kind)); -+ } -+ else if (warn_bidi == bidirectional_any) -+ { -+ if (kind == bidi::PDF || kind == bidi::PDI) -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "\"%s\" is closing an unopened context", -+ bidi::to_str (kind)); -+ else -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "found problematic Unicode character \"%s\"", -+ bidi::to_str (kind)); -+ } -+ } -+ /* We're done with this context. */ -+ bidi::on_char (kind, ucn_p); -+} -+ - /* Skip a C-style block comment. We find the end of the comment by - seeing if an asterisk is before every '/' we encounter. Returns - nonzero if comment terminated by EOF, zero otherwise. -@@ -1175,6 +1493,7 @@ _cpp_skip_block_comment (cpp_reader *pfile) - cpp_buffer *buffer = pfile->buffer; - const uchar *cur = buffer->cur; - uchar c; -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - - cur++; - if (*cur == '/') -@@ -1189,7 +1508,11 @@ _cpp_skip_block_comment (cpp_reader *pfile) - if (c == '/') - { - if (cur[-2] == '*') -- break; -+ { -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur); -+ break; -+ } - - /* Warn about potential nested comments, but not if the '/' - comes immediately before the true comment delimiter. -@@ -1208,6 +1531,8 @@ _cpp_skip_block_comment (cpp_reader *pfile) - { - unsigned int cols; - buffer->cur = cur - 1; -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur); - _cpp_process_line_notes (pfile, true); - if (buffer->next_line >= buffer->rlimit) - return true; -@@ -1218,6 +1543,13 @@ _cpp_skip_block_comment (cpp_reader *pfile) - - cur = buffer->cur; - } -+ /* If this is a beginning of a UTF-8 encoding, it might be -+ a bidirectional control character. */ -+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_utf8 (cur - 1); -+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false); -+ } - } - - buffer->cur = cur; -@@ -1233,9 +1565,31 @@ skip_line_comment (cpp_reader *pfile) - { - cpp_buffer *buffer = pfile->buffer; - source_location orig_line = pfile->line_table->highest_line; -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - -- while (*buffer->cur != '\n') -- buffer->cur++; -+ if (!warn_bidi_p) -+ while (*buffer->cur != '\n') -+ buffer->cur++; -+ else -+ { -+ while (*buffer->cur != '\n' -+ && *buffer->cur != bidi::utf8_start) -+ buffer->cur++; -+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) -+ { -+ while (*buffer->cur != '\n') -+ { -+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) -+ { -+ bidi::kind kind = get_bidi_utf8 (buffer->cur); -+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind, -+ /*ucn_p=*/false); -+ } -+ buffer->cur++; -+ } -+ maybe_warn_bidi_on_close (pfile, buffer->cur); -+ } -+ } - - _cpp_process_line_notes (pfile, true); - return orig_line != pfile->line_table->highest_line; -@@ -1315,11 +1669,13 @@ warn_about_normalization (cpp_reader *pfile, - - /* Returns TRUE if the sequence starting at buffer->cur is invalid in - an identifier. FIRST is TRUE if this starts an identifier. */ -+ - static bool - forms_identifier_p (cpp_reader *pfile, int first, - struct normalize_state *state) - { - cpp_buffer *buffer = pfile->buffer; -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - - if (*buffer->cur == '$') - { -@@ -1343,6 +1699,12 @@ forms_identifier_p (cpp_reader *pfile, int first, - { - cppchar_t s; - buffer->cur += 2; -+ if (warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_ucn (buffer->cur, -+ buffer->cur[-1] == 'U'); -+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind, /*ucn_p=*/true); -+ } - if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first, - state, &s, NULL, NULL)) - return true; -@@ -1450,6 +1812,7 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, - const uchar *cur; - unsigned int len; - unsigned int hash = HT_HASHSTEP (0, *base); -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - - cur = pfile->buffer->cur; - if (! starts_ucn) -@@ -1472,6 +1835,8 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, - pfile->buffer->cur++; - } - } while (forms_identifier_p (pfile, false, nst)); -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, pfile->buffer->cur); - result = _cpp_interpret_identifier (pfile, base, - pfile->buffer->cur - base); - *spelling = cpp_lookup (pfile, base, pfile->buffer->cur - base); -@@ -1673,6 +2038,7 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, - _cpp_buff *first_buff = NULL, *last_buff = NULL; - size_t raw_prefix_start; - _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note]; -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - - type = (*base == 'L' ? CPP_WSTRING : - *base == 'U' ? CPP_STRING32 : -@@ -1909,8 +2275,15 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, - cur = base = pfile->buffer->cur; - note = &pfile->buffer->notes[pfile->buffer->cur_note]; - } -+ else if (__builtin_expect ((unsigned char) c == bidi::utf8_start, 0) -+ && warn_bidi_p) -+ maybe_warn_bidi_on_char (pfile, cur - 1, get_bidi_utf8 (cur - 1), -+ /*ucn_p=*/false); - } - -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur); -+ - if (CPP_OPTION (pfile, user_literals)) - { - /* If a string format macro, say from inttypes.h, is placed touching -@@ -2005,15 +2378,27 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) - else - terminator = '>', type = CPP_HEADER_NAME; - -+ const bool warn_bidi_p = pfile->warn_bidi_p (); - for (;;) - { - cppchar_t c = *cur++; - - /* In #include-style directives, terminators are not escapable. */ - if (c == '\\' && !pfile->state.angled_headers && *cur != '\n') -- cur++; -+ { -+ if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U'); -+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true); -+ } -+ cur++; -+ } - else if (c == terminator) -- break; -+ { -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur - 1); -+ break; -+ } - else if (c == '\n') - { - cur--; -@@ -2030,6 +2415,11 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) - } - else if (c == '\0') - saw_NUL = true; -+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_utf8 (cur - 1); -+ maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false); -+ } - } - - if (saw_NUL && !pfile->state.skipping) diff --git a/SOURCES/gcc8-Wno-format-security.patch b/SOURCES/gcc8-Wno-format-security.patch deleted file mode 100644 index cb21e5d..0000000 --- a/SOURCES/gcc8-Wno-format-security.patch +++ /dev/null @@ -1,27 +0,0 @@ -2017-02-25 Jakub Jelinek - - * configure.ac: When adding -Wno-format, also add -Wno-format-security. - * configure: Regenerated. - ---- gcc/configure.ac.jj 2017-02-13 12:20:53.000000000 +0100 -+++ gcc/configure.ac 2017-02-25 12:42:32.859175403 +0100 -@@ -481,7 +481,7 @@ AC_ARG_ENABLE(build-format-warnings, - AS_HELP_STRING([--disable-build-format-warnings],[don't use -Wformat while building GCC]), - [],[enable_build_format_warnings=yes]) - AS_IF([test $enable_build_format_warnings = no], -- [wf_opt=-Wno-format],[wf_opt=]) -+ [wf_opt="-Wno-format -Wno-format-security"],[wf_opt=]) - ACX_PROG_CXX_WARNING_OPTS( - m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ], - [-Wcast-qual $wf_opt])), [loose_warn]) ---- gcc/configure.jj 2017-02-13 12:20:52.000000000 +0100 -+++ gcc/configure 2017-02-25 12:42:50.041946391 +0100 -@@ -6647,7 +6647,7 @@ else - fi - - if test $enable_build_format_warnings = no; then : -- wf_opt=-Wno-format -+ wf_opt="-Wno-format -Wno-format-security" - else - wf_opt= - fi diff --git a/SOURCES/gcc8-aarch64-mtune-neoverse-512tvb.patch b/SOURCES/gcc8-aarch64-mtune-neoverse-512tvb.patch deleted file mode 100644 index af0a049..0000000 --- a/SOURCES/gcc8-aarch64-mtune-neoverse-512tvb.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 9c108bb84d3a2447dac730c455df658be0a2c751 Mon Sep 17 00:00:00 2001 -From: Richard Sandiford -Date: Tue, 17 Aug 2021 15:15:27 +0100 -Subject: [PATCH] aarch64: Add -mtune=neoverse-512tvb -To: gcc-patches@gcc.gnu.org - -This patch adds an option to tune for Neoverse cores that have -a total vector bandwidth of 512 bits (4x128 for Advanced SIMD -and a vector-length-dependent equivalent for SVE). This is intended -to be a compromise between tuning aggressively for a single core like -Neoverse V1 (which can be too narrow) and tuning for AArch64 cores -in general (which can be too wide). - --mcpu=neoverse-512tvb is equivalent to -mcpu=neoverse-v1 --mtune=neoverse-512tvb. - -gcc/ - * doc/invoke.texi: Document -mtune=neoverse-512tvb and - -mcpu=neoverse-512tvb. - * config/aarch64/aarch64-cores.def (neoverse-512tvb): New entry. - * config/aarch64/aarch64-tune.md: Regenerate. - -(cherry picked from commit 048039c49b96875144f67e7789fdea54abf7710b) ---- - gcc/config/aarch64/aarch64-cores.def | 1 + - gcc/config/aarch64/aarch64-tune.md | 2 +- - gcc/doc/invoke.texi | 25 ++++++++++++++++++++++--- - 3 files changed, 24 insertions(+), 4 deletions(-) - -diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def -index dfb839c01cc..f348d31e22e 100644 ---- a/gcc/config/aarch64/aarch64-cores.def -+++ b/gcc/config/aarch64/aarch64-cores.def -@@ -99,6 +99,7 @@ AARCH64_CORE("saphira", saphira, falkor, 8_3A, AARCH64_FL_FOR_ARCH8_3 - /* ARM ('A') cores. */ - AARCH64_CORE("zeus", zeus, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1) - AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1) -+AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, INVALID_IMP, INVALID_CORE, -1) - - /* Armv8.5-A Architecture Processors. */ - AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversen2, 0x41, 0xd49, -1) -diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md -index 2d7c9aa4740..09b76480f0b 100644 ---- a/gcc/config/aarch64/aarch64-tune.md -+++ b/gcc/config/aarch64/aarch64-tune.md -@@ -1,5 +1,5 @@ - ;; -*- buffer-read-only: t -*- - ;; Generated automatically by gentune.sh from aarch64-cores.def - (define_attr "tune" -- "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55" -+ "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoverse512tvb,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55" - (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 78ca7738df2..68fda03281a 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -14772,9 +14772,9 @@ performance of the code. Permissible values for this option are: - @samp{generic}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55}, - @samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75}, - @samp{cortex-a76}, @samp{ares}, @samp{neoverse-n1}, @samp{neoverse-n2}, --@samp{neoverse-v1}, @samp{zeus}, @samp{exynos-m1}, @samp{falkor}, --@samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan}, @samp{thunderx}, --@samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81}, -+@samp{neoverse-v1}, @samp{zeus}, @samp{neoverse-512tvb}, @samp{exynos-m1}, -+@samp{falkor}, @samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan}, -+@samp{thunderx}, @samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81}, - @samp{thunderxt83}, @samp{thunderx2t99}, @samp{cortex-a57.cortex-a53}, - @samp{cortex-a72.cortex-a53}, @samp{cortex-a73.cortex-a35}, - @samp{cortex-a73.cortex-a53}, @samp{cortex-a75.cortex-a55}, -@@ -14785,6 +14785,15 @@ The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53}, - @samp{cortex-a75.cortex-a55} specify that GCC should tune for a - big.LITTLE system. - -+The value @samp{neoverse-512tvb} specifies that GCC should tune -+for Neoverse cores that (a) implement SVE and (b) have a total vector -+bandwidth of 512 bits per cycle. In other words, the option tells GCC to -+tune for Neoverse cores that can execute 4 128-bit Advanced SIMD arithmetic -+instructions a cycle and that can execute an equivalent number of SVE -+arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE). -+This is more general than tuning for a specific core like Neoverse V1 -+but is more specific than the default tuning described below. -+ - Additionally on native AArch64 GNU/Linux systems the value - @samp{native} tunes performance to the host system. This option has no effect - if the compiler is unable to recognize the processor of the host system. -@@ -14814,6 +14823,16 @@ by @option{-mtune}). Where this option is used in conjunction - with @option{-march} or @option{-mtune}, those options take precedence - over the appropriate part of this option. - -+@option{-mcpu=neoverse-512tvb} is special in that it does not refer -+to a specific core, but instead refers to all Neoverse cores that -+(a) implement SVE and (b) have a total vector bandwidth of 512 bits -+a cycle. Unless overridden by @option{-march}, -+@option{-mcpu=neoverse-512tvb} generates code that can run on a -+Neoverse V1 core, since Neoverse V1 is the first Neoverse core with -+these properties. Unless overridden by @option{-mtune}, -+@option{-mcpu=neoverse-512tvb} tunes code in the same way as for -+@option{-mtune=neoverse-512tvb}. -+ - @item -moverride=@var{string} - @opindex moverride - Override tuning decisions made by the back-end in response to a --- -2.25.1 - diff --git a/SOURCES/gcc8-foffload-default.patch b/SOURCES/gcc8-foffload-default.patch deleted file mode 100644 index 771e1e0..0000000 --- a/SOURCES/gcc8-foffload-default.patch +++ /dev/null @@ -1,117 +0,0 @@ -2017-01-20 Jakub Jelinek - - * gcc.c (offload_targets_default): New variable. - (process_command): Set it if -foffload is defaulted. - (driver::maybe_putenv_OFFLOAD_TARGETS): Add OFFLOAD_TARGET_DEFAULT=1 - into environment if -foffload has been defaulted. - * lto-wrapper.c (OFFLOAD_TARGET_DEFAULT_ENV): Define. - (compile_images_for_offload_targets): If OFFLOAD_TARGET_DEFAULT - is in the environment, don't fail if corresponding mkoffload - can't be found. Free and clear offload_names if no valid offload - is found. -libgomp/ - * target.c (gomp_load_plugin_for_device): If a plugin can't be - dlopened, assume it has no devices silently. - ---- gcc/gcc.c.jj 2017-01-17 10:28:40.000000000 +0100 -+++ gcc/gcc.c 2017-01-20 16:26:29.649962902 +0100 -@@ -290,6 +290,10 @@ static const char *spec_host_machine = D - - static char *offload_targets = NULL; - -+/* Set to true if -foffload has not been used and offload_targets -+ is set to the configured in default. */ -+static bool offload_targets_default; -+ - /* Nonzero if cross-compiling. - When -b is used, the value comes from the `specs' file. */ - -@@ -4457,7 +4461,10 @@ process_command (unsigned int decoded_op - /* If the user didn't specify any, default to all configured offload - targets. */ - if (ENABLE_OFFLOADING && offload_targets == NULL) -- handle_foffload_option (OFFLOAD_TARGETS); -+ { -+ handle_foffload_option (OFFLOAD_TARGETS); -+ offload_targets_default = true; -+ } - - if (output_file - && strcmp (output_file, "-") != 0 -@@ -7693,6 +7700,8 @@ driver::maybe_putenv_OFFLOAD_TARGETS () - obstack_grow (&collect_obstack, offload_targets, - strlen (offload_targets) + 1); - xputenv (XOBFINISH (&collect_obstack, char *)); -+ if (offload_targets_default) -+ xputenv ("OFFLOAD_TARGET_DEFAULT=1"); - } - - free (offload_targets); ---- gcc/lto-wrapper.c.jj 2017-01-01 12:45:34.000000000 +0100 -+++ gcc/lto-wrapper.c 2017-01-20 16:34:18.294016997 +0100 -@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. - /* Environment variable, used for passing the names of offload targets from GCC - driver to lto-wrapper. */ - #define OFFLOAD_TARGET_NAMES_ENV "OFFLOAD_TARGET_NAMES" -+#define OFFLOAD_TARGET_DEFAULT_ENV "OFFLOAD_TARGET_DEFAULT" - - enum lto_mode_d { - LTO_MODE_NONE, /* Not doing LTO. */ -@@ -790,8 +791,10 @@ compile_images_for_offload_targets (unsi - if (!target_names) - return; - unsigned num_targets = parse_env_var (target_names, &names, NULL); -+ const char *target_names_default = getenv (OFFLOAD_TARGET_DEFAULT_ENV); - - int next_name_entry = 0; -+ bool hsa_seen = false; - const char *compiler_path = getenv ("COMPILER_PATH"); - if (!compiler_path) - goto out; -@@ -804,18 +807,32 @@ compile_images_for_offload_targets (unsi - /* HSA does not use LTO-like streaming and a different compiler, skip - it. */ - if (strcmp (names[i], "hsa") == 0) -- continue; -+ { -+ hsa_seen = true; -+ continue; -+ } - - offload_names[next_name_entry] - = compile_offload_image (names[i], compiler_path, in_argc, in_argv, - compiler_opts, compiler_opt_count, - linker_opts, linker_opt_count); - if (!offload_names[next_name_entry]) -- fatal_error (input_location, -- "problem with building target image for %s\n", names[i]); -+ { -+ if (target_names_default != NULL) -+ continue; -+ fatal_error (input_location, -+ "problem with building target image for %s\n", -+ names[i]); -+ } - next_name_entry++; - } - -+ if (next_name_entry == 0 && !hsa_seen) -+ { -+ free (offload_names); -+ offload_names = NULL; -+ } -+ - out: - free_array_of_ptrs ((void **) names, num_targets); - } ---- libgomp/target.c.jj 2017-01-01 12:45:52.000000000 +0100 -+++ libgomp/target.c 2017-01-20 20:12:13.756710875 +0100 -@@ -2356,7 +2356,7 @@ gomp_load_plugin_for_device (struct gomp - - void *plugin_handle = dlopen (plugin_name, RTLD_LAZY); - if (!plugin_handle) -- goto dl_fail; -+ return 0; - - /* Check if all required functions are available in the plugin and store - their handlers. None of the symbols can legitimately be NULL, diff --git a/SOURCES/gcc8-harden-1.patch b/SOURCES/gcc8-harden-1.patch deleted file mode 100644 index a325c09..0000000 --- a/SOURCES/gcc8-harden-1.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 88bf1c3910e4cf97dcb85c6d32291c23e572a516 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Wed, 27 Oct 2021 07:48:54 -0700 -Subject: [PATCH 1/4] x86: Add -mharden-sls=[none|all|return|indirect-branch] - -Add -mharden-sls= to mitigate against straight line speculation (SLS) -for function return and indirect branch by adding an INT3 instruction -after function return and indirect branch. - -gcc/ - - PR target/102952 - * config/i386/i386-opts.h (harden_sls): New enum. - * config/i386/i386.c (output_indirect_thunk): Mitigate against - SLS for function return. - (ix86_output_function_return): Likewise. - (ix86_output_jmp_thunk_or_indirect): Mitigate against indirect - branch. - (ix86_output_indirect_jmp): Likewise. - (ix86_output_call_insn): Likewise. - * config/i386/i386.opt: Add -mharden-sls=. - * doc/invoke.texi: Document -mharden-sls=. - -gcc/testsuite/ - - PR target/102952 - * gcc.target/i386/harden-sls-1.c: New test. - * gcc.target/i386/harden-sls-2.c: Likewise. - * gcc.target/i386/harden-sls-3.c: Likewise. - * gcc.target/i386/harden-sls-4.c: Likewise. - * gcc.target/i386/harden-sls-5.c: Likewise. - -(cherry picked from commit 53a643f8568067d7700a9f2facc8ba39974973d3) ---- - gcc/config/i386/i386-opts.h | 7 +++++++ - gcc/config/i386/i386.c | 22 +++++++++++++++----- - gcc/config/i386/i386.opt | 20 ++++++++++++++++++ - gcc/doc/invoke.texi | 10 ++++++++- - gcc/testsuite/gcc.target/i386/harden-sls-1.c | 14 +++++++++++++ - gcc/testsuite/gcc.target/i386/harden-sls-2.c | 14 +++++++++++++ - gcc/testsuite/gcc.target/i386/harden-sls-3.c | 14 +++++++++++++ - gcc/testsuite/gcc.target/i386/harden-sls-4.c | 16 ++++++++++++++ - gcc/testsuite/gcc.target/i386/harden-sls-5.c | 17 +++++++++++++++ - 9 files changed, 128 insertions(+), 6 deletions(-) - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-1.c - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-2.c - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-3.c - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-4.c - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-5.c - -diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h -index 46366cbfa72..34718b6d52c 100644 ---- a/gcc/config/i386/i386-opts.h -+++ b/gcc/config/i386/i386-opts.h -@@ -119,4 +119,11 @@ enum indirect_branch { - indirect_branch_thunk_extern - }; - -+enum harden_sls { -+ harden_sls_none = 0, -+ harden_sls_return = 1 << 0, -+ harden_sls_indirect_branch = 1 << 1, -+ harden_sls_all = harden_sls_return | harden_sls_indirect_branch -+}; -+ - #endif -diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c -index 31502774ef3..eb9303f8742 100644 ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -10977,6 +10977,9 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix, - fputs ("\tbnd ret\n", asm_out_file); - else - fputs ("\tret\n", asm_out_file); -+ -+ if ((ix86_harden_sls & harden_sls_return)) -+ fputs ("\tint3\n", asm_out_file); - } - - /* Output a funtion with a call and return thunk for indirect branch. -@@ -28728,6 +28731,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, - fprintf (asm_out_file, "\tjmp\t"); - assemble_name (asm_out_file, thunk_name); - putc ('\n', asm_out_file); -+ if ((ix86_harden_sls & harden_sls_indirect_branch)) -+ fputs ("\tint3\n", asm_out_file); - } - else - output_indirect_thunk (need_prefix, regno); -@@ -28973,10 +28978,10 @@ ix86_output_indirect_jmp (rtx call_op) - gcc_unreachable (); - - ix86_output_indirect_branch (call_op, "%0", true); -- return ""; - } - else -- return "%!jmp\t%A0"; -+ output_asm_insn ("%!jmp\t%A0", &call_op); -+ return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : ""; - } - - /* Output function return. CALL_OP is the jump target. Add a REP -@@ -29018,9 +29023,11 @@ ix86_output_function_return (bool long_p) - } - - if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn)) -- return "%!ret"; -+ output_asm_insn ("%!ret", NULL); -+ else -+ output_asm_insn ("rep%; ret", NULL); - -- return "rep%; ret"; -+ return (ix86_harden_sls & harden_sls_return) ? "int3" : ""; - } - - /* Output indirect function return. RET_OP is the function return -@@ -29158,7 +29165,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) - if (output_indirect_p && !direct_p) - ix86_output_indirect_branch (call_op, xasm, true); - else -- output_asm_insn (xasm, &call_op); -+ { -+ output_asm_insn (xasm, &call_op); -+ if (!direct_p -+ && (ix86_harden_sls & harden_sls_indirect_branch)) -+ return "int3"; -+ } - return ""; - } - -diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt -index d9bd909a885..3ae48609e25 100644 ---- a/gcc/config/i386/i386.opt -+++ b/gcc/config/i386/i386.opt -@@ -1055,3 +1055,23 @@ Support MOVDIRI built-in functions and code generation. - mmovdir64b - Target Report Mask(ISA_MOVDIR64B) Var(ix86_isa_flags2) Save - Support MOVDIR64B built-in functions and code generation. -+ -+mharden-sls= -+Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none) -+Generate code to mitigate against straight line speculation. -+ -+Enum -+Name(harden_sls) Type(enum harden_sls) -+Known choices for mitigation against straight line speculation with -mharden-sls=: -+ -+EnumValue -+Enum(harden_sls) String(none) Value(harden_sls_none) -+ -+EnumValue -+Enum(harden_sls) String(return) Value(harden_sls_return) -+ -+EnumValue -+Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch) -+ -+EnumValue -+Enum(harden_sls) String(all) Value(harden_sls_all) -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 78ca7738df2..1e20efd6969 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -1284,7 +1284,7 @@ See RS/6000 and PowerPC Options. - -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol - -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol - -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol ---mindirect-branch-register} -+-mindirect-branch-register -mharden-sls=@var{choice}} - - @emph{x86 Windows Options} - @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol -@@ -28036,6 +28036,14 @@ not be reachable in the large code model. - @opindex -mindirect-branch-register - Force indirect call and jump via register. - -+@item -mharden-sls=@var{choice} -+@opindex mharden-sls -+Generate code to mitigate against straight line speculation (SLS) with -+@var{choice}. The default is @samp{none} which disables all SLS -+hardening. @samp{return} enables SLS hardening for function return. -+@samp{indirect-branch} enables SLS hardening for indirect branch. -+@samp{all} enables all SLS hardening. -+ - @end table - - These @samp{-m} switches are supported in addition to the above -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c -new file mode 100644 -index 00000000000..6f70dc94a23 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void foo (void); -+ -+void -+bar (void) -+{ -+ foo (); -+} -+ -+/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */ -+/* { dg-final { scan-assembler-not {int3} } } */ -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c -new file mode 100644 -index 00000000000..a7c59078d03 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void (*fptr) (void); -+ -+void -+foo (void) -+{ -+ fptr (); -+} -+ -+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ -+/* { dg-final { scan-assembler-times "int3" 1 } } */ -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c -new file mode 100644 -index 00000000000..1a6056b6d7b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void (*fptr) (void); -+ -+void -+foo (void) -+{ -+ fptr (); -+} -+ -+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ -+/* { dg-final { scan-assembler-times "int3" 2 } } */ -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c -new file mode 100644 -index 00000000000..f70dd1379d3 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void (*fptr) (void); -+ -+void -+foo (void) -+{ -+ fptr (); -+} -+ -+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */ -+/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */ -+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */ -+/* { dg-final { scan-assembler-times "int3" 1 } } */ -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c -new file mode 100644 -index 00000000000..613c44c6f82 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c -@@ -0,0 +1,17 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+typedef void (*dispatch_t)(long offset); -+ -+dispatch_t dispatch; -+ -+int -+male_indirect_jump (long offset) -+{ -+ dispatch(offset); -+ return 0; -+} -+ -+/* { dg-final { scan-assembler-times "ret" 1 } } */ -+/* { dg-final { scan-assembler-times "int3" 1 } } */ --- -2.36.1 - diff --git a/SOURCES/gcc8-harden-2.patch b/SOURCES/gcc8-harden-2.patch deleted file mode 100644 index 669c11f..0000000 --- a/SOURCES/gcc8-harden-2.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0df8313a0a5d8533f2487e21d7b42e9adee28f18 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Wed, 27 Oct 2021 06:27:15 -0700 -Subject: [PATCH 2/4] x86: Add -mindirect-branch-cs-prefix - -Add -mindirect-branch-cs-prefix to add CS prefix to call and jmp to -indirect thunk with branch target in r8-r15 registers so that the call -and jmp instruction length is 6 bytes to allow them to be replaced with -"lfence; call *%r8-r15" or "lfence; jmp *%r8-r15" at run-time. - -gcc/ - - PR target/102952 - * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): Emit - CS prefix for -mindirect-branch-cs-prefix. - (ix86_output_indirect_branch_via_reg): Likewise. - * config/i386/i386.opt: Add -mindirect-branch-cs-prefix. - * doc/invoke.texi: Document -mindirect-branch-cs-prefix. - -gcc/testsuite/ - - PR target/102952 - * gcc.target/i386/indirect-thunk-cs-prefix-1.c: New test. - * gcc.target/i386/indirect-thunk-cs-prefix-2.c: Likewise. - -(cherry picked from commit 2196a681d7810ad8b227bf983f38ba716620545e) ---- - gcc/config/i386/i386.c | 14 ++++++++++++-- - gcc/config/i386/i386.opt | 4 ++++ - gcc/doc/invoke.texi | 10 +++++++++- - .../gcc.target/i386/indirect-thunk-cs-prefix-1.c | 14 ++++++++++++++ - .../gcc.target/i386/indirect-thunk-cs-prefix-2.c | 15 +++++++++++++++ - 5 files changed, 54 insertions(+), 3 deletions(-) - create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c - create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c - -diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c -index eb9303f8742..8442dd0daea 100644 ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -28728,7 +28728,12 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, - if (need_prefix == indirect_thunk_prefix_bnd) - fprintf (asm_out_file, "\tbnd jmp\t"); - else -- fprintf (asm_out_file, "\tjmp\t"); -+ { -+ if (REX_INT_REGNO_P (regno) -+ && ix86_indirect_branch_cs_prefix) -+ fprintf (asm_out_file, "\tcs\n"); -+ fprintf (asm_out_file, "\tjmp\t"); -+ } - assemble_name (asm_out_file, thunk_name); - putc ('\n', asm_out_file); - if ((ix86_harden_sls & harden_sls_indirect_branch)) -@@ -28787,7 +28792,12 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) - if (need_prefix == indirect_thunk_prefix_bnd) - fprintf (asm_out_file, "\tbnd call\t"); - else -- fprintf (asm_out_file, "\tcall\t"); -+ { -+ if (REX_INT_REGNO_P (regno) -+ && ix86_indirect_branch_cs_prefix) -+ fprintf (asm_out_file, "\tcs\n"); -+ fprintf (asm_out_file, "\tcall\t"); -+ } - assemble_name (asm_out_file, thunk_name); - putc ('\n', asm_out_file); - return; -diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt -index 3ae48609e25..9f67ef558dc 100644 ---- a/gcc/config/i386/i386.opt -+++ b/gcc/config/i386/i386.opt -@@ -1044,6 +1044,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline) - EnumValue - Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern) - -+mindirect-branch-cs-prefix -+Target Var(ix86_indirect_branch_cs_prefix) Init(0) -+Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers. -+ - mindirect-branch-register - Target Report Var(ix86_indirect_branch_register) Init(0) - Force indirect call and jump via register. -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 1e20efd6969..605cd4b93f1 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -1284,7 +1284,8 @@ See RS/6000 and PowerPC Options. - -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol - -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol - -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol ---mindirect-branch-register -mharden-sls=@var{choice}} -+-mindirect-branch-register -mharden-sls=@var{choice} @gol -+-mindirect-branch-cs-prefix} - - @emph{x86 Windows Options} - @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol -@@ -28044,6 +28045,13 @@ hardening. @samp{return} enables SLS hardening for function return. - @samp{indirect-branch} enables SLS hardening for indirect branch. - @samp{all} enables all SLS hardening. - -+@item -mindirect-branch-cs-prefix -+@opindex mindirect-branch-cs-prefix -+Add CS prefix to call and jmp to indirect thunk with branch target in -+r8-r15 registers so that the call and jmp instruction length is 6 bytes -+to allow them to be replaced with @samp{lfence; call *%r8-r15} or -+@samp{lfence; jmp *%r8-r15} at run-time. -+ - @end table - - These @samp{-m} switches are supported in addition to the above -diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c -new file mode 100644 -index 00000000000..db2f3416823 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile { target { ! ia32 } } } */ -+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void (*fptr) (void); -+ -+void -+foo (void) -+{ -+ fptr (); -+} -+ -+/* { dg-final { scan-assembler-times "jmp\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */ -+/* { dg-final { scan-assembler-times "\tcs" 1 } } */ -diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c -new file mode 100644 -index 00000000000..adfc39a49d4 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c -@@ -0,0 +1,15 @@ -+/* { dg-do compile { target { ! ia32 } } } */ -+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */ -+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ -+ -+extern void (*bar) (void); -+ -+int -+foo (void) -+{ -+ bar (); -+ return 0; -+} -+ -+/* { dg-final { scan-assembler-times "call\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */ -+/* { dg-final { scan-assembler-times "\tcs" 1 } } */ --- -2.36.1 - diff --git a/SOURCES/gcc8-harden-3.patch b/SOURCES/gcc8-harden-3.patch deleted file mode 100644 index ecb643a..0000000 --- a/SOURCES/gcc8-harden-3.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 621de498ee19e1f2642eebde707430254c0459c0 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Wed, 5 Jan 2022 16:33:16 -0800 -Subject: [PATCH 3/4] x86: Rename -harden-sls=indirect-branch to - -harden-sls=indirect-jmp - -Indirect branch also includes indirect call instructions. Rename --harden-sls=indirect-branch to -harden-sls=indirect-jmp to match its -intended behavior. - - PR target/102952 - * config/i386/i386-opts.h (harden_sls): Replace - harden_sls_indirect_branch with harden_sls_indirect_jmp. - * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): - Likewise. - (ix86_output_indirect_jmp): Likewise. - (ix86_output_call_insn): Likewise. - * config/i386/i386.opt: Replace indirect-branch with - indirect-jmp. Replace harden_sls_indirect_branch with - harden_sls_indirect_jmp. - * doc/invoke.texi (-harden-sls=): Replace indirect-branch with - indirect-jmp. - -(cherry picked from commit ed8060950c64f2e449aaf90e438aa26d0d9d0b31) ---- - gcc/config/i386/i386-opts.h | 4 ++-- - gcc/config/i386/i386.c | 6 +++--- - gcc/config/i386/i386.opt | 2 +- - gcc/doc/invoke.texi | 4 ++-- - 4 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h -index 34718b6d52c..47facc254cd 100644 ---- a/gcc/config/i386/i386-opts.h -+++ b/gcc/config/i386/i386-opts.h -@@ -122,8 +122,8 @@ enum indirect_branch { - enum harden_sls { - harden_sls_none = 0, - harden_sls_return = 1 << 0, -- harden_sls_indirect_branch = 1 << 1, -- harden_sls_all = harden_sls_return | harden_sls_indirect_branch -+ harden_sls_indirect_jmp = 1 << 1, -+ harden_sls_all = harden_sls_return | harden_sls_indirect_jmp - }; - - #endif -diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c -index 8442dd0daea..3bc14e20105 100644 ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -28736,7 +28736,7 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, - } - assemble_name (asm_out_file, thunk_name); - putc ('\n', asm_out_file); -- if ((ix86_harden_sls & harden_sls_indirect_branch)) -+ if ((ix86_harden_sls & harden_sls_indirect_jmp)) - fputs ("\tint3\n", asm_out_file); - } - else -@@ -28991,7 +28991,7 @@ ix86_output_indirect_jmp (rtx call_op) - } - else - output_asm_insn ("%!jmp\t%A0", &call_op); -- return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : ""; -+ return (ix86_harden_sls & harden_sls_indirect_jmp) ? "int3" : ""; - } - - /* Output function return. CALL_OP is the jump target. Add a REP -@@ -29178,7 +29178,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) - { - output_asm_insn (xasm, &call_op); - if (!direct_p -- && (ix86_harden_sls & harden_sls_indirect_branch)) -+ && (ix86_harden_sls & harden_sls_indirect_jmp)) - return "int3"; - } - return ""; -diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt -index 9f67ef558dc..7a5c7b9369a 100644 ---- a/gcc/config/i386/i386.opt -+++ b/gcc/config/i386/i386.opt -@@ -1075,7 +1075,7 @@ EnumValue - Enum(harden_sls) String(return) Value(harden_sls_return) - - EnumValue --Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch) -+Enum(harden_sls) String(indirect-jmp) Value(harden_sls_indirect_jmp) - - EnumValue - Enum(harden_sls) String(all) Value(harden_sls_all) -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 605cd4b93f1..20d8e3fd782 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -28041,8 +28041,8 @@ Force indirect call and jump via register. - @opindex mharden-sls - Generate code to mitigate against straight line speculation (SLS) with - @var{choice}. The default is @samp{none} which disables all SLS --hardening. @samp{return} enables SLS hardening for function return. --@samp{indirect-branch} enables SLS hardening for indirect branch. -+hardening. @samp{return} enables SLS hardening for function returns. -+@samp{indirect-jmp} enables SLS hardening for indirect jumps. - @samp{all} enables all SLS hardening. - - @item -mindirect-branch-cs-prefix --- -2.36.1 - diff --git a/SOURCES/gcc8-harden-4.patch b/SOURCES/gcc8-harden-4.patch deleted file mode 100644 index 648d543..0000000 --- a/SOURCES/gcc8-harden-4.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 5a5e7890cefa112e95e1de9800d8081c2a38a1da Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Wed, 5 Jan 2022 18:04:21 -0800 -Subject: [PATCH 4/4] x86: Generate INT3 for __builtin_eh_return - -Generate INT3 after indirect jmp in exception return for -fcf-protection -with -mharden-sls=indirect-jmp. - -gcc/ - - PR target/103925 - * config/i386/i386.c (ix86_output_indirect_function_return): - Generate INT3 after indirect jmp for -mharden-sls=indirect-jmp. - -gcc/testsuite/ - - PR target/103925 - * gcc.target/i386/harden-sls-6.c: New test. - -(cherry picked from commit c2e5c4feed32c808591b5278f680bbabe63eb225) ---- - gcc/config/i386/i386.c | 9 ++++++--- - gcc/testsuite/gcc.target/i386/harden-sls-6.c | 18 ++++++++++++++++++ - 2 files changed, 24 insertions(+), 3 deletions(-) - create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-6.c - -diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c -index 3bc14e20105..dbc3d462fda 100644 ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -29083,11 +29083,14 @@ ix86_output_indirect_function_return (rtx ret_op) - } - else - output_indirect_thunk (need_prefix, regno); -- -- return ""; - } - else -- return "%!jmp\t%A0"; -+ { -+ output_asm_insn ("%!jmp\t%A0", &ret_op); -+ if (ix86_harden_sls & harden_sls_indirect_jmp) -+ fputs ("\tint3\n", asm_out_file); -+ } -+ return ""; - } - - /* Split simple return with popping POPC bytes from stack to indirect -diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-6.c b/gcc/testsuite/gcc.target/i386/harden-sls-6.c -new file mode 100644 -index 00000000000..9068eb64008 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/i386/harden-sls-6.c -@@ -0,0 +1,18 @@ -+/* { dg-do compile { target { ! ia32 } } } */ -+/* { dg-options "-O2 -fcf-protection -mharden-sls=indirect-jmp" } */ -+ -+struct _Unwind_Context _Unwind_Resume_or_Rethrow_this_context; -+ -+void offset (int); -+ -+struct _Unwind_Context { -+ void *reg[7]; -+} _Unwind_Resume_or_Rethrow() { -+ struct _Unwind_Context cur_contextcur_context = -+ _Unwind_Resume_or_Rethrow_this_context; -+ offset(0); -+ __builtin_eh_return ((long) offset, 0); -+} -+ -+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rcx" } } */ -+/* { dg-final { scan-assembler-times "int3" 1 } } */ --- -2.36.1 - diff --git a/SOURCES/gcc8-i386-libgomp.patch b/SOURCES/gcc8-i386-libgomp.patch deleted file mode 100644 index 520561e..0000000 --- a/SOURCES/gcc8-i386-libgomp.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- libgomp/configure.tgt.jj 2008-01-10 20:53:48.000000000 +0100 -+++ libgomp/configure.tgt 2008-03-27 12:44:51.000000000 +0100 -@@ -67,7 +67,7 @@ if test $enable_linux_futex = yes; then - ;; - *) - if test -z "$with_arch"; then -- XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}" -+ XCFLAGS="${XCFLAGS} -march=i486 -mtune=generic" - fi - esac - ;; diff --git a/SOURCES/gcc8-libgcc-hardened.patch b/SOURCES/gcc8-libgcc-hardened.patch deleted file mode 100644 index 51f6c39..0000000 --- a/SOURCES/gcc8-libgcc-hardened.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- libgcc/config/t-slibgcc.mp 2018-10-03 16:07:00.336990246 -0400 -+++ libgcc/config/t-slibgcc 2018-10-03 16:06:26.719946740 -0400 -@@ -30,9 +30,10 @@ SHLIB_LC = -lc - SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK) - SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \ - $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK) -+SHLIB_EXTRA_LDFLAGS = -Wl,-z,relro -Wl,-z,now - - SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \ -- $(SHLIB_LDFLAGS) \ -+ $(SHLIB_LDFLAGS) $(SHLIB_EXTRA_LDFLAGS) \ - -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \ - $(SHLIB_OBJS) $(SHLIB_LC) && \ - rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \ diff --git a/SOURCES/gcc8-libgfortran-default-values.patch b/SOURCES/gcc8-libgfortran-default-values.patch deleted file mode 100644 index b070abe..0000000 --- a/SOURCES/gcc8-libgfortran-default-values.patch +++ /dev/null @@ -1,516 +0,0 @@ -diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c -index d93dcfa..f47565c 100644 ---- a/gcc/fortran/io.c -+++ b/gcc/fortran/io.c -@@ -909,6 +909,13 @@ data_desc: - - if (u != FMT_POSINT) - { -+ if (flag_dec) -+ { -+ /* Assume a default width based on the variable size. */ -+ saved_token = u; -+ break; -+ } -+ - format_locus.nextc += format_string_pos; - gfc_error ("Positive width required in format " - "specifier %s at %L", token_to_string (t), -@@ -1030,6 +1037,13 @@ data_desc: - goto fail; - if (t != FMT_ZERO && t != FMT_POSINT) - { -+ if (flag_dec) -+ { -+ /* Assume the default width is expected here and continue lexing. */ -+ value = 0; /* It doesn't matter what we set the value to here. */ -+ saved_token = t; -+ break; -+ } - error = nonneg_required; - goto syntax; - } -@@ -1099,8 +1113,17 @@ data_desc: - goto fail; - if (t != FMT_ZERO && t != FMT_POSINT) - { -- error = nonneg_required; -- goto syntax; -+ if (flag_dec) -+ { -+ /* Assume the default width is expected here and continue lexing. */ -+ value = 0; /* It doesn't matter what we set the value to here. */ -+ saved_token = t; -+ } -+ else -+ { -+ error = nonneg_required; -+ goto syntax; -+ } - } - else if (is_input && t == FMT_ZERO) - { -diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90 -new file mode 100644 -index 0000000..b087b8f ---- /dev/null -+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90 -@@ -0,0 +1,43 @@ -+! { dg-do run } -+! { dg-options -fdec } -+! -+! Test case for the default field widths enabled by the -fdec-format-defaults flag. -+! -+! This feature is not part of any Fortran standard, but it is supported by the -+! Oracle Fortran compiler and others. -+! -+! libgfortran uses printf() internally to implement FORMAT. If you print float -+! values to a higher precision than the type can actually store, the results -+! are implementation dependent: some platforms print zeros, others print random -+! numbers. Don't depend on this behaviour in tests because they will not be -+! portable. -+ -+ character(50) :: buffer -+ -+ real*4 :: real_4 -+ real*8 :: real_8 -+ real*16 :: real_16 -+ integer :: len -+ -+ real_4 = 4.18 -+ write(buffer, '(A, F, A)') ':',real_4,':' -+ print *,buffer -+ if (buffer.ne.": 4.1799998:") call abort -+ -+ real_4 = 0.00000018 -+ write(buffer, '(A, F, A)') ':',real_4,':' -+ print *,buffer -+ if (buffer.ne.": 0.0000002:") call abort -+ -+ real_8 = 4.18 -+ write(buffer, '(A, F, A)') ':',real_8,':' -+ print *,buffer -+ len = len_trim(buffer) -+ if (len /= 27) call abort -+ -+ real_16 = 4.18 -+ write(buffer, '(A, F, A)') ':',real_16,':' -+ print *,buffer -+ len = len_trim(buffer) -+ if (len /= 44) call abort -+end -diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90 -new file mode 100644 -index 0000000..3d3a476 ---- /dev/null -+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90 -@@ -0,0 +1,48 @@ -+! { dg-do run } -+! { dg-options -fdec } -+! -+! Test case for the default field widths enabled by the -fdec-format-defaults flag. -+! -+! This feature is not part of any Fortran standard, but it is supported by the -+! Oracle Fortran compiler and others. -+! -+! libgfortran uses printf() internally to implement FORMAT. If you print float -+! values to a higher precision than the type can actually store, the results -+! are implementation dependent: some platforms print zeros, others print random -+! numbers. Don't depend on this behaviour in tests because they will not be -+! portable. -+ -+ character(50) :: buffer -+ -+ real*4 :: real_4 -+ real*8 :: real_8 -+ real*16 :: real_16 -+ integer :: len -+ -+ real_4 = 4.18 -+ write(buffer, '(A, G, A)') ':',real_4,':' -+ print *,buffer -+ if (buffer.ne.": 4.180000 :") call abort -+ -+ real_4 = 0.00000018 -+ write(buffer, '(A, G, A)') ':',real_4,':' -+ print *,buffer -+ if (buffer.ne.": 0.1800000E-06:") call abort -+ -+ real_4 = 18000000.4 -+ write(buffer, '(A, G, A)') ':',real_4,':' -+ print *,buffer -+ if (buffer.ne.": 0.1800000E+08:") call abort -+ -+ real_8 = 4.18 -+ write(buffer, '(A, G, A)') ':',real_8,':' -+ print *,buffer -+ len = len_trim(buffer) -+ if (len /= 27) call abort -+ -+ real_16 = 4.18 -+ write(buffer, '(A, G, A)') ':',real_16,':' -+ print *,buffer -+ len = len_trim(buffer) -+ if (len /= 44) call abort -+end -diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90 -new file mode 100644 -index 0000000..ac4e165 ---- /dev/null -+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90 -@@ -0,0 +1,38 @@ -+! { dg-do run } -+! { dg-options -fdec } -+! -+! Test case for the default field widths enabled by the -fdec-format-defaults flag. -+! -+! This feature is not part of any Fortran standard, but it is supported by the -+! Oracle Fortran compiler and others. -+ -+ character(50) :: buffer -+ character(1) :: colon -+ -+ integer*2 :: integer_2 -+ integer*4 :: integer_4 -+ integer*8 :: integer_8 -+ -+ write(buffer, '(A, I, A)') ':',12340,':' -+ print *,buffer -+ if (buffer.ne.": 12340:") call abort -+ -+ read(buffer, '(A1, I, A1)') colon, integer_4, colon -+ if (integer_4.ne.12340) call abort -+ -+ integer_2 = -99 -+ write(buffer, '(A, I, A)') ':',integer_2,':' -+ print *,buffer -+ if (buffer.ne.": -99:") call abort -+ -+ integer_8 = -11112222 -+ write(buffer, '(A, I, A)') ':',integer_8,':' -+ print *,buffer -+ if (buffer.ne.": -11112222:") call abort -+ -+! If the width is 7 and there are 7 leading zeroes, the result should be zero. -+ integer_2 = 789 -+ buffer = '0000000789' -+ read(buffer, '(I)') integer_2 -+ if (integer_2.ne.0) call abort -+end -diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c -index c2abdd7..692b1ff 100644 ---- a/libgfortran/io/format.c -+++ b/libgfortran/io/format.c -@@ -956,12 +956,33 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd) - *seen_dd = true; - if (u != FMT_POSINT && u != FMT_ZERO) - { -+ if (dtp->common.flags & IOPARM_DT_DEC_EXT) -+ { -+ tail->u.real.w = DEFAULT_WIDTH; -+ tail->u.real.d = 0; -+ tail->u.real.e = -1; -+ fmt->saved_token = u; -+ break; -+ } - fmt->error = nonneg_required; - goto finished; - } - } -+ else if (u == FMT_ZERO) -+ { -+ fmt->error = posint_required; -+ goto finished; -+ } - else if (u != FMT_POSINT) - { -+ if (dtp->common.flags & IOPARM_DT_DEC_EXT) -+ { -+ tail->u.real.w = DEFAULT_WIDTH; -+ tail->u.real.d = 0; -+ tail->u.real.e = -1; -+ fmt->saved_token = u; -+ break; -+ } - fmt->error = posint_required; - goto finished; - } -@@ -1099,6 +1120,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd) - { - if (t != FMT_POSINT) - { -+ if (dtp->common.flags & IOPARM_DT_DEC_EXT) -+ { -+ tail->u.integer.w = DEFAULT_WIDTH; -+ tail->u.integer.m = -1; -+ fmt->saved_token = t; -+ break; -+ } - fmt->error = posint_required; - goto finished; - } -@@ -1107,6 +1135,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd) - { - if (t != FMT_ZERO && t != FMT_POSINT) - { -+ if (dtp->common.flags & IOPARM_DT_DEC_EXT) -+ { -+ tail->u.integer.w = DEFAULT_WIDTH; -+ tail->u.integer.m = -1; -+ fmt->saved_token = t; -+ break; -+ } - fmt->error = nonneg_required; - goto finished; - } -diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h -index 5583183..d1d08e8 100644 ---- a/libgfortran/io/io.h -+++ b/libgfortran/io/io.h -@@ -981,5 +981,55 @@ memset4 (gfc_char4_t *p, gfc_char4_t c, int k) - *p++ = c; - } - -+/* Used in width fields to indicate that the default should be used */ -+#define DEFAULT_WIDTH -1 -+ -+/* Defaults for certain format field descriptors. These are decided based on -+ * the type of the value being formatted. -+ * -+ * The behaviour here is modelled on the Oracle Fortran compiler. At the time -+ * of writing, the details were available at this URL: -+ * -+ * https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnc3/index.html#z4000743746d -+ */ -+ -+static inline int -+default_width_for_integer (int kind) -+{ -+ switch (kind) -+ { -+ case 1: -+ case 2: return 7; -+ case 4: return 12; -+ case 8: return 23; -+ case 16: return 44; -+ default: return 0; -+ } -+} -+ -+static inline int -+default_width_for_float (int kind) -+{ -+ switch (kind) -+ { -+ case 4: return 15; -+ case 8: return 25; -+ case 16: return 42; -+ default: return 0; -+ } -+} -+ -+static inline int -+default_precision_for_float (int kind) -+{ -+ switch (kind) -+ { -+ case 4: return 7; -+ case 8: return 16; -+ case 16: return 33; -+ default: return 0; -+ } -+} -+ - #endif - -diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c -index 2c9de48..e911e35 100644 ---- a/libgfortran/io/read.c -+++ b/libgfortran/io/read.c -@@ -629,6 +629,12 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) - - w = f->u.w; - -+ /* This is a legacy extension, and the frontend will only allow such cases -+ * through when -fdec-format-defaults is passed. -+ */ -+ if (w == DEFAULT_WIDTH) -+ w = default_width_for_integer (length); -+ - p = read_block_form (dtp, &w); - - if (p == NULL) -diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c -index a7307a8..c8e52fb 100644 ---- a/libgfortran/io/write.c -+++ b/libgfortran/io/write.c -@@ -684,9 +684,8 @@ write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len) - p[wlen - 1] = (n) ? 'T' : 'F'; - } - -- - static void --write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n) -+write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n, int len) - { - int w, m, digits, nzero, nblank; - char *p; -@@ -719,6 +718,9 @@ write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n) - /* Select a width if none was specified. The idea here is to always - print something. */ - -+ if (w == DEFAULT_WIDTH) -+ w = default_width_for_integer (len); -+ - if (w == 0) - w = ((digits < m) ? m : digits); - -@@ -845,6 +847,8 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source, - - /* Select a width if none was specified. The idea here is to always - print something. */ -+ if (w == DEFAULT_WIDTH) -+ w = default_width_for_integer (len); - - if (w == 0) - w = ((digits < m) ? m : digits) + nsign; -@@ -1187,13 +1191,13 @@ write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len) - if (len > (int) sizeof (GFC_UINTEGER_LARGEST)) - { - p = btoa_big (source, itoa_buf, len, &n); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - else - { - n = extract_uint (source, len); - p = btoa (n, itoa_buf, sizeof (itoa_buf)); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - } - -@@ -1208,13 +1212,13 @@ write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len) - if (len > (int) sizeof (GFC_UINTEGER_LARGEST)) - { - p = otoa_big (source, itoa_buf, len, &n); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - else - { - n = extract_uint (source, len); - p = otoa (n, itoa_buf, sizeof (itoa_buf)); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - } - -@@ -1228,13 +1232,13 @@ write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len) - if (len > (int) sizeof (GFC_UINTEGER_LARGEST)) - { - p = ztoa_big (source, itoa_buf, len, &n); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - else - { - n = extract_uint (source, len); - p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf)); -- write_boz (dtp, f, p, n); -+ write_boz (dtp, f, p, n, len); - } - } - -@@ -1504,7 +1508,7 @@ size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind) - { - int size; - -- if (f->format == FMT_F && f->u.real.w == 0) -+ if ((f->format == FMT_F && f->u.real.w == 0) || f->u.real.w == DEFAULT_WIDTH) - { - switch (kind) - { -diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def -index 7f0aa1d..73dc910 100644 ---- a/libgfortran/io/write_float.def -+++ b/libgfortran/io/write_float.def -@@ -113,7 +113,8 @@ determine_precision (st_parameter_dt * d - static void - build_float_string (st_parameter_dt *dtp, const fnode *f, char *buffer, - size_t size, int nprinted, int precision, int sign_bit, -- bool zero_flag, int npad, char *result, size_t *len) -+ bool zero_flag, int npad, int default_width, char *result, -+ size_t *len) - { - char *put; - char *digits; -@@ -132,8 +133,17 @@ build_float_string (st_parameter_dt *dtp - sign_t sign; - - ft = f->format; -- w = f->u.real.w; -- d = f->u.real.d; -+ if (f->u.real.w == DEFAULT_WIDTH) -+ /* This codepath can only be reached with -fdec-format-defaults. */ -+ { -+ w = default_width; -+ d = precision; -+ } -+ else -+ { -+ w = f->u.real.w; -+ d = f->u.real.d; -+ } - p = dtp->u.p.scale_factor; - *len = 0; - -@@ -959,6 +969,11 @@ determine_en_precision (st_parameter_dt - int save_scale_factor;\ - volatile GFC_REAL_ ## x temp;\ - save_scale_factor = dtp->u.p.scale_factor;\ -+ if (w == DEFAULT_WIDTH)\ -+ {\ -+ w = default_width;\ -+ d = precision;\ -+ }\ - switch (dtp->u.p.current_unit->round_status)\ - {\ - case ROUND_ZERO:\ -@@ -1034,7 +1049,8 @@ determine_en_precision (st_parameter_dt - nprinted = FDTOA(y,precision,m);\ - }\ - build_float_string (dtp, &newf, buffer, size, nprinted, precision,\ -- sign_bit, zero_flag, npad, result, res_len);\ -+ sign_bit, zero_flag, npad, default_width,\ -+ result, res_len);\ - dtp->u.p.scale_factor = save_scale_factor;\ - }\ - else\ -@@ -1044,7 +1060,8 @@ determine_en_precision (st_parameter_dt - else\ - nprinted = DTOA(y,precision,m);\ - build_float_string (dtp, f, buffer, size, nprinted, precision,\ -- sign_bit, zero_flag, npad, result, res_len);\ -+ sign_bit, zero_flag, npad, default_width,\ -+ result, res_len);\ - }\ - }\ - -@@ -1058,6 +1075,16 @@ get_float_string (st_parameter_dt *dtp, - { - int sign_bit, nprinted; - bool zero_flag; -+ int default_width = 0; -+ -+ if (f->u.real.w == DEFAULT_WIDTH) -+ /* This codepath can only be reached with -fdec-format-defaults. The default -+ * values are based on those used in the Oracle Fortran compiler. -+ */ -+ { -+ default_width = default_width_for_float (kind); -+ precision = default_precision_for_float (kind); -+ } - - switch (kind) - { diff --git a/SOURCES/gcc8-libgomp-20190503.patch b/SOURCES/gcc8-libgomp-20190503.patch deleted file mode 100644 index fcd226d..0000000 --- a/SOURCES/gcc8-libgomp-20190503.patch +++ /dev/null @@ -1,10068 +0,0 @@ ---- libgomp/loop.c.jj 2018-04-25 09:40:31.870655561 +0200 -+++ libgomp/loop.c 2019-05-07 18:46:36.526109736 +0200 -@@ -27,9 +27,13 @@ - - #include - #include -+#include - #include "libgomp.h" - - -+ialias (GOMP_loop_runtime_next) -+ialias_redirect (GOMP_taskgroup_reduction_register) -+ - /* Initialize the given work share construct from the given arguments. */ - - static inline void -@@ -79,12 +83,12 @@ gomp_loop_init (struct gomp_work_share * - } - - /* The *_start routines are called when first encountering a loop construct -- that is not bound directly to a parallel construct. The first thread -+ that is not bound directly to a parallel construct. The first thread - that arrives will create the work-share construct; subsequent threads - will see the construct exists and allocate work from it. - - START, END, INCR are the bounds of the loop; due to the restrictions of -- OpenMP, these values must be the same in every thread. This is not -+ OpenMP, these values must be the same in every thread. This is not - verified (nor is it entirely verifiable, since START is not necessarily - retained intact in the work-share data structure). CHUNK_SIZE is the - scheduling parameter; again this must be identical in all threads. -@@ -101,7 +105,7 @@ gomp_loop_static_start (long start, long - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_STATIC, chunk_size); -@@ -123,7 +127,7 @@ gomp_loop_dynamic_start (long start, lon - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_DYNAMIC, chunk_size); -@@ -151,7 +155,7 @@ gomp_loop_guided_start (long start, long - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_GUIDED, chunk_size); -@@ -174,7 +178,7 @@ GOMP_loop_runtime_start (long start, lon - long *istart, long *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_static_start (start, end, incr, -@@ -197,6 +201,100 @@ GOMP_loop_runtime_start (long start, lon - } - } - -+static long -+gomp_adjust_sched (long sched, long *chunk_size) -+{ -+ sched &= ~GFS_MONOTONIC; -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_DYNAMIC: -+ case GFS_GUIDED: -+ return sched; -+ /* GFS_RUNTIME is used for runtime schedule without monotonic -+ or nonmonotonic modifiers on the clause. -+ GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic -+ modifier. */ -+ case GFS_RUNTIME: -+ /* GFS_AUTO is used for runtime schedule with nonmonotonic -+ modifier. */ -+ case GFS_AUTO: -+ { -+ struct gomp_task_icv *icv = gomp_icv (false); -+ sched = icv->run_sched_var & ~GFS_MONOTONIC; -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_DYNAMIC: -+ case GFS_GUIDED: -+ *chunk_size = icv->run_sched_chunk_size; -+ break; -+ case GFS_AUTO: -+ sched = GFS_STATIC; -+ *chunk_size = 0; -+ break; -+ default: -+ abort (); -+ } -+ return sched; -+ } -+ default: -+ abort (); -+ } -+} -+ -+bool -+GOMP_loop_start (long start, long end, long incr, long sched, -+ long chunk_size, long *istart, long *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (gomp_work_share_start (0)) -+ { -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_init (thr->ts.work_share, start, end, incr, -+ sched, chunk_size); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ if (mem) -+ { -+ uintptr_t size = (uintptr_t) *mem; -+ if (size > (sizeof (struct gomp_work_share) -+ - offsetof (struct gomp_work_share, -+ inline_ordered_team_ids))) -+ thr->ts.work_share->ordered_team_ids -+ = gomp_malloc_cleared (size); -+ else -+ memset (thr->ts.work_share->ordered_team_ids, '\0', size); -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ if (mem) -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ -+ if (!istart) -+ return true; -+ return ialias_call (GOMP_loop_runtime_next) (istart, iend); -+} -+ - /* The *_ordered_*_start routines are similar. The only difference is that - this work-share construct is initialized to expect an ORDERED section. */ - -@@ -207,7 +305,7 @@ gomp_loop_ordered_static_start (long sta - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_STATIC, chunk_size); -@@ -225,7 +323,7 @@ gomp_loop_ordered_dynamic_start (long st - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_DYNAMIC, chunk_size); -@@ -250,7 +348,7 @@ gomp_loop_ordered_guided_start (long sta - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_init (thr->ts.work_share, start, end, incr, - GFS_GUIDED, chunk_size); -@@ -273,7 +371,7 @@ GOMP_loop_ordered_runtime_start (long st - long *istart, long *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_ordered_static_start (start, end, incr, -@@ -297,6 +395,81 @@ GOMP_loop_ordered_runtime_start (long st - } - } - -+bool -+GOMP_loop_ordered_start (long start, long end, long incr, long sched, -+ long chunk_size, long *istart, long *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ size_t ordered = 1; -+ bool ret; -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (mem) -+ ordered += (uintptr_t) *mem; -+ if (gomp_work_share_start (ordered)) -+ { -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_init (thr->ts.work_share, start, end, incr, -+ sched, chunk_size); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ if (sched == GFS_STATIC) -+ gomp_ordered_static_init (); -+ else -+ gomp_mutex_lock (&thr->ts.work_share->lock); -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ sched = thr->ts.work_share->sched; -+ if (sched != GFS_STATIC) -+ gomp_mutex_lock (&thr->ts.work_share->lock); -+ } -+ -+ if (mem) -+ { -+ uintptr_t p -+ = (uintptr_t) (thr->ts.work_share->ordered_team_ids -+ + (thr->ts.team ? thr->ts.team->nthreads : 1)); -+ p += __alignof__ (long long) - 1; -+ p &= ~(__alignof__ (long long) - 1); -+ *mem = (void *) p; -+ } -+ -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_AUTO: -+ return !gomp_iter_static_next (istart, iend); -+ case GFS_DYNAMIC: -+ ret = gomp_iter_dynamic_next_locked (istart, iend); -+ break; -+ case GFS_GUIDED: -+ ret = gomp_iter_guided_next_locked (istart, iend); -+ break; -+ default: -+ abort (); -+ } -+ -+ if (ret) -+ gomp_ordered_first (); -+ gomp_mutex_unlock (&thr->ts.work_share->lock); -+ return ret; -+} -+ - /* The *_doacross_*_start routines are similar. The only difference is that - this work-share construct is initialized to expect an ORDERED(N) - DOACROSS - section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1 -@@ -310,11 +483,11 @@ gomp_loop_doacross_static_start (unsigne - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, - GFS_STATIC, chunk_size); -- gomp_doacross_init (ncounts, counts, chunk_size); -+ gomp_doacross_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -328,11 +501,11 @@ gomp_loop_doacross_dynamic_start (unsign - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, - GFS_DYNAMIC, chunk_size); -- gomp_doacross_init (ncounts, counts, chunk_size); -+ gomp_doacross_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -354,11 +527,11 @@ gomp_loop_doacross_guided_start (unsigne - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, - GFS_GUIDED, chunk_size); -- gomp_doacross_init (ncounts, counts, chunk_size); -+ gomp_doacross_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -378,7 +551,7 @@ GOMP_loop_doacross_runtime_start (unsign - long *istart, long *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_doacross_static_start (ncounts, counts, -@@ -402,8 +575,52 @@ GOMP_loop_doacross_runtime_start (unsign - } - } - --/* The *_next routines are called when the thread completes processing of -- the iteration block currently assigned to it. If the work-share -+bool -+GOMP_loop_doacross_start (unsigned ncounts, long *counts, long sched, -+ long chunk_size, long *istart, long *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (gomp_work_share_start (0)) -+ { -+ size_t extra = 0; -+ if (mem) -+ extra = (uintptr_t) *mem; -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, -+ sched, chunk_size); -+ gomp_doacross_init (ncounts, counts, chunk_size, extra); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ sched = thr->ts.work_share->sched; -+ } -+ -+ if (mem) -+ *mem = thr->ts.work_share->doacross->extra; -+ -+ return ialias_call (GOMP_loop_runtime_next) (istart, iend); -+} -+ -+/* The *_next routines are called when the thread completes processing of -+ the iteration block currently assigned to it. If the work-share - construct is bound directly to a parallel construct, then the iteration - bounds may have been set up before the parallel. In which case, this - may be the first iteration for the thread. -@@ -456,7 +673,7 @@ bool - GOMP_loop_runtime_next (long *istart, long *iend) - { - struct gomp_thread *thr = gomp_thread (); -- -+ - switch (thr->ts.work_share->sched) - { - case GFS_STATIC: -@@ -534,7 +751,7 @@ bool - GOMP_loop_ordered_runtime_next (long *istart, long *iend) - { - struct gomp_thread *thr = gomp_thread (); -- -+ - switch (thr->ts.work_share->sched) - { - case GFS_STATIC: -@@ -563,7 +780,7 @@ gomp_parallel_loop_start (void (*fn) (vo - num_threads = gomp_resolve_num_threads (num_threads, 0); - team = gomp_new_team (num_threads); - gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size); -- gomp_team_start (fn, data, num_threads, flags, team); -+ gomp_team_start (fn, data, num_threads, flags, team, NULL); - } - - void -@@ -600,7 +817,8 @@ GOMP_parallel_loop_runtime_start (void ( - { - struct gomp_task_icv *icv = gomp_icv (false); - gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, -- icv->run_sched_var, icv->run_sched_chunk_size, 0); -+ icv->run_sched_var & ~GFS_MONOTONIC, -+ icv->run_sched_chunk_size, 0); - } - - ialias_redirect (GOMP_parallel_end) -@@ -638,11 +856,28 @@ GOMP_parallel_loop_guided (void (*fn) (v - GOMP_parallel_end (); - } - -+void -+GOMP_parallel_loop_runtime (void (*fn) (void *), void *data, -+ unsigned num_threads, long start, long end, -+ long incr, unsigned flags) -+{ -+ struct gomp_task_icv *icv = gomp_icv (false); -+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, -+ icv->run_sched_var & ~GFS_MONOTONIC, -+ icv->run_sched_chunk_size, flags); -+ fn (data); -+ GOMP_parallel_end (); -+} -+ - #ifdef HAVE_ATTRIBUTE_ALIAS - extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic - __attribute__((alias ("GOMP_parallel_loop_dynamic"))); - extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided - __attribute__((alias ("GOMP_parallel_loop_guided"))); -+extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_nonmonotonic_runtime -+ __attribute__((alias ("GOMP_parallel_loop_runtime"))); -+extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_maybe_nonmonotonic_runtime -+ __attribute__((alias ("GOMP_parallel_loop_runtime"))); - #else - void - GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data, -@@ -667,21 +902,35 @@ GOMP_parallel_loop_nonmonotonic_guided ( - fn (data); - GOMP_parallel_end (); - } --#endif - - void --GOMP_parallel_loop_runtime (void (*fn) (void *), void *data, -- unsigned num_threads, long start, long end, -- long incr, unsigned flags) -+GOMP_parallel_loop_nonmonotonic_runtime (void (*fn) (void *), void *data, -+ unsigned num_threads, long start, -+ long end, long incr, unsigned flags) - { - struct gomp_task_icv *icv = gomp_icv (false); - gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, -- icv->run_sched_var, icv->run_sched_chunk_size, -- flags); -+ icv->run_sched_var & ~GFS_MONOTONIC, -+ icv->run_sched_chunk_size, flags); - fn (data); - GOMP_parallel_end (); - } - -+void -+GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*fn) (void *), void *data, -+ unsigned num_threads, long start, -+ long end, long incr, -+ unsigned flags) -+{ -+ struct gomp_task_icv *icv = gomp_icv (false); -+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, -+ icv->run_sched_var & ~GFS_MONOTONIC, -+ icv->run_sched_chunk_size, flags); -+ fn (data); -+ GOMP_parallel_end (); -+} -+#endif -+ - /* The GOMP_loop_end* routines are called after the thread is told that - all loop iterations are complete. The first two versions synchronize - all threads; the nowait version does not. */ -@@ -721,6 +970,10 @@ extern __typeof(gomp_loop_dynamic_start) - __attribute__((alias ("gomp_loop_dynamic_start"))); - extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start - __attribute__((alias ("gomp_loop_guided_start"))); -+extern __typeof(GOMP_loop_runtime_start) GOMP_loop_nonmonotonic_runtime_start -+ __attribute__((alias ("GOMP_loop_runtime_start"))); -+extern __typeof(GOMP_loop_runtime_start) GOMP_loop_maybe_nonmonotonic_runtime_start -+ __attribute__((alias ("GOMP_loop_runtime_start"))); - - extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start - __attribute__((alias ("gomp_loop_ordered_static_start"))); -@@ -746,6 +999,10 @@ extern __typeof(gomp_loop_dynamic_next) - __attribute__((alias ("gomp_loop_dynamic_next"))); - extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next - __attribute__((alias ("gomp_loop_guided_next"))); -+extern __typeof(GOMP_loop_runtime_next) GOMP_loop_nonmonotonic_runtime_next -+ __attribute__((alias ("GOMP_loop_runtime_next"))); -+extern __typeof(GOMP_loop_runtime_next) GOMP_loop_maybe_nonmonotonic_runtime_next -+ __attribute__((alias ("GOMP_loop_runtime_next"))); - - extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next - __attribute__((alias ("gomp_loop_ordered_static_next"))); -@@ -791,6 +1048,20 @@ GOMP_loop_nonmonotonic_guided_start (lon - } - - bool -+GOMP_loop_nonmonotonic_runtime_start (long start, long end, long incr, -+ long *istart, long *iend) -+{ -+ return GOMP_loop_runtime_start (start, end, incr, istart, iend); -+} -+ -+bool -+GOMP_loop_maybe_nonmonotonic_runtime_start (long start, long end, long incr, -+ long *istart, long *iend) -+{ -+ return GOMP_loop_runtime_start (start, end, incr, istart, iend); -+} -+ -+bool - GOMP_loop_ordered_static_start (long start, long end, long incr, - long chunk_size, long *istart, long *iend) - { -@@ -869,6 +1140,18 @@ GOMP_loop_nonmonotonic_guided_next (long - } - - bool -+GOMP_loop_nonmonotonic_runtime_next (long *istart, long *iend) -+{ -+ return GOMP_loop_runtime_next (istart, iend); -+} -+ -+bool -+GOMP_loop_maybe_nonmonotonic_runtime_next (long *istart, long *iend) -+{ -+ return GOMP_loop_runtime_next (istart, iend); -+} -+ -+bool - GOMP_loop_ordered_static_next (long *istart, long *iend) - { - return gomp_loop_ordered_static_next (istart, iend); ---- libgomp/oacc-plugin.c.jj 2018-04-25 09:40:31.322655307 +0200 -+++ libgomp/oacc-plugin.c 2019-05-07 18:46:36.531109656 +0200 -@@ -49,3 +49,14 @@ GOMP_PLUGIN_acc_thread (void) - struct goacc_thread *thr = goacc_thread (); - return thr ? thr->target_tls : NULL; - } -+ -+int -+GOMP_PLUGIN_acc_default_dim (unsigned int i) -+{ -+ if (i >= GOMP_DIM_MAX) -+ { -+ gomp_fatal ("invalid dimension argument: %d", i); -+ return -1; -+ } -+ return goacc_default_dims[i]; -+} ---- libgomp/libgomp_g.h.jj 2018-04-25 09:40:31.320655306 +0200 -+++ libgomp/libgomp_g.h 2019-05-07 18:46:36.513109943 +0200 -@@ -1,4 +1,4 @@ --/* Copyright (C) 2005-2018 Free Software Foundation, Inc. -+/* Copyright (C) 2005-2019 Free Software Foundation, Inc. - Contributed by Richard Henderson . - - This file is part of the GNU Offloading and Multi Processing Library -@@ -31,6 +31,7 @@ - - #include - #include -+#include "gstdint.h" - - /* barrier.c */ - -@@ -56,6 +57,12 @@ extern bool GOMP_loop_nonmonotonic_dynam - long *, long *); - extern bool GOMP_loop_nonmonotonic_guided_start (long, long, long, long, - long *, long *); -+extern bool GOMP_loop_nonmonotonic_runtime_start (long, long, long, -+ long *, long *); -+extern bool GOMP_loop_maybe_nonmonotonic_runtime_start (long, long, long, -+ long *, long *); -+extern bool GOMP_loop_start (long, long, long, long, long, long *, long *, -+ uintptr_t *, void **); - - extern bool GOMP_loop_ordered_static_start (long, long, long, long, - long *, long *); -@@ -64,6 +71,8 @@ extern bool GOMP_loop_ordered_dynamic_st - extern bool GOMP_loop_ordered_guided_start (long, long, long, long, - long *, long *); - extern bool GOMP_loop_ordered_runtime_start (long, long, long, long *, long *); -+extern bool GOMP_loop_ordered_start (long, long, long, long, long, long *, -+ long *, uintptr_t *, void **); - - extern bool GOMP_loop_static_next (long *, long *); - extern bool GOMP_loop_dynamic_next (long *, long *); -@@ -71,6 +80,8 @@ extern bool GOMP_loop_guided_next (long - extern bool GOMP_loop_runtime_next (long *, long *); - extern bool GOMP_loop_nonmonotonic_dynamic_next (long *, long *); - extern bool GOMP_loop_nonmonotonic_guided_next (long *, long *); -+extern bool GOMP_loop_nonmonotonic_runtime_next (long *, long *); -+extern bool GOMP_loop_maybe_nonmonotonic_runtime_next (long *, long *); - - extern bool GOMP_loop_ordered_static_next (long *, long *); - extern bool GOMP_loop_ordered_dynamic_next (long *, long *); -@@ -85,6 +96,8 @@ extern bool GOMP_loop_doacross_guided_st - long *); - extern bool GOMP_loop_doacross_runtime_start (unsigned, long *, long *, - long *); -+extern bool GOMP_loop_doacross_start (unsigned, long *, long, long, long *, -+ long *, uintptr_t *, void **); - - extern void GOMP_parallel_loop_static_start (void (*)(void *), void *, - unsigned, long, long, long, long); -@@ -112,6 +125,13 @@ extern void GOMP_parallel_loop_nonmonoto - extern void GOMP_parallel_loop_nonmonotonic_guided (void (*)(void *), void *, - unsigned, long, long, - long, long, unsigned); -+extern void GOMP_parallel_loop_nonmonotonic_runtime (void (*)(void *), void *, -+ unsigned, long, long, -+ long, unsigned); -+extern void GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*)(void *), -+ void *, unsigned, -+ long, long, -+ long, unsigned); - - extern void GOMP_loop_end (void); - extern void GOMP_loop_end_nowait (void); -@@ -154,6 +174,21 @@ extern bool GOMP_loop_ull_nonmonotonic_g - unsigned long long, - unsigned long long *, - unsigned long long *); -+extern bool GOMP_loop_ull_nonmonotonic_runtime_start (bool, unsigned long long, -+ unsigned long long, -+ unsigned long long, -+ unsigned long long *, -+ unsigned long long *); -+extern bool GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool, -+ unsigned long long, -+ unsigned long long, -+ unsigned long long, -+ unsigned long long *, -+ unsigned long long *); -+extern bool GOMP_loop_ull_start (bool, unsigned long long, unsigned long long, -+ unsigned long long, long, unsigned long long, -+ unsigned long long *, unsigned long long *, -+ uintptr_t *, void **); - - extern bool GOMP_loop_ull_ordered_static_start (bool, unsigned long long, - unsigned long long, -@@ -178,6 +213,13 @@ extern bool GOMP_loop_ull_ordered_runtim - unsigned long long, - unsigned long long *, - unsigned long long *); -+extern bool GOMP_loop_ull_ordered_start (bool, unsigned long long, -+ unsigned long long, -+ unsigned long long, long, -+ unsigned long long, -+ unsigned long long *, -+ unsigned long long *, -+ uintptr_t *, void **); - - extern bool GOMP_loop_ull_static_next (unsigned long long *, - unsigned long long *); -@@ -191,6 +233,10 @@ extern bool GOMP_loop_ull_nonmonotonic_d - unsigned long long *); - extern bool GOMP_loop_ull_nonmonotonic_guided_next (unsigned long long *, - unsigned long long *); -+extern bool GOMP_loop_ull_nonmonotonic_runtime_next (unsigned long long *, -+ unsigned long long *); -+extern bool GOMP_loop_ull_maybe_nonmonotonic_runtime_next (unsigned long long *, -+ unsigned long long *); - - extern bool GOMP_loop_ull_ordered_static_next (unsigned long long *, - unsigned long long *); -@@ -220,6 +266,11 @@ extern bool GOMP_loop_ull_doacross_runti - unsigned long long *, - unsigned long long *, - unsigned long long *); -+extern bool GOMP_loop_ull_doacross_start (unsigned, unsigned long long *, -+ long, unsigned long long, -+ unsigned long long *, -+ unsigned long long *, -+ uintptr_t *, void **); - - /* ordered.c */ - -@@ -235,6 +286,8 @@ extern void GOMP_doacross_ull_wait (unsi - extern void GOMP_parallel_start (void (*) (void *), void *, unsigned); - extern void GOMP_parallel_end (void); - extern void GOMP_parallel (void (*) (void *), void *, unsigned, unsigned); -+extern unsigned GOMP_parallel_reductions (void (*) (void *), void *, unsigned, -+ unsigned); - extern bool GOMP_cancel (int, bool); - extern bool GOMP_cancellation_point (int); - -@@ -251,13 +304,19 @@ extern void GOMP_taskloop_ull (void (*) - unsigned long long, unsigned long long, - unsigned long long); - extern void GOMP_taskwait (void); -+extern void GOMP_taskwait_depend (void **); - extern void GOMP_taskyield (void); - extern void GOMP_taskgroup_start (void); - extern void GOMP_taskgroup_end (void); -+extern void GOMP_taskgroup_reduction_register (uintptr_t *); -+extern void GOMP_taskgroup_reduction_unregister (uintptr_t *); -+extern void GOMP_task_reduction_remap (size_t, size_t, void **); -+extern void GOMP_workshare_task_reduction_unregister (bool); - - /* sections.c */ - - extern unsigned GOMP_sections_start (unsigned); -+extern unsigned GOMP_sections2_start (unsigned, uintptr_t *, void **); - extern unsigned GOMP_sections_next (void); - extern void GOMP_parallel_sections_start (void (*) (void *), void *, - unsigned, unsigned); -@@ -293,6 +352,11 @@ extern void GOMP_target_enter_exit_data - void **); - extern void GOMP_teams (unsigned int, unsigned int); - -+/* teams.c */ -+ -+extern void GOMP_teams_reg (void (*) (void *), void *, unsigned, unsigned, -+ unsigned); -+ - /* oacc-parallel.c */ - - extern void GOACC_parallel_keyed (int, void (*) (void *), size_t, ---- libgomp/affinity.c.jj 2018-04-25 09:40:31.913655581 +0200 -+++ libgomp/affinity.c 2019-05-07 18:46:36.254114081 +0200 -@@ -26,6 +26,8 @@ - /* This is a generic stub implementation of a CPU affinity setting. */ - - #include "libgomp.h" -+#include -+#include - - void - gomp_init_affinity (void) -@@ -138,5 +140,17 @@ gomp_get_place_proc_ids_8 (int place_num - (void) ids; - } - -+void -+gomp_display_affinity_place (char *buffer, size_t size, size_t *ret, -+ int place) -+{ -+ char buf[sizeof (long) * 3 + 4]; -+ if (gomp_available_cpus > 1) -+ sprintf (buf, "0-%lu", gomp_available_cpus - 1); -+ else -+ strcpy (buf, "0"); -+ gomp_display_string (buffer, size, ret, buf, strlen (buf)); -+} -+ - ialias(omp_get_place_num_procs) - ialias(omp_get_place_proc_ids) ---- libgomp/sections.c.jj 2018-04-25 09:40:31.924655586 +0200 -+++ libgomp/sections.c 2019-05-07 18:46:36.535109592 +0200 -@@ -26,8 +26,11 @@ - /* This file handles the SECTIONS construct. */ - - #include "libgomp.h" -+#include - - -+ialias_redirect (GOMP_taskgroup_reduction_register) -+ - /* Initialize the given work share construct from the given arguments. */ - - static inline void -@@ -72,7 +75,7 @@ GOMP_sections_start (unsigned count) - struct gomp_thread *thr = gomp_thread (); - long s, e, ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_sections_init (thr->ts.work_share, count); - gomp_work_share_init_done (); -@@ -95,6 +98,66 @@ GOMP_sections_start (unsigned count) - return ret; - } - -+unsigned -+GOMP_sections2_start (unsigned count, uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ long s, e, ret; -+ -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (gomp_work_share_start (0)) -+ { -+ gomp_sections_init (thr->ts.work_share, count); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ if (mem) -+ { -+ uintptr_t size = (uintptr_t) *mem; -+ if (size > (sizeof (struct gomp_work_share) -+ - offsetof (struct gomp_work_share, -+ inline_ordered_team_ids))) -+ thr->ts.work_share->ordered_team_ids -+ = gomp_malloc_cleared (size); -+ else -+ memset (thr->ts.work_share->ordered_team_ids, '\0', size); -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ if (mem) -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ -+#ifdef HAVE_SYNC_BUILTINS -+ if (gomp_iter_dynamic_next (&s, &e)) -+ ret = s; -+ else -+ ret = 0; -+#else -+ gomp_mutex_lock (&thr->ts.work_share->lock); -+ if (gomp_iter_dynamic_next_locked (&s, &e)) -+ ret = s; -+ else -+ ret = 0; -+ gomp_mutex_unlock (&thr->ts.work_share->lock); -+#endif -+ -+ return ret; -+} -+ - /* This routine is called when the thread completes processing of the - section currently assigned to it. If the work-share construct is - bound directly to a parallel construct, then the construct may have -@@ -140,7 +203,7 @@ GOMP_parallel_sections_start (void (*fn) - num_threads = gomp_resolve_num_threads (num_threads, count); - team = gomp_new_team (num_threads); - gomp_sections_init (&team->work_shares[0], count); -- gomp_team_start (fn, data, num_threads, 0, team); -+ gomp_team_start (fn, data, num_threads, 0, team, NULL); - } - - ialias_redirect (GOMP_parallel_end) -@@ -154,7 +217,7 @@ GOMP_parallel_sections (void (*fn) (void - num_threads = gomp_resolve_num_threads (num_threads, count); - team = gomp_new_team (num_threads); - gomp_sections_init (&team->work_shares[0], count); -- gomp_team_start (fn, data, num_threads, flags, team); -+ gomp_team_start (fn, data, num_threads, flags, team, NULL); - fn (data); - GOMP_parallel_end (); - } ---- libgomp/config/linux/affinity.c.jj 2018-04-25 09:40:31.875655563 +0200 -+++ libgomp/config/linux/affinity.c 2019-05-07 18:46:36.344112642 +0200 -@@ -396,6 +396,56 @@ gomp_get_place_proc_ids_8 (int place_num - *ids++ = i; - } - -+void -+gomp_display_affinity_place (char *buffer, size_t size, size_t *ret, -+ int place) -+{ -+ cpu_set_t *cpusetp; -+ char buf[sizeof (long) * 3 + 4]; -+ if (place >= 0 && place < gomp_places_list_len) -+ cpusetp = (cpu_set_t *) gomp_places_list[place]; -+ else if (gomp_cpusetp) -+ cpusetp = gomp_cpusetp; -+ else -+ { -+ if (gomp_available_cpus > 1) -+ sprintf (buf, "0-%lu", gomp_available_cpus - 1); -+ else -+ strcpy (buf, "0"); -+ gomp_display_string (buffer, size, ret, buf, strlen (buf)); -+ return; -+ } -+ -+ unsigned long i, max = 8 * gomp_cpuset_size, start; -+ bool prev_set = false; -+ start = max; -+ for (i = 0; i <= max; i++) -+ { -+ bool this_set; -+ if (i == max) -+ this_set = false; -+ else -+ this_set = CPU_ISSET_S (i, gomp_cpuset_size, cpusetp); -+ if (this_set != prev_set) -+ { -+ prev_set = this_set; -+ if (this_set) -+ { -+ char *p = buf; -+ if (start != max) -+ *p++ = ','; -+ sprintf (p, "%lu", i); -+ start = i; -+ } -+ else if (i == start + 1) -+ continue; -+ else -+ sprintf (buf, "-%lu", i - 1); -+ gomp_display_string (buffer, size, ret, buf, strlen (buf)); -+ } -+ } -+} -+ - ialias(omp_get_place_num_procs) - ialias(omp_get_place_proc_ids) - ---- libgomp/config/linux/ia64/futex.h.jj 2018-04-25 09:40:31.877655564 +0200 -+++ libgomp/config/linux/ia64/futex.h 2019-05-07 18:46:36.344112642 +0200 -@@ -45,8 +45,8 @@ sys_futex0(int *addr, int op, int val) - "=r"(r8), "=r"(r10) - : "r"(r15), "r"(out0), "r"(out1), "r"(out2), "r"(out3) - : "memory", "out4", "out5", "out6", "out7", -- /* Non-stacked integer registers, minus r8, r10, r15. */ -- "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", -+ /* Non-stacked integer registers, minus r8, r10, r12, r15. */ -+ "r2", "r3", "r9", "r11", "r13", "r14", "r16", "r17", "r18", - "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", - "r28", "r29", "r30", "r31", - /* Predicate registers. */ ---- libgomp/config/nvptx/teams.c.jj 2019-05-07 18:46:36.459110805 +0200 -+++ libgomp/config/nvptx/teams.c 2019-05-07 18:46:36.459110805 +0200 -@@ -0,0 +1,57 @@ -+/* Copyright (C) 2015-2019 Free Software Foundation, Inc. -+ Contributed by Alexander Monakov -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+/* This file defines OpenMP API entry points that accelerator targets are -+ expected to replace. */ -+ -+#include "libgomp.h" -+ -+void -+GOMP_teams_reg (void (*fn) (void *), void *data, unsigned int num_teams, -+ unsigned int thread_limit, unsigned int flags) -+{ -+ (void) fn; -+ (void) data; -+ (void) flags; -+ (void) num_teams; -+ (void) thread_limit; -+} -+ -+int -+omp_get_num_teams (void) -+{ -+ return gomp_num_teams_var + 1; -+} -+ -+int -+omp_get_team_num (void) -+{ -+ int ctaid; -+ asm ("mov.u32 %0, %%ctaid.x;" : "=r" (ctaid)); -+ return ctaid; -+} -+ -+ialias (omp_get_num_teams) -+ialias (omp_get_team_num) ---- libgomp/config/nvptx/team.c.jj 2018-04-25 09:40:31.890655570 +0200 -+++ libgomp/config/nvptx/team.c 2019-05-07 18:46:36.459110805 +0200 -@@ -116,7 +116,8 @@ gomp_thread_start (struct gomp_thread_po - - void - gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, -- unsigned flags, struct gomp_team *team) -+ unsigned flags, struct gomp_team *team, -+ struct gomp_taskgroup *taskgroup) - { - struct gomp_thread *thr, *nthr; - struct gomp_task *task; -@@ -147,6 +148,7 @@ gomp_team_start (void (*fn) (void *), vo - nthreads_var = icv->nthreads_var; - gomp_init_task (thr->task, task, icv); - team->implicit_task[0].icv.nthreads_var = nthreads_var; -+ team->implicit_task[0].taskgroup = taskgroup; - - if (nthreads == 1) - return; -@@ -166,6 +168,7 @@ gomp_team_start (void (*fn) (void *), vo - nthr->task = &team->implicit_task[i]; - gomp_init_task (nthr->task, task, icv); - team->implicit_task[i].icv.nthreads_var = nthreads_var; -+ team->implicit_task[i].taskgroup = taskgroup; - nthr->fn = fn; - nthr->data = data; - team->ordered_release[i] = &nthr->release; -@@ -174,5 +177,11 @@ gomp_team_start (void (*fn) (void *), vo - gomp_simple_barrier_wait (&pool->threads_dock); - } - -+int -+gomp_pause_host (void) -+{ -+ return -1; -+} -+ - #include "../../team.c" - #endif ---- libgomp/config/nvptx/oacc-parallel.c.jj 2018-04-25 09:40:31.887655569 +0200 -+++ libgomp/config/nvptx/oacc-parallel.c 2019-05-07 18:46:36.453110901 +0200 -@@ -1,358 +0,0 @@ --/* OpenACC constructs -- -- Copyright (C) 2014-2018 Free Software Foundation, Inc. -- -- Contributed by Mentor Embedded. -- -- This file is part of the GNU Offloading and Multi Processing Library -- (libgomp). -- -- Libgomp is free software; you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3, or (at your option) -- any later version. -- -- Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -- FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- Under Section 7 of GPL version 3, you are granted additional -- permissions described in the GCC Runtime Library Exception, version -- 3.1, as published by the Free Software Foundation. -- -- You should have received a copy of the GNU General Public License and -- a copy of the GCC Runtime Library Exception along with this program; -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- . */ -- --#include "libgomp_g.h" -- --__asm__ (".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1);\n" -- ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1);\n" -- ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1);\n" -- ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1);\n" -- "// BEGIN GLOBAL FUNCTION DECL: GOACC_get_num_threads\n" -- ".visible .func (.param .u32 %out_retval) GOACC_get_num_threads;\n" -- "// BEGIN GLOBAL FUNCTION DECL: GOACC_get_thread_num\n" -- ".visible .func (.param .u32 %out_retval) GOACC_get_thread_num;\n" -- "// BEGIN GLOBAL FUNCTION DECL: abort\n" -- ".extern .func abort;\n" -- ".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1)\n" -- "{\n" -- ".reg .u32 %ar1;\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- ".reg .pred %r30;\n" -- ".reg .u32 %r31;\n" -- ".reg .pred %r32;\n" -- ".reg .u32 %r33;\n" -- ".reg .pred %r34;\n" -- ".local .align 8 .b8 %frame[4];\n" -- "ld.param.u32 %ar1,[%in_ar1];\n" -- "mov.u32 %r27,%ar1;\n" -- "st.local.u32 [%frame],%r27;\n" -- "ld.local.u32 %r28,[%frame];\n" -- "mov.u32 %r29,1;\n" -- "setp.eq.u32 %r30,%r28,%r29;\n" -- "@%r30 bra $L4;\n" -- "mov.u32 %r31,2;\n" -- "setp.eq.u32 %r32,%r28,%r31;\n" -- "@%r32 bra $L5;\n" -- "mov.u32 %r33,0;\n" -- "setp.eq.u32 %r34,%r28,%r33;\n" -- "@!%r34 bra $L8;\n" -- "mov.u32 %r23,%tid.x;\n" -- "mov.u32 %r22,%r23;\n" -- "bra $L7;\n" -- "$L4:\n" -- "mov.u32 %r24,%tid.y;\n" -- "mov.u32 %r22,%r24;\n" -- "bra $L7;\n" -- "$L5:\n" -- "mov.u32 %r25,%tid.z;\n" -- "mov.u32 %r22,%r25;\n" -- "bra $L7;\n" -- "$L8:\n" -- "{\n" -- "{\n" -- "call abort;\n" -- "}\n" -- "}\n" -- "$L7:\n" -- "mov.u32 %r26,%r22;\n" -- "mov.u32 %retval,%r26;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n" -- ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1)\n" -- "{\n" -- ".reg .u32 %ar1;\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- ".reg .pred %r30;\n" -- ".reg .u32 %r31;\n" -- ".reg .pred %r32;\n" -- ".reg .u32 %r33;\n" -- ".reg .pred %r34;\n" -- ".local .align 8 .b8 %frame[4];\n" -- "ld.param.u32 %ar1,[%in_ar1];\n" -- "mov.u32 %r27,%ar1;\n" -- "st.local.u32 [%frame],%r27;\n" -- "ld.local.u32 %r28,[%frame];\n" -- "mov.u32 %r29,1;\n" -- "setp.eq.u32 %r30,%r28,%r29;\n" -- "@%r30 bra $L11;\n" -- "mov.u32 %r31,2;\n" -- "setp.eq.u32 %r32,%r28,%r31;\n" -- "@%r32 bra $L12;\n" -- "mov.u32 %r33,0;\n" -- "setp.eq.u32 %r34,%r28,%r33;\n" -- "@!%r34 bra $L15;\n" -- "mov.u32 %r23,%ntid.x;\n" -- "mov.u32 %r22,%r23;\n" -- "bra $L14;\n" -- "$L11:\n" -- "mov.u32 %r24,%ntid.y;\n" -- "mov.u32 %r22,%r24;\n" -- "bra $L14;\n" -- "$L12:\n" -- "mov.u32 %r25,%ntid.z;\n" -- "mov.u32 %r22,%r25;\n" -- "bra $L14;\n" -- "$L15:\n" -- "{\n" -- "{\n" -- "call abort;\n" -- "}\n" -- "}\n" -- "$L14:\n" -- "mov.u32 %r26,%r22;\n" -- "mov.u32 %retval,%r26;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n" -- ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1)\n" -- "{\n" -- ".reg .u32 %ar1;\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- ".reg .pred %r30;\n" -- ".reg .u32 %r31;\n" -- ".reg .pred %r32;\n" -- ".reg .u32 %r33;\n" -- ".reg .pred %r34;\n" -- ".local .align 8 .b8 %frame[4];\n" -- "ld.param.u32 %ar1,[%in_ar1];\n" -- "mov.u32 %r27,%ar1;\n" -- "st.local.u32 [%frame],%r27;\n" -- "ld.local.u32 %r28,[%frame];\n" -- "mov.u32 %r29,1;\n" -- "setp.eq.u32 %r30,%r28,%r29;\n" -- "@%r30 bra $L18;\n" -- "mov.u32 %r31,2;\n" -- "setp.eq.u32 %r32,%r28,%r31;\n" -- "@%r32 bra $L19;\n" -- "mov.u32 %r33,0;\n" -- "setp.eq.u32 %r34,%r28,%r33;\n" -- "@!%r34 bra $L22;\n" -- "mov.u32 %r23,%ctaid.x;\n" -- "mov.u32 %r22,%r23;\n" -- "bra $L21;\n" -- "$L18:\n" -- "mov.u32 %r24,%ctaid.y;\n" -- "mov.u32 %r22,%r24;\n" -- "bra $L21;\n" -- "$L19:\n" -- "mov.u32 %r25,%ctaid.z;\n" -- "mov.u32 %r22,%r25;\n" -- "bra $L21;\n" -- "$L22:\n" -- "{\n" -- "{\n" -- "call abort;\n" -- "}\n" -- "}\n" -- "$L21:\n" -- "mov.u32 %r26,%r22;\n" -- "mov.u32 %retval,%r26;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n" -- ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1)\n" -- "{\n" -- ".reg .u32 %ar1;\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- ".reg .pred %r30;\n" -- ".reg .u32 %r31;\n" -- ".reg .pred %r32;\n" -- ".reg .u32 %r33;\n" -- ".reg .pred %r34;\n" -- ".local .align 8 .b8 %frame[4];\n" -- "ld.param.u32 %ar1,[%in_ar1];\n" -- "mov.u32 %r27,%ar1;\n" -- "st.local.u32 [%frame],%r27;\n" -- "ld.local.u32 %r28,[%frame];\n" -- "mov.u32 %r29,1;\n" -- "setp.eq.u32 %r30,%r28,%r29;\n" -- "@%r30 bra $L25;\n" -- "mov.u32 %r31,2;\n" -- "setp.eq.u32 %r32,%r28,%r31;\n" -- "@%r32 bra $L26;\n" -- "mov.u32 %r33,0;\n" -- "setp.eq.u32 %r34,%r28,%r33;\n" -- "@!%r34 bra $L29;\n" -- "mov.u32 %r23,%nctaid.x;\n" -- "mov.u32 %r22,%r23;\n" -- "bra $L28;\n" -- "$L25:\n" -- "mov.u32 %r24,%nctaid.y;\n" -- "mov.u32 %r22,%r24;\n" -- "bra $L28;\n" -- "$L26:\n" -- "mov.u32 %r25,%nctaid.z;\n" -- "mov.u32 %r22,%r25;\n" -- "bra $L28;\n" -- "$L29:\n" -- "{\n" -- "{\n" -- "call abort;\n" -- "}\n" -- "}\n" -- "$L28:\n" -- "mov.u32 %r26,%r22;\n" -- "mov.u32 %retval,%r26;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n" -- "// BEGIN GLOBAL FUNCTION DEF: GOACC_get_num_threads\n" -- ".visible .func (.param .u32 %out_retval) GOACC_get_num_threads\n" -- "{\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- "mov.u32 %r26,0;\n" -- "{\n" -- ".param .u32 %retval_in;\n" -- "{\n" -- ".param .u32 %out_arg0;\n" -- "st.param.u32 [%out_arg0],%r26;\n" -- "call (%retval_in),GOACC_ntid,(%out_arg0);\n" -- "}\n" -- "ld.param.u32 %r27,[%retval_in];\n" -- "}\n" -- "mov.u32 %r22,%r27;\n" -- "mov.u32 %r28,0;\n" -- "{\n" -- ".param .u32 %retval_in;\n" -- "{\n" -- ".param .u32 %out_arg0;\n" -- "st.param.u32 [%out_arg0],%r28;\n" -- "call (%retval_in),GOACC_nctaid,(%out_arg0);\n" -- "}\n" -- "ld.param.u32 %r29,[%retval_in];\n" -- "}\n" -- "mov.u32 %r23,%r29;\n" -- "mul.lo.u32 %r24,%r22,%r23;\n" -- "mov.u32 %r25,%r24;\n" -- "mov.u32 %retval,%r25;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n" -- "// BEGIN GLOBAL FUNCTION DEF: GOACC_get_thread_num\n" -- ".visible .func (.param .u32 %out_retval) GOACC_get_thread_num\n" -- "{\n" -- ".reg .u32 %retval;\n" -- ".reg .u64 %hr10;\n" -- ".reg .u32 %r22;\n" -- ".reg .u32 %r23;\n" -- ".reg .u32 %r24;\n" -- ".reg .u32 %r25;\n" -- ".reg .u32 %r26;\n" -- ".reg .u32 %r27;\n" -- ".reg .u32 %r28;\n" -- ".reg .u32 %r29;\n" -- ".reg .u32 %r30;\n" -- ".reg .u32 %r31;\n" -- ".reg .u32 %r32;\n" -- ".reg .u32 %r33;\n" -- "mov.u32 %r28,0;\n" -- "{\n" -- ".param .u32 %retval_in;\n" -- "{\n" -- ".param .u32 %out_arg0;\n" -- "st.param.u32 [%out_arg0],%r28;\n" -- "call (%retval_in),GOACC_ntid,(%out_arg0);\n" -- "}\n" -- "ld.param.u32 %r29,[%retval_in];\n" -- "}\n" -- "mov.u32 %r22,%r29;\n" -- "mov.u32 %r30,0;\n" -- "{\n" -- ".param .u32 %retval_in;\n" -- "{\n" -- ".param .u32 %out_arg0;\n" -- "st.param.u32 [%out_arg0],%r30;\n" -- "call (%retval_in),GOACC_ctaid,(%out_arg0);\n" -- "}\n" -- "ld.param.u32 %r31,[%retval_in];\n" -- "}\n" -- "mov.u32 %r23,%r31;\n" -- "mul.lo.u32 %r24,%r22,%r23;\n" -- "mov.u32 %r32,0;\n" -- "{\n" -- ".param .u32 %retval_in;\n" -- "{\n" -- ".param .u32 %out_arg0;\n" -- "st.param.u32 [%out_arg0],%r32;\n" -- "call (%retval_in),GOACC_tid,(%out_arg0);\n" -- "}\n" -- "ld.param.u32 %r33,[%retval_in];\n" -- "}\n" -- "mov.u32 %r25,%r33;\n" -- "add.u32 %r26,%r24,%r25;\n" -- "mov.u32 %r27,%r26;\n" -- "mov.u32 %retval,%r27;\n" -- "st.param.u32 [%out_retval],%retval;\n" -- "ret;\n" -- "}\n"); ---- libgomp/config/nvptx/target.c.jj 2018-04-25 09:40:31.890655570 +0200 -+++ libgomp/config/nvptx/target.c 2019-05-07 18:46:36.453110901 +0200 -@@ -47,3 +47,21 @@ GOMP_teams (unsigned int num_teams, unsi - } - gomp_num_teams_var = num_teams - 1; - } -+ -+int -+omp_pause_resource (omp_pause_resource_t kind, int device_num) -+{ -+ (void) kind; -+ (void) device_num; -+ return -1; -+} -+ -+int -+omp_pause_resource_all (omp_pause_resource_t kind) -+{ -+ (void) kind; -+ return -1; -+} -+ -+ialias (omp_pause_resource) -+ialias (omp_pause_resource_all) ---- libgomp/config/nvptx/icv-device.c.jj 2018-04-25 09:40:31.889655570 +0200 -+++ libgomp/config/nvptx/icv-device.c 2019-05-07 18:46:36.453110901 +0200 -@@ -46,20 +46,6 @@ omp_get_num_devices (void) - } - - int --omp_get_num_teams (void) --{ -- return gomp_num_teams_var + 1; --} -- --int --omp_get_team_num (void) --{ -- int ctaid; -- asm ("mov.u32 %0, %%ctaid.x;" : "=r" (ctaid)); -- return ctaid; --} -- --int - omp_is_initial_device (void) - { - /* NVPTX is an accelerator-only target. */ -@@ -69,6 +55,4 @@ omp_is_initial_device (void) - ialias (omp_set_default_device) - ialias (omp_get_default_device) - ialias (omp_get_num_devices) --ialias (omp_get_num_teams) --ialias (omp_get_team_num) - ialias (omp_is_initial_device) ---- libgomp/config/nvptx/affinity-fmt.c.jj 2019-05-07 18:46:36.358112419 +0200 -+++ libgomp/config/nvptx/affinity-fmt.c 2019-05-07 18:46:36.358112419 +0200 -@@ -0,0 +1,51 @@ -+/* Copyright (C) 2018-2019 Free Software Foundation, Inc. -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+#include "libgomp.h" -+#include -+#include -+#include -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#ifdef HAVE_INTTYPES_H -+# include /* For PRIx64. */ -+#endif -+#ifdef HAVE_UNAME -+#include -+#endif -+ -+/* The HAVE_GETPID and HAVE_GETHOSTNAME configure tests are passing for nvptx, -+ while the nvptx newlib implementation does not support those functions. -+ Override the configure test results here. */ -+#undef HAVE_GETPID -+#undef HAVE_GETHOSTNAME -+ -+/* The nvptx newlib implementation does not support fwrite, but it does support -+ write. Map fwrite to write. */ -+#undef fwrite -+#define fwrite(ptr, size, nmemb, stream) write (1, (ptr), (nmemb) * (size)) -+ -+#include "../../affinity-fmt.c" -+ ---- libgomp/config/mingw32/affinity-fmt.c.jj 2019-05-07 18:46:36.344112642 +0200 -+++ libgomp/config/mingw32/affinity-fmt.c 2019-05-07 18:46:36.344112642 +0200 -@@ -0,0 +1,68 @@ -+/* Copyright (C) 2018-2019 Free Software Foundation, Inc. -+ Contributed by Jakub Jelinek . -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+#include "libgomp.h" -+#include -+#include -+#include -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#ifdef HAVE_INTTYPES_H -+# include /* For PRIx64. */ -+#endif -+#define WIN32_LEAN_AND_MEAN -+#include -+#include -+ -+static int -+gomp_gethostname (char *name, size_t len) -+{ -+ /* On Win9x GetComputerName fails if the input size is less -+ than MAX_COMPUTERNAME_LENGTH + 1. */ -+ char buffer[MAX_COMPUTERNAME_LENGTH + 1]; -+ DWORD size = sizeof (buffer); -+ int ret = 0; -+ -+ if (!GetComputerName (buffer, &size)) -+ return -1; -+ -+ if ((size = strlen (buffer) + 1) > len) -+ { -+ errno = EINVAL; -+ /* Truncate as per POSIX spec. We do not NUL-terminate. */ -+ size = len; -+ ret = -1; -+ } -+ memcpy (name, buffer, (size_t) size); -+ -+ return ret; -+} -+ -+#undef gethostname -+#define gethostname gomp_gethostname -+#define HAVE_GETHOSTNAME 1 -+ -+#include "../../affinity-fmt.c" ---- libgomp/config/rtems/bar.c.jj 2018-04-25 09:40:31.902655576 +0200 -+++ libgomp/config/rtems/bar.c 2019-05-07 18:46:36.460110789 +0200 -@@ -72,184 +72,5 @@ do_wait (int *addr, int val) - futex_wait (addr, val); - } - --/* Everything below this point should be identical to the Linux -- implementation. */ -- --void --gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state) --{ -- if (__builtin_expect (state & BAR_WAS_LAST, 0)) -- { -- /* Next time we'll be awaiting TOTAL threads again. */ -- bar->awaited = bar->total; -- __atomic_store_n (&bar->generation, bar->generation + BAR_INCR, -- MEMMODEL_RELEASE); -- futex_wake ((int *) &bar->generation, INT_MAX); -- } -- else -- { -- do -- do_wait ((int *) &bar->generation, state); -- while (__atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) == state); -- } --} -- --void --gomp_barrier_wait (gomp_barrier_t *bar) --{ -- gomp_barrier_wait_end (bar, gomp_barrier_wait_start (bar)); --} -- --/* Like gomp_barrier_wait, except that if the encountering thread -- is not the last one to hit the barrier, it returns immediately. -- The intended usage is that a thread which intends to gomp_barrier_destroy -- this barrier calls gomp_barrier_wait, while all other threads -- call gomp_barrier_wait_last. When gomp_barrier_wait returns, -- the barrier can be safely destroyed. */ -- --void --gomp_barrier_wait_last (gomp_barrier_t *bar) --{ -- gomp_barrier_state_t state = gomp_barrier_wait_start (bar); -- if (state & BAR_WAS_LAST) -- gomp_barrier_wait_end (bar, state); --} -- --void --gomp_team_barrier_wake (gomp_barrier_t *bar, int count) --{ -- futex_wake ((int *) &bar->generation, count == 0 ? INT_MAX : count); --} -- --void --gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state) --{ -- unsigned int generation, gen; -- -- if (__builtin_expect (state & BAR_WAS_LAST, 0)) -- { -- /* Next time we'll be awaiting TOTAL threads again. */ -- struct gomp_thread *thr = gomp_thread (); -- struct gomp_team *team = thr->ts.team; -- -- bar->awaited = bar->total; -- team->work_share_cancelled = 0; -- if (__builtin_expect (team->task_count, 0)) -- { -- gomp_barrier_handle_tasks (state); -- state &= ~BAR_WAS_LAST; -- } -- else -- { -- state &= ~BAR_CANCELLED; -- state += BAR_INCR - BAR_WAS_LAST; -- __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE); -- futex_wake ((int *) &bar->generation, INT_MAX); -- return; -- } -- } -- -- generation = state; -- state &= ~BAR_CANCELLED; -- do -- { -- do_wait ((int *) &bar->generation, generation); -- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE); -- if (__builtin_expect (gen & BAR_TASK_PENDING, 0)) -- { -- gomp_barrier_handle_tasks (state); -- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE); -- } -- generation |= gen & BAR_WAITING_FOR_TASK; -- } -- while (gen != state + BAR_INCR); --} -- --void --gomp_team_barrier_wait (gomp_barrier_t *bar) --{ -- gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar)); --} -- --void --gomp_team_barrier_wait_final (gomp_barrier_t *bar) --{ -- gomp_barrier_state_t state = gomp_barrier_wait_final_start (bar); -- if (__builtin_expect (state & BAR_WAS_LAST, 0)) -- bar->awaited_final = bar->total; -- gomp_team_barrier_wait_end (bar, state); --} -- --bool --gomp_team_barrier_wait_cancel_end (gomp_barrier_t *bar, -- gomp_barrier_state_t state) --{ -- unsigned int generation, gen; -- -- if (__builtin_expect (state & BAR_WAS_LAST, 0)) -- { -- /* Next time we'll be awaiting TOTAL threads again. */ -- /* BAR_CANCELLED should never be set in state here, because -- cancellation means that at least one of the threads has been -- cancelled, thus on a cancellable barrier we should never see -- all threads to arrive. */ -- struct gomp_thread *thr = gomp_thread (); -- struct gomp_team *team = thr->ts.team; -- -- bar->awaited = bar->total; -- team->work_share_cancelled = 0; -- if (__builtin_expect (team->task_count, 0)) -- { -- gomp_barrier_handle_tasks (state); -- state &= ~BAR_WAS_LAST; -- } -- else -- { -- state += BAR_INCR - BAR_WAS_LAST; -- __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE); -- futex_wake ((int *) &bar->generation, INT_MAX); -- return false; -- } -- } -- -- if (__builtin_expect (state & BAR_CANCELLED, 0)) -- return true; -- -- generation = state; -- do -- { -- do_wait ((int *) &bar->generation, generation); -- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE); -- if (__builtin_expect (gen & BAR_CANCELLED, 0)) -- return true; -- if (__builtin_expect (gen & BAR_TASK_PENDING, 0)) -- { -- gomp_barrier_handle_tasks (state); -- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE); -- } -- generation |= gen & BAR_WAITING_FOR_TASK; -- } -- while (gen != state + BAR_INCR); -- -- return false; --} -- --bool --gomp_team_barrier_wait_cancel (gomp_barrier_t *bar) --{ -- return gomp_team_barrier_wait_cancel_end (bar, gomp_barrier_wait_start (bar)); --} -- --void --gomp_team_barrier_cancel (struct gomp_team *team) --{ -- gomp_mutex_lock (&team->task_lock); -- if (team->barrier.generation & BAR_CANCELLED) -- { -- gomp_mutex_unlock (&team->task_lock); -- return; -- } -- team->barrier.generation |= BAR_CANCELLED; -- gomp_mutex_unlock (&team->task_lock); -- futex_wake ((int *) &team->barrier.generation, INT_MAX); --} -+#define GOMP_WAIT_H 1 -+#include "../linux/bar.c" ---- libgomp/config/rtems/affinity-fmt.c.jj 2019-05-07 18:46:36.459110805 +0200 -+++ libgomp/config/rtems/affinity-fmt.c 2019-05-07 18:46:36.459110805 +0200 -@@ -0,0 +1,49 @@ -+/* Copyright (C) 2018-2019 Free Software Foundation, Inc. -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+#include "libgomp.h" -+#include -+#include -+#include -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#ifdef HAVE_INTTYPES_H -+# include /* For PRIx64. */ -+#endif -+#ifdef HAVE_UNAME -+#include -+#endif -+ -+/* The HAVE_GETPID and HAVE_GETHOSTNAME configure tests are passing for RTEMS, -+ but the extra information they give are of little value for the user. -+ Override the configure test results here. */ -+#undef HAVE_GETPID -+#undef HAVE_GETHOSTNAME -+ -+/* Avoid the complex fwrite() in favour of the simple write(). */ -+#undef fwrite -+#define fwrite(ptr, size, nmemb, stream) write (1, (ptr), (nmemb) * (size)) -+ -+#include "../../affinity-fmt.c" ---- libgomp/config.h.in.jj 2018-04-25 09:40:31.870655561 +0200 -+++ libgomp/config.h.in 2019-05-07 18:46:36.465110710 +0200 -@@ -1,5 +1,8 @@ - /* config.h.in. Generated from configure.ac by autoheader. */ - -+/* Define to 1 if you have the `aligned_alloc' function. */ -+#undef HAVE_ALIGNED_ALLOC -+ - /* Define to 1 if the target assembler supports .symver directive. */ - #undef HAVE_AS_SYMVER_DIRECTIVE - -@@ -33,9 +36,15 @@ - /* Define to 1 if you have the `getgid' function. */ - #undef HAVE_GETGID - -+/* Define if gethostname is supported. */ -+#undef HAVE_GETHOSTNAME -+ - /* Define to 1 if you have the `getloadavg' function. */ - #undef HAVE_GETLOADAVG - -+/* Define if getpid is supported. */ -+#undef HAVE_GETPID -+ - /* Define to 1 if you have the `getuid' function. */ - #undef HAVE_GETUID - -@@ -45,9 +54,15 @@ - /* Define to 1 if you have the `dl' library (-ldl). */ - #undef HAVE_LIBDL - -+/* Define to 1 if you have the `memalign' function. */ -+#undef HAVE_MEMALIGN -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_MEMORY_H - -+/* Define to 1 if you have the `posix_memalign' function. */ -+#undef HAVE_POSIX_MEMALIGN -+ - /* Define if pthread_{,attr_}{g,s}etaffinity_np is supported. */ - #undef HAVE_PTHREAD_AFFINITY_NP - -@@ -103,9 +118,15 @@ - /* Define to 1 if the target supports thread-local storage. */ - #undef HAVE_TLS - -+/* Define if uname is supported and struct utsname has nodename field. */ -+#undef HAVE_UNAME -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_UNISTD_H - -+/* Define to 1 if you have the `_aligned_malloc' function. */ -+#undef HAVE__ALIGNED_MALLOC -+ - /* Define to 1 if you have the `__secure_getenv' function. */ - #undef HAVE___SECURE_GETENV - -@@ -125,8 +146,8 @@ - */ - #undef LT_OBJDIR - --/* Define to offload targets, separated by commas. */ --#undef OFFLOAD_TARGETS -+/* Define to offload plugins, separated by commas. */ -+#undef OFFLOAD_PLUGINS - - /* Name of package */ - #undef PACKAGE ---- libgomp/teams.c.jj 2019-05-07 18:46:36.548109384 +0200 -+++ libgomp/teams.c 2019-05-07 18:46:36.548109384 +0200 -@@ -0,0 +1,74 @@ -+/* Copyright (C) 2018-2019 Free Software Foundation, Inc. -+ Contributed by Jakub Jelinek . -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+/* This file handles the host TEAMS construct. */ -+ -+#include "libgomp.h" -+#include -+ -+static unsigned gomp_num_teams = 1, gomp_team_num = 0; -+ -+void -+GOMP_teams_reg (void (*fn) (void *), void *data, unsigned int num_teams, -+ unsigned int thread_limit, unsigned int flags) -+{ -+ (void) flags; -+ (void) num_teams; -+ unsigned old_thread_limit_var = 0; -+ if (thread_limit) -+ { -+ struct gomp_task_icv *icv = gomp_icv (true); -+ old_thread_limit_var = icv->thread_limit_var; -+ icv->thread_limit_var -+ = thread_limit > INT_MAX ? UINT_MAX : thread_limit; -+ } -+ if (num_teams == 0) -+ num_teams = 3; -+ gomp_num_teams = num_teams; -+ for (gomp_team_num = 0; gomp_team_num < num_teams; gomp_team_num++) -+ fn (data); -+ gomp_num_teams = 1; -+ gomp_team_num = 0; -+ if (thread_limit) -+ { -+ struct gomp_task_icv *icv = gomp_icv (true); -+ icv->thread_limit_var = old_thread_limit_var; -+ } -+} -+ -+int -+omp_get_num_teams (void) -+{ -+ return gomp_num_teams; -+} -+ -+int -+omp_get_team_num (void) -+{ -+ return gomp_team_num; -+} -+ -+ialias (omp_get_num_teams) -+ialias (omp_get_team_num) ---- libgomp/libgomp.map.jj 2018-04-25 09:40:31.321655307 +0200 -+++ libgomp/libgomp.map 2019-05-07 18:46:36.525109751 +0200 -@@ -164,6 +164,22 @@ OMP_4.5 { - omp_target_disassociate_ptr; - } OMP_4.0; - -+OMP_5.0 { -+ global: -+ omp_capture_affinity; -+ omp_capture_affinity_; -+ omp_display_affinity; -+ omp_display_affinity_; -+ omp_get_affinity_format; -+ omp_get_affinity_format_; -+ omp_set_affinity_format; -+ omp_set_affinity_format_; -+ omp_pause_resource; -+ omp_pause_resource_; -+ omp_pause_resource_all; -+ omp_pause_resource_all_; -+} OMP_4.5; -+ - GOMP_1.0 { - global: - GOMP_atomic_end; -@@ -298,6 +314,34 @@ GOMP_4.5 { - GOMP_parallel_loop_nonmonotonic_guided; - } GOMP_4.0.1; - -+GOMP_5.0 { -+ global: -+ GOMP_loop_doacross_start; -+ GOMP_loop_maybe_nonmonotonic_runtime_next; -+ GOMP_loop_maybe_nonmonotonic_runtime_start; -+ GOMP_loop_nonmonotonic_runtime_next; -+ GOMP_loop_nonmonotonic_runtime_start; -+ GOMP_loop_ordered_start; -+ GOMP_loop_start; -+ GOMP_loop_ull_doacross_start; -+ GOMP_loop_ull_maybe_nonmonotonic_runtime_next; -+ GOMP_loop_ull_maybe_nonmonotonic_runtime_start; -+ GOMP_loop_ull_nonmonotonic_runtime_next; -+ GOMP_loop_ull_nonmonotonic_runtime_start; -+ GOMP_loop_ull_ordered_start; -+ GOMP_loop_ull_start; -+ GOMP_parallel_loop_maybe_nonmonotonic_runtime; -+ GOMP_parallel_loop_nonmonotonic_runtime; -+ GOMP_parallel_reductions; -+ GOMP_sections2_start; -+ GOMP_taskgroup_reduction_register; -+ GOMP_taskgroup_reduction_unregister; -+ GOMP_task_reduction_remap; -+ GOMP_taskwait_depend; -+ GOMP_teams_reg; -+ GOMP_workshare_task_reduction_unregister; -+} GOMP_4.5; -+ - OACC_2.0 { - global: - acc_get_num_devices; -@@ -386,6 +430,52 @@ OACC_2.0.1 { - acc_pcreate; - } OACC_2.0; - -+OACC_2.5 { -+ global: -+ acc_copyin_async; -+ acc_copyin_async_32_h_; -+ acc_copyin_async_64_h_; -+ acc_copyin_async_array_h_; -+ acc_copyout_async; -+ acc_copyout_async_32_h_; -+ acc_copyout_async_64_h_; -+ acc_copyout_async_array_h_; -+ acc_copyout_finalize; -+ acc_copyout_finalize_32_h_; -+ acc_copyout_finalize_64_h_; -+ acc_copyout_finalize_array_h_; -+ acc_copyout_finalize_async; -+ acc_copyout_finalize_async_32_h_; -+ acc_copyout_finalize_async_64_h_; -+ acc_copyout_finalize_async_array_h_; -+ acc_create_async; -+ acc_create_async_32_h_; -+ acc_create_async_64_h_; -+ acc_create_async_array_h_; -+ acc_delete_async; -+ acc_delete_async_32_h_; -+ acc_delete_async_64_h_; -+ acc_delete_async_array_h_; -+ acc_delete_finalize; -+ acc_delete_finalize_32_h_; -+ acc_delete_finalize_64_h_; -+ acc_delete_finalize_array_h_; -+ acc_delete_finalize_async; -+ acc_delete_finalize_async_32_h_; -+ acc_delete_finalize_async_64_h_; -+ acc_delete_finalize_async_array_h_; -+ acc_memcpy_from_device_async; -+ acc_memcpy_to_device_async; -+ acc_update_device_async; -+ acc_update_device_async_32_h_; -+ acc_update_device_async_64_h_; -+ acc_update_device_async_array_h_; -+ acc_update_self_async; -+ acc_update_self_async_32_h_; -+ acc_update_self_async_64_h_; -+ acc_update_self_async_array_h_; -+} OACC_2.0.1; -+ - GOACC_2.0 { - global: - GOACC_data_end; -@@ -420,3 +510,8 @@ GOMP_PLUGIN_1.1 { - global: - GOMP_PLUGIN_target_task_completion; - } GOMP_PLUGIN_1.0; -+ -+GOMP_PLUGIN_1.2 { -+ global: -+ GOMP_PLUGIN_acc_default_dim; -+} GOMP_PLUGIN_1.1; ---- libgomp/oacc-async.c.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/oacc-async.c 2019-05-07 18:46:36.528109704 +0200 -@@ -34,7 +34,7 @@ - int - acc_async_test (int async) - { -- if (async < acc_async_sync) -+ if (!async_valid_p (async)) - gomp_fatal ("invalid async argument: %d", async); - - struct goacc_thread *thr = goacc_thread (); -@@ -59,7 +59,7 @@ acc_async_test_all (void) - void - acc_wait (int async) - { -- if (async < acc_async_sync) -+ if (!async_valid_p (async)) - gomp_fatal ("invalid async argument: %d", async); - - struct goacc_thread *thr = goacc_thread (); -@@ -117,7 +117,7 @@ acc_async_wait_all (void) - void - acc_wait_all_async (int async) - { -- if (async < acc_async_sync) -+ if (!async_valid_p (async)) - gomp_fatal ("invalid async argument: %d", async); - - struct goacc_thread *thr = goacc_thread (); ---- libgomp/loop_ull.c.jj 2018-04-25 09:40:31.912655580 +0200 -+++ libgomp/loop_ull.c 2019-05-07 18:46:36.527109719 +0200 -@@ -27,8 +27,12 @@ - - #include - #include -+#include - #include "libgomp.h" - -+ialias (GOMP_loop_ull_runtime_next) -+ialias_redirect (GOMP_taskgroup_reduction_register) -+ - typedef unsigned long long gomp_ull; - - /* Initialize the given work share construct from the given arguments. */ -@@ -104,7 +108,7 @@ gomp_loop_ull_static_start (bool up, gom - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_STATIC, chunk_size); -@@ -122,7 +126,7 @@ gomp_loop_ull_dynamic_start (bool up, go - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_DYNAMIC, chunk_size); -@@ -148,7 +152,7 @@ gomp_loop_ull_guided_start (bool up, gom - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_GUIDED, chunk_size); -@@ -171,7 +175,7 @@ GOMP_loop_ull_runtime_start (bool up, go - gomp_ull incr, gomp_ull *istart, gomp_ull *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_ull_static_start (up, start, end, incr, -@@ -195,6 +199,99 @@ GOMP_loop_ull_runtime_start (bool up, go - } - } - -+static long -+gomp_adjust_sched (long sched, gomp_ull *chunk_size) -+{ -+ sched &= ~GFS_MONOTONIC; -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_DYNAMIC: -+ case GFS_GUIDED: -+ return sched; -+ /* GFS_RUNTIME is used for runtime schedule without monotonic -+ or nonmonotonic modifiers on the clause. -+ GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic -+ modifier. */ -+ case GFS_RUNTIME: -+ /* GFS_AUTO is used for runtime schedule with nonmonotonic -+ modifier. */ -+ case GFS_AUTO: -+ { -+ struct gomp_task_icv *icv = gomp_icv (false); -+ sched = icv->run_sched_var & ~GFS_MONOTONIC; -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_DYNAMIC: -+ case GFS_GUIDED: -+ *chunk_size = icv->run_sched_chunk_size; -+ break; -+ case GFS_AUTO: -+ sched = GFS_STATIC; -+ *chunk_size = 0; -+ break; -+ default: -+ abort (); -+ } -+ return sched; -+ } -+ default: -+ abort (); -+ } -+} -+ -+bool -+GOMP_loop_ull_start (bool up, gomp_ull start, gomp_ull end, -+ gomp_ull incr, long sched, gomp_ull chunk_size, -+ gomp_ull *istart, gomp_ull *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (gomp_work_share_start (0)) -+ { -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, -+ sched, chunk_size); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ if (mem) -+ { -+ uintptr_t size = (uintptr_t) *mem; -+ if (size > (sizeof (struct gomp_work_share) -+ - offsetof (struct gomp_work_share, -+ inline_ordered_team_ids))) -+ thr->ts.work_share->ordered_team_ids -+ = gomp_malloc_cleared (size); -+ else -+ memset (thr->ts.work_share->ordered_team_ids, '\0', size); -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ if (mem) -+ *mem = (void *) thr->ts.work_share->ordered_team_ids; -+ } -+ -+ return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend); -+} -+ - /* The *_ordered_*_start routines are similar. The only difference is that - this work-share construct is initialized to expect an ORDERED section. */ - -@@ -206,7 +303,7 @@ gomp_loop_ull_ordered_static_start (bool - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_STATIC, chunk_size); -@@ -225,7 +322,7 @@ gomp_loop_ull_ordered_dynamic_start (boo - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_DYNAMIC, chunk_size); -@@ -251,7 +348,7 @@ gomp_loop_ull_ordered_guided_start (bool - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (true)) -+ if (gomp_work_share_start (1)) - { - gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, - GFS_GUIDED, chunk_size); -@@ -275,7 +372,7 @@ GOMP_loop_ull_ordered_runtime_start (boo - gomp_ull *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_ull_ordered_static_start (up, start, end, incr, -@@ -299,6 +396,82 @@ GOMP_loop_ull_ordered_runtime_start (boo - } - } - -+bool -+GOMP_loop_ull_ordered_start (bool up, gomp_ull start, gomp_ull end, -+ gomp_ull incr, long sched, gomp_ull chunk_size, -+ gomp_ull *istart, gomp_ull *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ size_t ordered = 1; -+ bool ret; -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (mem) -+ ordered += (uintptr_t) *mem; -+ if (gomp_work_share_start (ordered)) -+ { -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, -+ sched, chunk_size); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ if (sched == GFS_STATIC) -+ gomp_ordered_static_init (); -+ else -+ gomp_mutex_lock (&thr->ts.work_share->lock); -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ sched = thr->ts.work_share->sched; -+ if (sched != GFS_STATIC) -+ gomp_mutex_lock (&thr->ts.work_share->lock); -+ } -+ -+ if (mem) -+ { -+ uintptr_t p -+ = (uintptr_t) (thr->ts.work_share->ordered_team_ids -+ + (thr->ts.team ? thr->ts.team->nthreads : 1)); -+ p += __alignof__ (long long) - 1; -+ p &= ~(__alignof__ (long long) - 1); -+ *mem = (void *) p; -+ } -+ -+ switch (sched) -+ { -+ case GFS_STATIC: -+ case GFS_AUTO: -+ return !gomp_iter_ull_static_next (istart, iend); -+ case GFS_DYNAMIC: -+ ret = gomp_iter_ull_dynamic_next_locked (istart, iend); -+ break; -+ case GFS_GUIDED: -+ ret = gomp_iter_ull_guided_next_locked (istart, iend); -+ break; -+ default: -+ abort (); -+ } -+ -+ if (ret) -+ gomp_ordered_first (); -+ gomp_mutex_unlock (&thr->ts.work_share->lock); -+ return ret; -+} -+ - /* The *_doacross_*_start routines are similar. The only difference is that - this work-share construct is initialized to expect an ORDERED(N) - DOACROSS - section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1 -@@ -313,11 +486,11 @@ gomp_loop_ull_doacross_static_start (uns - struct gomp_thread *thr = gomp_thread (); - - thr->ts.static_trip = 0; -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, - GFS_STATIC, chunk_size); -- gomp_doacross_ull_init (ncounts, counts, chunk_size); -+ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -332,11 +505,11 @@ gomp_loop_ull_doacross_dynamic_start (un - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, - GFS_DYNAMIC, chunk_size); -- gomp_doacross_ull_init (ncounts, counts, chunk_size); -+ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -359,11 +532,11 @@ gomp_loop_ull_doacross_guided_start (uns - struct gomp_thread *thr = gomp_thread (); - bool ret; - -- if (gomp_work_share_start (false)) -+ if (gomp_work_share_start (0)) - { - gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, - GFS_GUIDED, chunk_size); -- gomp_doacross_ull_init (ncounts, counts, chunk_size); -+ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0); - gomp_work_share_init_done (); - } - -@@ -383,7 +556,7 @@ GOMP_loop_ull_doacross_runtime_start (un - gomp_ull *istart, gomp_ull *iend) - { - struct gomp_task_icv *icv = gomp_icv (false); -- switch (icv->run_sched_var) -+ switch (icv->run_sched_var & ~GFS_MONOTONIC) - { - case GFS_STATIC: - return gomp_loop_ull_doacross_static_start (ncounts, counts, -@@ -407,6 +580,51 @@ GOMP_loop_ull_doacross_runtime_start (un - } - } - -+bool -+GOMP_loop_ull_doacross_start (unsigned ncounts, gomp_ull *counts, -+ long sched, gomp_ull chunk_size, -+ gomp_ull *istart, gomp_ull *iend, -+ uintptr_t *reductions, void **mem) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ -+ thr->ts.static_trip = 0; -+ if (reductions) -+ gomp_workshare_taskgroup_start (); -+ if (gomp_work_share_start (0)) -+ { -+ size_t extra = 0; -+ if (mem) -+ extra = (uintptr_t) *mem; -+ sched = gomp_adjust_sched (sched, &chunk_size); -+ gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, -+ sched, chunk_size); -+ gomp_doacross_ull_init (ncounts, counts, chunk_size, extra); -+ if (reductions) -+ { -+ GOMP_taskgroup_reduction_register (reductions); -+ thr->task->taskgroup->workshare = true; -+ thr->ts.work_share->task_reductions = reductions; -+ } -+ gomp_work_share_init_done (); -+ } -+ else -+ { -+ if (reductions) -+ { -+ uintptr_t *first_reductions = thr->ts.work_share->task_reductions; -+ gomp_workshare_task_reduction_register (reductions, -+ first_reductions); -+ } -+ sched = thr->ts.work_share->sched; -+ } -+ -+ if (mem) -+ *mem = thr->ts.work_share->doacross->extra; -+ -+ return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend); -+} -+ - /* The *_next routines are called when the thread completes processing of - the iteration block currently assigned to it. If the work-share - construct is bound directly to a parallel construct, then the iteration -@@ -570,6 +788,10 @@ extern __typeof(gomp_loop_ull_dynamic_st - __attribute__((alias ("gomp_loop_ull_dynamic_start"))); - extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_nonmonotonic_guided_start - __attribute__((alias ("gomp_loop_ull_guided_start"))); -+extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_nonmonotonic_runtime_start -+ __attribute__((alias ("GOMP_loop_ull_runtime_start"))); -+extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_maybe_nonmonotonic_runtime_start -+ __attribute__((alias ("GOMP_loop_ull_runtime_start"))); - - extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start - __attribute__((alias ("gomp_loop_ull_ordered_static_start"))); -@@ -595,6 +817,10 @@ extern __typeof(gomp_loop_ull_dynamic_ne - __attribute__((alias ("gomp_loop_ull_dynamic_next"))); - extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_nonmonotonic_guided_next - __attribute__((alias ("gomp_loop_ull_guided_next"))); -+extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_nonmonotonic_runtime_next -+ __attribute__((alias ("GOMP_loop_ull_runtime_next"))); -+extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_maybe_nonmonotonic_runtime_next -+ __attribute__((alias ("GOMP_loop_ull_runtime_next"))); - - extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next - __attribute__((alias ("gomp_loop_ull_ordered_static_next"))); -@@ -650,6 +876,23 @@ GOMP_loop_ull_nonmonotonic_guided_start - } - - bool -+GOMP_loop_ull_nonmonotonic_runtime_start (bool up, gomp_ull start, -+ gomp_ull end, gomp_ull incr, -+ gomp_ull *istart, gomp_ull *iend) -+{ -+ return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend); -+} -+ -+bool -+GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool up, gomp_ull start, -+ gomp_ull end, gomp_ull incr, -+ gomp_ull *istart, -+ gomp_ull *iend) -+{ -+ return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend); -+} -+ -+bool - GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end, - gomp_ull incr, gomp_ull chunk_size, - gomp_ull *istart, gomp_ull *iend) -@@ -734,6 +977,19 @@ GOMP_loop_ull_nonmonotonic_guided_next ( - } - - bool -+GOMP_loop_ull_nonmonotonic_runtime_next (gomp_ull *istart, gomp_ull *iend) -+{ -+ return GOMP_loop_ull_runtime_next (istart, iend); -+} -+ -+bool -+GOMP_loop_ull_maybe_nonmonotonic_runtime_next (gomp_ull *istart, -+ gomp_ull *iend) -+{ -+ return GOMP_loop_ull_runtime_next (istart, iend); -+} -+ -+bool - GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend) - { - return gomp_loop_ull_ordered_static_next (istart, iend); ---- libgomp/oacc-int.h.jj 2018-04-25 09:40:31.320655306 +0200 -+++ libgomp/oacc-int.h 2019-05-07 18:46:36.529109688 +0200 -@@ -99,6 +99,28 @@ void goacc_restore_bind (void); - void goacc_lazy_initialize (void); - void goacc_host_init (void); - -+static inline bool -+async_valid_stream_id_p (int async) -+{ -+ return async >= 0; -+} -+ -+static inline bool -+async_valid_p (int async) -+{ -+ return (async == acc_async_noval || async == acc_async_sync -+ || async_valid_stream_id_p (async)); -+} -+ -+static inline bool -+async_synchronous_p (int async) -+{ -+ if (!async_valid_p (async)) -+ return true; -+ -+ return async == acc_async_sync; -+} -+ - #ifdef HAVE_ATTRIBUTE_VISIBILITY - # pragma GCC visibility pop - #endif ---- libgomp/testsuite/Makefile.in.jj 2018-04-25 09:40:31.452655368 +0200 -+++ libgomp/testsuite/Makefile.in 2019-05-07 18:51:35.754330084 +0200 -@@ -223,6 +223,7 @@ mkdir_p = @mkdir_p@ - multi_basedir = @multi_basedir@ - offload_additional_lib_paths = @offload_additional_lib_paths@ - offload_additional_options = @offload_additional_options@ -+offload_plugins = @offload_plugins@ - offload_targets = @offload_targets@ - oldincludedir = @oldincludedir@ - pdfdir = @pdfdir@ ---- libgomp/task.c.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/task.c 2019-05-07 18:46:36.547109400 +0200 -@@ -166,21 +166,72 @@ gomp_task_handle_depend (struct gomp_tas - void **depend) - { - size_t ndepend = (uintptr_t) depend[0]; -- size_t nout = (uintptr_t) depend[1]; - size_t i; - hash_entry_type ent; - -+ if (ndepend) -+ { -+ /* depend[0] is total # */ -+ size_t nout = (uintptr_t) depend[1]; /* # of out: and inout: */ -+ /* ndepend - nout is # of in: */ -+ for (i = 0; i < ndepend; i++) -+ { -+ task->depend[i].addr = depend[2 + i]; -+ task->depend[i].is_in = i >= nout; -+ } -+ } -+ else -+ { -+ ndepend = (uintptr_t) depend[1]; /* total # */ -+ size_t nout = (uintptr_t) depend[2]; /* # of out: and inout: */ -+ size_t nmutexinoutset = (uintptr_t) depend[3]; /* # of mutexinoutset: */ -+ /* For now we treat mutexinoutset like out, which is compliant, but -+ inefficient. */ -+ size_t nin = (uintptr_t) depend[4]; /* # of in: */ -+ /* ndepend - nout - nmutexinoutset - nin is # of depobjs */ -+ size_t normal = nout + nmutexinoutset + nin; -+ size_t n = 0; -+ for (i = normal; i < ndepend; i++) -+ { -+ void **d = (void **) (uintptr_t) depend[5 + i]; -+ switch ((uintptr_t) d[1]) -+ { -+ case GOMP_DEPEND_OUT: -+ case GOMP_DEPEND_INOUT: -+ case GOMP_DEPEND_MUTEXINOUTSET: -+ break; -+ case GOMP_DEPEND_IN: -+ continue; -+ default: -+ gomp_fatal ("unknown omp_depend_t dependence type %d", -+ (int) (uintptr_t) d[1]); -+ } -+ task->depend[n].addr = d[0]; -+ task->depend[n++].is_in = 0; -+ } -+ for (i = 0; i < normal; i++) -+ { -+ task->depend[n].addr = depend[5 + i]; -+ task->depend[n++].is_in = i >= nout + nmutexinoutset; -+ } -+ for (i = normal; i < ndepend; i++) -+ { -+ void **d = (void **) (uintptr_t) depend[5 + i]; -+ if ((uintptr_t) d[1] != GOMP_DEPEND_IN) -+ continue; -+ task->depend[n].addr = d[0]; -+ task->depend[n++].is_in = 1; -+ } -+ } - task->depend_count = ndepend; - task->num_dependees = 0; - if (parent->depend_hash == NULL) - parent->depend_hash = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12); - for (i = 0; i < ndepend; i++) - { -- task->depend[i].addr = depend[2 + i]; - task->depend[i].next = NULL; - task->depend[i].prev = NULL; - task->depend[i].task = task; -- task->depend[i].is_in = i >= nout; - task->depend[i].redundant = false; - task->depend[i].redundant_out = false; - -@@ -205,7 +256,7 @@ gomp_task_handle_depend (struct gomp_tas - last = ent; - - /* depend(in:...) doesn't depend on earlier depend(in:...). */ -- if (i >= nout && ent->is_in) -+ if (task->depend[i].is_in && ent->is_in) - continue; - - if (!ent->is_in) -@@ -280,9 +331,18 @@ gomp_task_handle_depend (struct gomp_tas - then the task may be executed by any member of the team. - - DEPEND is an array containing: -+ if depend[0] is non-zero, then: - depend[0]: number of depend elements. -- depend[1]: number of depend elements of type "out". -- depend[2..N+1]: address of [1..N]th depend element. */ -+ depend[1]: number of depend elements of type "out/inout". -+ depend[2..N+1]: address of [1..N]th depend element. -+ otherwise, when depend[0] is zero, then: -+ depend[1]: number of depend elements. -+ depend[2]: number of depend elements of type "out/inout". -+ depend[3]: number of depend elements of type "mutexinoutset". -+ depend[4]: number of depend elements of type "in". -+ depend[5..4+depend[2]+depend[3]+depend[4]]: address of depend elements -+ depend[5+depend[2]+depend[3]+depend[4]..4+depend[1]]: address of -+ omp_depend_t objects. */ - - void - GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), -@@ -303,10 +363,20 @@ GOMP_task (void (*fn) (void *), void *da - #endif - - /* If parallel or taskgroup has been cancelled, don't start new tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup && thr->task->taskgroup->cancelled))) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } - - if ((flags & GOMP_TASK_FLAG_PRIORITY) == 0) - priority = 0; -@@ -377,7 +447,7 @@ GOMP_task (void (*fn) (void *), void *da - size_t depend_size = 0; - - if (flags & GOMP_TASK_FLAG_DEPEND) -- depend_size = ((uintptr_t) depend[0] -+ depend_size = ((uintptr_t) (depend[0] ? depend[0] : depend[1]) - * sizeof (struct gomp_task_depend_entry)); - task = gomp_malloc (sizeof (*task) + depend_size - + arg_size + arg_align - 1); -@@ -404,14 +474,26 @@ GOMP_task (void (*fn) (void *), void *da - gomp_mutex_lock (&team->task_lock); - /* If parallel or taskgroup has been cancelled, don't start new - tasks. */ -- if (__builtin_expect ((gomp_team_barrier_cancelled (&team->barrier) -- || (taskgroup && taskgroup->cancelled)) -- && !task->copy_ctors_done, 0)) -+ if (__builtin_expect (gomp_cancel_var, 0) -+ && !task->copy_ctors_done) - { -- gomp_mutex_unlock (&team->task_lock); -- gomp_finish_task (task); -- free (task); -- return; -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ { -+ do_cancel: -+ gomp_mutex_unlock (&team->task_lock); -+ gomp_finish_task (task); -+ free (task); -+ return; -+ } -+ if (taskgroup) -+ { -+ if (taskgroup->cancelled) -+ goto do_cancel; -+ if (taskgroup->workshare -+ && taskgroup->prev -+ && taskgroup->prev->cancelled) -+ goto do_cancel; -+ } - } - if (taskgroup) - taskgroup->num_children++; -@@ -463,6 +545,7 @@ GOMP_task (void (*fn) (void *), void *da - - ialias (GOMP_taskgroup_start) - ialias (GOMP_taskgroup_end) -+ialias (GOMP_taskgroup_reduction_register) - - #define TYPE long - #define UTYPE unsigned long -@@ -601,10 +684,20 @@ gomp_create_target_task (struct gomp_dev - struct gomp_team *team = thr->ts.team; - - /* If parallel or taskgroup has been cancelled, don't start new tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup && thr->task->taskgroup->cancelled))) -- return true; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return true; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return true; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return true; -+ } -+ } - - struct gomp_target_task *ttask; - struct gomp_task *task; -@@ -617,7 +710,7 @@ gomp_create_target_task (struct gomp_dev - - if (depend != NULL) - { -- depend_cnt = (uintptr_t) depend[0]; -+ depend_cnt = (uintptr_t) (depend[0] ? depend[0] : depend[1]); - depend_size = depend_cnt * sizeof (struct gomp_task_depend_entry); - } - if (fn) -@@ -687,13 +780,25 @@ gomp_create_target_task (struct gomp_dev - task->final_task = 0; - gomp_mutex_lock (&team->task_lock); - /* If parallel or taskgroup has been cancelled, don't start new tasks. */ -- if (__builtin_expect (gomp_team_barrier_cancelled (&team->barrier) -- || (taskgroup && taskgroup->cancelled), 0)) -+ if (__builtin_expect (gomp_cancel_var, 0)) - { -- gomp_mutex_unlock (&team->task_lock); -- gomp_finish_task (task); -- free (task); -- return true; -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ { -+ do_cancel: -+ gomp_mutex_unlock (&team->task_lock); -+ gomp_finish_task (task); -+ free (task); -+ return true; -+ } -+ if (taskgroup) -+ { -+ if (taskgroup->cancelled) -+ goto do_cancel; -+ if (taskgroup->workshare -+ && taskgroup->prev -+ && taskgroup->prev->cancelled) -+ goto do_cancel; -+ } - } - if (depend_size) - { -@@ -986,10 +1091,21 @@ gomp_task_run_pre (struct gomp_task *chi - - if (--team->task_queued_count == 0) - gomp_team_barrier_clear_task_pending (&team->barrier); -- if ((gomp_team_barrier_cancelled (&team->barrier) -- || (taskgroup && taskgroup->cancelled)) -+ if (__builtin_expect (gomp_cancel_var, 0) - && !child_task->copy_ctors_done) -- return true; -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return true; -+ if (taskgroup) -+ { -+ if (taskgroup->cancelled) -+ return true; -+ if (taskgroup->workshare -+ && taskgroup->prev -+ && taskgroup->prev->cancelled) -+ return true; -+ } -+ } - return false; - } - -@@ -1456,6 +1572,35 @@ GOMP_taskwait (void) - } - } - -+/* Called when encountering a taskwait directive with depend clause(s). -+ Wait as if it was an mergeable included task construct with empty body. */ -+ -+void -+GOMP_taskwait_depend (void **depend) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_team *team = thr->ts.team; -+ -+ /* If parallel or taskgroup has been cancelled, return early. */ -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } -+ -+ if (thr->task && thr->task->depend_hash) -+ gomp_task_maybe_wait_for_dependencies (depend); -+} -+ - /* An undeferred task is about to run. Wait for all tasks that this - undeferred task depends on. - -@@ -1464,7 +1609,7 @@ GOMP_taskwait (void) - the scheduling queues. Then we iterate through these imminently - ready tasks (and possibly other high priority tasks), and run them. - If we run out of ready dependencies to execute, we either wait for -- the reamining dependencies to finish, or wait for them to get -+ the remaining dependencies to finish, or wait for them to get - scheduled so we can run them. - - DEPEND is as in GOMP_task. */ -@@ -1477,21 +1622,50 @@ gomp_task_maybe_wait_for_dependencies (v - struct gomp_team *team = thr->ts.team; - struct gomp_task_depend_entry elem, *ent = NULL; - struct gomp_taskwait taskwait; -- size_t ndepend = (uintptr_t) depend[0]; -+ size_t orig_ndepend = (uintptr_t) depend[0]; - size_t nout = (uintptr_t) depend[1]; -+ size_t ndepend = orig_ndepend; -+ size_t normal = ndepend; -+ size_t n = 2; - size_t i; - size_t num_awaited = 0; - struct gomp_task *child_task = NULL; - struct gomp_task *to_free = NULL; - int do_wake = 0; - -+ if (ndepend == 0) -+ { -+ ndepend = nout; -+ nout = (uintptr_t) depend[2] + (uintptr_t) depend[3]; -+ normal = nout + (uintptr_t) depend[4]; -+ n = 5; -+ } - gomp_mutex_lock (&team->task_lock); - for (i = 0; i < ndepend; i++) - { -- elem.addr = depend[i + 2]; -+ elem.addr = depend[i + n]; -+ elem.is_in = i >= nout; -+ if (__builtin_expect (i >= normal, 0)) -+ { -+ void **d = (void **) elem.addr; -+ switch ((uintptr_t) d[1]) -+ { -+ case GOMP_DEPEND_IN: -+ break; -+ case GOMP_DEPEND_OUT: -+ case GOMP_DEPEND_INOUT: -+ case GOMP_DEPEND_MUTEXINOUTSET: -+ elem.is_in = 0; -+ break; -+ default: -+ gomp_fatal ("unknown omp_depend_t dependence type %d", -+ (int) (uintptr_t) d[1]); -+ } -+ elem.addr = d[0]; -+ } - ent = htab_find (task->depend_hash, &elem); - for (; ent; ent = ent->next) -- if (i >= nout && ent->is_in) -+ if (elem.is_in && ent->is_in) - continue; - else - { -@@ -1654,13 +1828,28 @@ GOMP_taskyield (void) - /* Nothing at the moment. */ - } - -+static inline struct gomp_taskgroup * -+gomp_taskgroup_init (struct gomp_taskgroup *prev) -+{ -+ struct gomp_taskgroup *taskgroup -+ = gomp_malloc (sizeof (struct gomp_taskgroup)); -+ taskgroup->prev = prev; -+ priority_queue_init (&taskgroup->taskgroup_queue); -+ taskgroup->reductions = prev ? prev->reductions : NULL; -+ taskgroup->in_taskgroup_wait = false; -+ taskgroup->cancelled = false; -+ taskgroup->workshare = false; -+ taskgroup->num_children = 0; -+ gomp_sem_init (&taskgroup->taskgroup_sem, 0); -+ return taskgroup; -+} -+ - void - GOMP_taskgroup_start (void) - { - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; - struct gomp_task *task = thr->task; -- struct gomp_taskgroup *taskgroup; - - /* If team is NULL, all tasks are executed as - GOMP_TASK_UNDEFERRED tasks and thus all children tasks of -@@ -1668,14 +1857,7 @@ GOMP_taskgroup_start (void) - by the time GOMP_taskgroup_end is called. */ - if (team == NULL) - return; -- taskgroup = gomp_malloc (sizeof (struct gomp_taskgroup)); -- taskgroup->prev = task->taskgroup; -- priority_queue_init (&taskgroup->taskgroup_queue); -- taskgroup->in_taskgroup_wait = false; -- taskgroup->cancelled = false; -- taskgroup->num_children = 0; -- gomp_sem_init (&taskgroup->taskgroup_sem, 0); -- task->taskgroup = taskgroup; -+ task->taskgroup = gomp_taskgroup_init (task->taskgroup); - } - - void -@@ -1840,6 +2022,302 @@ GOMP_taskgroup_end (void) - free (taskgroup); - } - -+static inline __attribute__((always_inline)) void -+gomp_reduction_register (uintptr_t *data, uintptr_t *old, uintptr_t *orig, -+ unsigned nthreads) -+{ -+ size_t total_cnt = 0; -+ uintptr_t *d = data; -+ struct htab *old_htab = NULL, *new_htab; -+ do -+ { -+ if (__builtin_expect (orig != NULL, 0)) -+ { -+ /* For worksharing task reductions, memory has been allocated -+ already by some other thread that encountered the construct -+ earlier. */ -+ d[2] = orig[2]; -+ d[6] = orig[6]; -+ orig = (uintptr_t *) orig[4]; -+ } -+ else -+ { -+ size_t sz = d[1] * nthreads; -+ /* Should use omp_alloc if d[3] is not -1. */ -+ void *ptr = gomp_aligned_alloc (d[2], sz); -+ memset (ptr, '\0', sz); -+ d[2] = (uintptr_t) ptr; -+ d[6] = d[2] + sz; -+ } -+ d[5] = 0; -+ total_cnt += d[0]; -+ if (d[4] == 0) -+ { -+ d[4] = (uintptr_t) old; -+ break; -+ } -+ else -+ d = (uintptr_t *) d[4]; -+ } -+ while (1); -+ if (old && old[5]) -+ { -+ old_htab = (struct htab *) old[5]; -+ total_cnt += htab_elements (old_htab); -+ } -+ new_htab = htab_create (total_cnt); -+ if (old_htab) -+ { -+ /* Copy old hash table, like in htab_expand. */ -+ hash_entry_type *p, *olimit; -+ new_htab->n_elements = htab_elements (old_htab); -+ olimit = old_htab->entries + old_htab->size; -+ p = old_htab->entries; -+ do -+ { -+ hash_entry_type x = *p; -+ if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) -+ *find_empty_slot_for_expand (new_htab, htab_hash (x)) = x; -+ p++; -+ } -+ while (p < olimit); -+ } -+ d = data; -+ do -+ { -+ size_t j; -+ for (j = 0; j < d[0]; ++j) -+ { -+ uintptr_t *p = d + 7 + j * 3; -+ p[2] = (uintptr_t) d; -+ /* Ugly hack, hash_entry_type is defined for the task dependencies, -+ which hash on the first element which is a pointer. We need -+ to hash also on the first sizeof (uintptr_t) bytes which contain -+ a pointer. Hide the cast from the compiler. */ -+ hash_entry_type n; -+ __asm ("" : "=g" (n) : "0" (p)); -+ *htab_find_slot (&new_htab, n, INSERT) = n; -+ } -+ if (d[4] == (uintptr_t) old) -+ break; -+ else -+ d = (uintptr_t *) d[4]; -+ } -+ while (1); -+ d[5] = (uintptr_t) new_htab; -+} -+ -+static void -+gomp_create_artificial_team (void) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_task_icv *icv; -+ struct gomp_team *team = gomp_new_team (1); -+ struct gomp_task *task = thr->task; -+ icv = task ? &task->icv : &gomp_global_icv; -+ team->prev_ts = thr->ts; -+ thr->ts.team = team; -+ thr->ts.team_id = 0; -+ thr->ts.work_share = &team->work_shares[0]; -+ thr->ts.last_work_share = NULL; -+#ifdef HAVE_SYNC_BUILTINS -+ thr->ts.single_count = 0; -+#endif -+ thr->ts.static_trip = 0; -+ thr->task = &team->implicit_task[0]; -+ gomp_init_task (thr->task, NULL, icv); -+ if (task) -+ { -+ thr->task = task; -+ gomp_end_task (); -+ free (task); -+ thr->task = &team->implicit_task[0]; -+ } -+#ifdef LIBGOMP_USE_PTHREADS -+ else -+ pthread_setspecific (gomp_thread_destructor, thr); -+#endif -+} -+ -+/* The format of data is: -+ data[0] cnt -+ data[1] size -+ data[2] alignment (on output array pointer) -+ data[3] allocator (-1 if malloc allocator) -+ data[4] next pointer -+ data[5] used internally (htab pointer) -+ data[6] used internally (end of array) -+ cnt times -+ ent[0] address -+ ent[1] offset -+ ent[2] used internally (pointer to data[0]) -+ The entries are sorted by increasing offset, so that a binary -+ search can be performed. Normally, data[8] is 0, exception is -+ for worksharing construct task reductions in cancellable parallel, -+ where at offset 0 there should be space for a pointer and an integer -+ which are used internally. */ -+ -+void -+GOMP_taskgroup_reduction_register (uintptr_t *data) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_team *team = thr->ts.team; -+ struct gomp_task *task; -+ unsigned nthreads; -+ if (__builtin_expect (team == NULL, 0)) -+ { -+ /* The task reduction code needs a team and task, so for -+ orphaned taskgroups just create the implicit team. */ -+ gomp_create_artificial_team (); -+ ialias_call (GOMP_taskgroup_start) (); -+ team = thr->ts.team; -+ } -+ nthreads = team->nthreads; -+ task = thr->task; -+ gomp_reduction_register (data, task->taskgroup->reductions, NULL, nthreads); -+ task->taskgroup->reductions = data; -+} -+ -+void -+GOMP_taskgroup_reduction_unregister (uintptr_t *data) -+{ -+ uintptr_t *d = data; -+ htab_free ((struct htab *) data[5]); -+ do -+ { -+ gomp_aligned_free ((void *) d[2]); -+ d = (uintptr_t *) d[4]; -+ } -+ while (d && !d[5]); -+} -+ialias (GOMP_taskgroup_reduction_unregister) -+ -+/* For i = 0 to cnt-1, remap ptrs[i] which is either address of the -+ original list item or address of previously remapped original list -+ item to address of the private copy, store that to ptrs[i]. -+ For i < cntorig, additionally set ptrs[cnt+i] to the address of -+ the original list item. */ -+ -+void -+GOMP_task_reduction_remap (size_t cnt, size_t cntorig, void **ptrs) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_task *task = thr->task; -+ unsigned id = thr->ts.team_id; -+ uintptr_t *data = task->taskgroup->reductions; -+ uintptr_t *d; -+ struct htab *reduction_htab = (struct htab *) data[5]; -+ size_t i; -+ for (i = 0; i < cnt; ++i) -+ { -+ hash_entry_type ent, n; -+ __asm ("" : "=g" (ent) : "0" (ptrs + i)); -+ n = htab_find (reduction_htab, ent); -+ if (n) -+ { -+ uintptr_t *p; -+ __asm ("" : "=g" (p) : "0" (n)); -+ /* At this point, p[0] should be equal to (uintptr_t) ptrs[i], -+ p[1] is the offset within the allocated chunk for each -+ thread, p[2] is the array registered with -+ GOMP_taskgroup_reduction_register, d[2] is the base of the -+ allocated memory and d[1] is the size of the allocated chunk -+ for one thread. */ -+ d = (uintptr_t *) p[2]; -+ ptrs[i] = (void *) (d[2] + id * d[1] + p[1]); -+ if (__builtin_expect (i < cntorig, 0)) -+ ptrs[cnt + i] = (void *) p[0]; -+ continue; -+ } -+ d = data; -+ while (d != NULL) -+ { -+ if ((uintptr_t) ptrs[i] >= d[2] && (uintptr_t) ptrs[i] < d[6]) -+ break; -+ d = (uintptr_t *) d[4]; -+ } -+ if (d == NULL) -+ gomp_fatal ("couldn't find matching task_reduction or reduction with " -+ "task modifier for %p", ptrs[i]); -+ uintptr_t off = ((uintptr_t) ptrs[i] - d[2]) % d[1]; -+ ptrs[i] = (void *) (d[2] + id * d[1] + off); -+ if (__builtin_expect (i < cntorig, 0)) -+ { -+ size_t lo = 0, hi = d[0] - 1; -+ while (lo <= hi) -+ { -+ size_t m = (lo + hi) / 2; -+ if (d[7 + 3 * m + 1] < off) -+ lo = m + 1; -+ else if (d[7 + 3 * m + 1] == off) -+ { -+ ptrs[cnt + i] = (void *) d[7 + 3 * m]; -+ break; -+ } -+ else -+ hi = m - 1; -+ } -+ if (lo > hi) -+ gomp_fatal ("couldn't find matching task_reduction or reduction " -+ "with task modifier for %p", ptrs[i]); -+ } -+ } -+} -+ -+struct gomp_taskgroup * -+gomp_parallel_reduction_register (uintptr_t *data, unsigned nthreads) -+{ -+ struct gomp_taskgroup *taskgroup = gomp_taskgroup_init (NULL); -+ gomp_reduction_register (data, NULL, NULL, nthreads); -+ taskgroup->reductions = data; -+ return taskgroup; -+} -+ -+void -+gomp_workshare_task_reduction_register (uintptr_t *data, uintptr_t *orig) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_team *team = thr->ts.team; -+ struct gomp_task *task = thr->task; -+ unsigned nthreads = team->nthreads; -+ gomp_reduction_register (data, task->taskgroup->reductions, orig, nthreads); -+ task->taskgroup->reductions = data; -+} -+ -+void -+gomp_workshare_taskgroup_start (void) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_team *team = thr->ts.team; -+ struct gomp_task *task; -+ -+ if (team == NULL) -+ { -+ gomp_create_artificial_team (); -+ team = thr->ts.team; -+ } -+ task = thr->task; -+ task->taskgroup = gomp_taskgroup_init (task->taskgroup); -+ task->taskgroup->workshare = true; -+} -+ -+void -+GOMP_workshare_task_reduction_unregister (bool cancelled) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_task *task = thr->task; -+ struct gomp_team *team = thr->ts.team; -+ uintptr_t *data = task->taskgroup->reductions; -+ ialias_call (GOMP_taskgroup_end) (); -+ if (thr->ts.team_id == 0) -+ ialias_call (GOMP_taskgroup_reduction_unregister) (data); -+ else -+ htab_free ((struct htab *) data[5]); -+ -+ if (!cancelled) -+ gomp_team_barrier_wait (&team->barrier); -+} -+ - int - omp_in_final (void) - { ---- libgomp/team.c.jj 2018-04-25 09:40:31.322655307 +0200 -+++ libgomp/team.c 2019-05-07 18:46:36.548109384 +0200 -@@ -32,7 +32,6 @@ - #include - - #ifdef LIBGOMP_USE_PTHREADS --/* This attribute contains PTHREAD_CREATE_DETACHED. */ - pthread_attr_t gomp_thread_attr; - - /* This key is for the thread destructor. */ -@@ -58,6 +57,7 @@ struct gomp_thread_start_data - struct gomp_thread_pool *thread_pool; - unsigned int place; - bool nested; -+ pthread_t handle; - }; - - -@@ -89,6 +89,9 @@ gomp_thread_start (void *xdata) - thr->ts = data->ts; - thr->task = data->task; - thr->place = data->place; -+#ifdef GOMP_NEEDS_THREAD_HANDLE -+ thr->handle = data->handle; -+#endif - - thr->ts.team->ordered_release[thr->ts.team_id] = &thr->release; - -@@ -131,6 +134,7 @@ gomp_thread_start (void *xdata) - } - - gomp_sem_destroy (&thr->release); -+ pthread_detach (pthread_self ()); - thr->thread_pool = NULL; - thr->task = NULL; - return NULL; -@@ -183,7 +187,7 @@ gomp_new_team (unsigned nthreads) - team->single_count = 0; - #endif - team->work_shares_to_free = &team->work_shares[0]; -- gomp_init_work_share (&team->work_shares[0], false, nthreads); -+ gomp_init_work_share (&team->work_shares[0], 0, nthreads); - team->work_shares[0].next_alloc = NULL; - team->work_share_list_free = NULL; - team->work_share_list_alloc = &team->work_shares[1]; -@@ -231,6 +235,7 @@ gomp_free_pool_helper (void *thread_pool - thr->thread_pool = NULL; - thr->task = NULL; - #ifdef LIBGOMP_USE_PTHREADS -+ pthread_detach (pthread_self ()); - pthread_exit (NULL); - #elif defined(__nvptx__) - asm ("exit;"); -@@ -297,7 +302,8 @@ gomp_free_thread (void *arg __attribute_ - #ifdef LIBGOMP_USE_PTHREADS - void - gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, -- unsigned flags, struct gomp_team *team) -+ unsigned flags, struct gomp_team *team, -+ struct gomp_taskgroup *taskgroup) - { - struct gomp_thread_start_data *start_data; - struct gomp_thread *thr, *nthr; -@@ -312,6 +318,7 @@ gomp_team_start (void (*fn) (void *), vo - unsigned int s = 0, rest = 0, p = 0, k = 0; - unsigned int affinity_count = 0; - struct gomp_thread **affinity_thr = NULL; -+ bool force_display = false; - - thr = gomp_thread (); - nested = thr->ts.level; -@@ -319,7 +326,12 @@ gomp_team_start (void (*fn) (void *), vo - task = thr->task; - icv = task ? &task->icv : &gomp_global_icv; - if (__builtin_expect (gomp_places_list != NULL, 0) && thr->place == 0) -- gomp_init_affinity (); -+ { -+ gomp_init_affinity (); -+ if (__builtin_expect (gomp_display_affinity_var, 0) && nthreads == 1) -+ gomp_display_affinity_thread (gomp_thread_self (), &thr->ts, -+ thr->place); -+ } - - /* Always save the previous state, even if this isn't a nested team. - In particular, we should save any work share state from an outer -@@ -338,6 +350,9 @@ gomp_team_start (void (*fn) (void *), vo - #endif - thr->ts.static_trip = 0; - thr->task = &team->implicit_task[0]; -+#ifdef GOMP_NEEDS_THREAD_HANDLE -+ thr->handle = pthread_self (); -+#endif - nthreads_var = icv->nthreads_var; - if (__builtin_expect (gomp_nthreads_var_list != NULL, 0) - && thr->ts.level < gomp_nthreads_var_list_len) -@@ -350,6 +365,7 @@ gomp_team_start (void (*fn) (void *), vo - && thr->ts.level < gomp_bind_var_list_len) - bind_var = gomp_bind_var_list[thr->ts.level]; - gomp_init_task (thr->task, task, icv); -+ thr->task->taskgroup = taskgroup; - team->implicit_task[0].icv.nthreads_var = nthreads_var; - team->implicit_task[0].icv.bind_var = bind_var; - -@@ -465,7 +481,9 @@ gomp_team_start (void (*fn) (void *), vo - pool->threads - = gomp_realloc (pool->threads, - pool->threads_size -- * sizeof (struct gomp_thread_data *)); -+ * sizeof (struct gomp_thread *)); -+ /* Add current (master) thread to threads[]. */ -+ pool->threads[0] = thr; - } - - /* Release existing idle threads. */ -@@ -540,6 +558,7 @@ gomp_team_start (void (*fn) (void *), vo - + place_partition_len)) - { - unsigned int l; -+ force_display = true; - if (affinity_thr == NULL) - { - unsigned int j; -@@ -623,6 +642,7 @@ gomp_team_start (void (*fn) (void *), vo - gomp_init_task (nthr->task, task, icv); - team->implicit_task[i].icv.nthreads_var = nthreads_var; - team->implicit_task[i].icv.bind_var = bind_var; -+ nthr->task->taskgroup = taskgroup; - nthr->fn = fn; - nthr->data = data; - team->ordered_release[i] = &nthr->release; -@@ -712,19 +732,17 @@ gomp_team_start (void (*fn) (void *), vo - { - size_t stacksize; - pthread_attr_init (&thread_attr); -- pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED); - if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize)) - pthread_attr_setstacksize (&thread_attr, stacksize); - attr = &thread_attr; - } - - start_data = gomp_alloca (sizeof (struct gomp_thread_start_data) -- * (nthreads-i)); -+ * (nthreads - i)); - - /* Launch new threads. */ - for (; i < nthreads; ++i) - { -- pthread_t pt; - int err; - - start_data->ts.place_partition_off = thr->ts.place_partition_off; -@@ -810,11 +828,14 @@ gomp_team_start (void (*fn) (void *), vo - gomp_init_task (start_data->task, task, icv); - team->implicit_task[i].icv.nthreads_var = nthreads_var; - team->implicit_task[i].icv.bind_var = bind_var; -+ start_data->task->taskgroup = taskgroup; - start_data->thread_pool = pool; - start_data->nested = nested; - - attr = gomp_adjust_thread_attr (attr, &thread_attr); -- err = pthread_create (&pt, attr, gomp_thread_start, start_data++); -+ err = pthread_create (&start_data->handle, attr, gomp_thread_start, -+ start_data); -+ start_data++; - if (err != 0) - gomp_fatal ("Thread creation failed: %s", strerror (err)); - } -@@ -854,6 +875,42 @@ gomp_team_start (void (*fn) (void *), vo - gomp_mutex_unlock (&gomp_managed_threads_lock); - #endif - } -+ if (__builtin_expect (gomp_display_affinity_var, 0)) -+ { -+ if (nested -+ || nthreads != old_threads_used -+ || force_display) -+ { -+ gomp_display_affinity_thread (gomp_thread_self (), &thr->ts, -+ thr->place); -+ if (nested) -+ { -+ start_data -= nthreads - 1; -+ for (i = 1; i < nthreads; ++i) -+ { -+ gomp_display_affinity_thread ( -+#ifdef LIBGOMP_USE_PTHREADS -+ start_data->handle, -+#else -+ gomp_thread_self (), -+#endif -+ &start_data->ts, -+ start_data->place); -+ start_data++; -+ } -+ } -+ else -+ { -+ for (i = 1; i < nthreads; ++i) -+ { -+ gomp_thread_handle handle -+ = gomp_thread_to_pthread_t (pool->threads[i]); -+ gomp_display_affinity_thread (handle, &pool->threads[i]->ts, -+ pool->threads[i]->place); -+ } -+ } -+ } -+ } - if (__builtin_expect (affinity_thr != NULL, 0) - && team->prev_ts.place_partition_len > 64) - free (affinity_thr); -@@ -894,7 +951,7 @@ gomp_team_end (void) - gomp_end_task (); - thr->ts = team->prev_ts; - -- if (__builtin_expect (thr->ts.team != NULL, 0)) -+ if (__builtin_expect (thr->ts.level != 0, 0)) - { - #ifdef HAVE_SYNC_BUILTINS - __sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads); -@@ -959,6 +1016,76 @@ team_destructor (void) - crashes. */ - pthread_key_delete (gomp_thread_destructor); - } -+ -+/* Similar to gomp_free_pool_helper, but don't detach itself, -+ gomp_pause_host will pthread_join those threads. */ -+ -+static void -+gomp_pause_pool_helper (void *thread_pool) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_thread_pool *pool -+ = (struct gomp_thread_pool *) thread_pool; -+ gomp_simple_barrier_wait_last (&pool->threads_dock); -+ gomp_sem_destroy (&thr->release); -+ thr->thread_pool = NULL; -+ thr->task = NULL; -+ pthread_exit (NULL); -+} -+ -+/* Free a thread pool and release its threads. Return non-zero on -+ failure. */ -+ -+int -+gomp_pause_host (void) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ struct gomp_thread_pool *pool = thr->thread_pool; -+ if (thr->ts.level) -+ return -1; -+ if (pool) -+ { -+ if (pool->threads_used > 0) -+ { -+ int i; -+ pthread_t *thrs -+ = gomp_alloca (sizeof (pthread_t) * pool->threads_used); -+ for (i = 1; i < pool->threads_used; i++) -+ { -+ struct gomp_thread *nthr = pool->threads[i]; -+ nthr->fn = gomp_pause_pool_helper; -+ nthr->data = pool; -+ thrs[i] = gomp_thread_to_pthread_t (nthr); -+ } -+ /* This barrier undocks threads docked on pool->threads_dock. */ -+ gomp_simple_barrier_wait (&pool->threads_dock); -+ /* And this waits till all threads have called gomp_barrier_wait_last -+ in gomp_pause_pool_helper. */ -+ gomp_simple_barrier_wait (&pool->threads_dock); -+ /* Now it is safe to destroy the barrier and free the pool. */ -+ gomp_simple_barrier_destroy (&pool->threads_dock); -+ -+#ifdef HAVE_SYNC_BUILTINS -+ __sync_fetch_and_add (&gomp_managed_threads, -+ 1L - pool->threads_used); -+#else -+ gomp_mutex_lock (&gomp_managed_threads_lock); -+ gomp_managed_threads -= pool->threads_used - 1L; -+ gomp_mutex_unlock (&gomp_managed_threads_lock); -+#endif -+ for (i = 1; i < pool->threads_used; i++) -+ pthread_join (thrs[i], NULL); -+ } -+ if (pool->last_team) -+ free_team (pool->last_team); -+#ifndef __nvptx__ -+ free (pool->threads); -+ free (pool); -+#endif -+ thr->thread_pool = NULL; -+ } -+ return 0; -+} - #endif - - struct gomp_task_icv * ---- libgomp/libgomp.h.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/libgomp.h 2019-05-07 19:01:51.285535999 +0200 -@@ -44,6 +44,7 @@ - #include "config.h" - #include "gstdint.h" - #include "libgomp-plugin.h" -+#include "gomp-constants.h" - - #ifdef HAVE_PTHREAD_H - #include -@@ -85,9 +86,21 @@ enum memmodel - - /* alloc.c */ - -+#if defined(HAVE_ALIGNED_ALLOC) \ -+ || defined(HAVE__ALIGNED_MALLOC) \ -+ || defined(HAVE_POSIX_MEMALIGN) \ -+ || defined(HAVE_MEMALIGN) -+/* Defined if gomp_aligned_alloc doesn't use fallback version -+ and free can be used instead of gomp_aligned_free. */ -+#define GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC 1 -+#endif -+ - extern void *gomp_malloc (size_t) __attribute__((malloc)); - extern void *gomp_malloc_cleared (size_t) __attribute__((malloc)); - extern void *gomp_realloc (void *, size_t); -+extern void *gomp_aligned_alloc (size_t, size_t) -+ __attribute__((malloc, alloc_size (2))); -+extern void gomp_aligned_free (void *); - - /* Avoid conflicting prototypes of alloca() in system headers by using - GCC's builtin alloca(). */ -@@ -137,7 +150,8 @@ enum gomp_schedule_type - GFS_STATIC, - GFS_DYNAMIC, - GFS_GUIDED, -- GFS_AUTO -+ GFS_AUTO, -+ GFS_MONOTONIC = 0x80000000U - }; - - struct gomp_doacross_work_share -@@ -174,6 +188,8 @@ struct gomp_doacross_work_share - /* Likewise, but for the ull implementation. */ - unsigned long long boundary_ull; - }; -+ /* Pointer to extra memory if needed for lastprivate(conditional). */ -+ void *extra; - /* Array of shift counts for each dimension if they can be flattened. */ - unsigned int shift_counts[]; - }; -@@ -275,6 +291,9 @@ struct gomp_work_share - struct gomp_work_share *next_free; - }; - -+ /* Task reductions for this work-sharing construct. */ -+ uintptr_t *task_reductions; -+ - /* If only few threads are in the team, ordered_team_ids can point - to this array which fills the padding at the end of this struct. */ - unsigned inline_ordered_team_ids[0]; -@@ -365,8 +384,12 @@ extern void **gomp_places_list; - extern unsigned long gomp_places_list_len; - extern unsigned int gomp_num_teams_var; - extern int gomp_debug_var; -+extern bool gomp_display_affinity_var; -+extern char *gomp_affinity_format_var; -+extern size_t gomp_affinity_format_len; - extern int goacc_device_num; - extern char *goacc_device_type; -+extern int goacc_default_dims[GOMP_DIM_MAX]; - - enum gomp_task_kind - { -@@ -469,8 +492,10 @@ struct gomp_taskgroup - struct gomp_taskgroup *prev; - /* Queue of tasks that belong in this taskgroup. */ - struct priority_queue taskgroup_queue; -+ uintptr_t *reductions; - bool in_taskgroup_wait; - bool cancelled; -+ bool workshare; - gomp_sem_t taskgroup_sem; - size_t num_children; - }; -@@ -613,6 +638,19 @@ struct gomp_thread - - /* User pthread thread pool */ - struct gomp_thread_pool *thread_pool; -+ -+#if defined(LIBGOMP_USE_PTHREADS) \ -+ && (!defined(HAVE_TLS) \ -+ || !defined(__GLIBC__) \ -+ || !defined(USING_INITIAL_EXEC_TLS)) -+ /* pthread_t of the thread containing this gomp_thread. -+ On Linux when using initial-exec TLS, -+ (typeof (pthread_t)) gomp_thread () - pthread_self () -+ is constant in all threads, so we can optimize and not -+ store it. */ -+#define GOMP_NEEDS_THREAD_HANDLE 1 -+ pthread_t handle; -+#endif - }; - - -@@ -709,6 +747,25 @@ extern bool gomp_affinity_finalize_place - extern bool gomp_affinity_init_level (int, unsigned long, bool); - extern void gomp_affinity_print_place (void *); - extern void gomp_get_place_proc_ids_8 (int, int64_t *); -+extern void gomp_display_affinity_place (char *, size_t, size_t *, int); -+ -+/* affinity-fmt.c */ -+ -+extern void gomp_print_string (const char *str, size_t len); -+extern void gomp_set_affinity_format (const char *, size_t); -+extern void gomp_display_string (char *, size_t, size_t *, const char *, -+ size_t); -+#ifdef LIBGOMP_USE_PTHREADS -+typedef pthread_t gomp_thread_handle; -+#else -+typedef struct {} gomp_thread_handle; -+#endif -+extern size_t gomp_display_affinity (char *, size_t, const char *, -+ gomp_thread_handle, -+ struct gomp_team_state *, unsigned int); -+extern void gomp_display_affinity_thread (gomp_thread_handle, -+ struct gomp_team_state *, -+ unsigned int) __attribute__((cold)); - - /* iter.c */ - -@@ -745,9 +802,9 @@ extern void gomp_ordered_next (void); - extern void gomp_ordered_static_init (void); - extern void gomp_ordered_static_next (void); - extern void gomp_ordered_sync (void); --extern void gomp_doacross_init (unsigned, long *, long); -+extern void gomp_doacross_init (unsigned, long *, long, size_t); - extern void gomp_doacross_ull_init (unsigned, unsigned long long *, -- unsigned long long); -+ unsigned long long, size_t); - - /* parallel.c */ - -@@ -770,6 +827,10 @@ extern bool gomp_create_target_task (str - size_t *, unsigned short *, unsigned int, - void **, void **, - enum gomp_target_task_state); -+extern struct gomp_taskgroup *gomp_parallel_reduction_register (uintptr_t *, -+ unsigned); -+extern void gomp_workshare_taskgroup_start (void); -+extern void gomp_workshare_task_reduction_register (uintptr_t *, uintptr_t *); - - static void inline - gomp_finish_task (struct gomp_task *task) -@@ -782,9 +843,11 @@ gomp_finish_task (struct gomp_task *task - - extern struct gomp_team *gomp_new_team (unsigned); - extern void gomp_team_start (void (*) (void *), void *, unsigned, -- unsigned, struct gomp_team *); -+ unsigned, struct gomp_team *, -+ struct gomp_taskgroup *); - extern void gomp_team_end (void); - extern void gomp_free_thread (void *); -+extern int gomp_pause_host (void); - - /* target.c */ - -@@ -851,6 +914,8 @@ struct splay_tree_key_s { - uintptr_t tgt_offset; - /* Reference count. */ - uintptr_t refcount; -+ /* Dynamic reference count. */ -+ uintptr_t dynamic_refcount; - /* Pointer to the original mapping of "omp declare target link" object. */ - splay_tree_key link_key; - }; -@@ -989,7 +1054,9 @@ enum gomp_map_vars_kind - }; - - extern void gomp_acc_insert_pointer (size_t, void **, size_t *, void *); --extern void gomp_acc_remove_pointer (void *, bool, int, int); -+extern void gomp_acc_remove_pointer (void *, size_t, bool, int, int, int); -+extern void gomp_acc_declare_allocate (bool, size_t, void **, size_t *, -+ unsigned short *); - - extern struct target_mem_desc *gomp_map_vars (struct gomp_device_descr *, - size_t, void **, void **, -@@ -999,12 +1066,13 @@ extern void gomp_unmap_vars (struct targ - extern void gomp_init_device (struct gomp_device_descr *); - extern void gomp_free_memmap (struct splay_tree_s *); - extern void gomp_unload_device (struct gomp_device_descr *); -+extern bool gomp_remove_var (struct gomp_device_descr *, splay_tree_key); - - /* work.c */ - --extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned); -+extern void gomp_init_work_share (struct gomp_work_share *, size_t, unsigned); - extern void gomp_fini_work_share (struct gomp_work_share *); --extern bool gomp_work_share_start (bool); -+extern bool gomp_work_share_start (size_t); - extern void gomp_work_share_end (void); - extern bool gomp_work_share_end_cancel (void); - extern void gomp_work_share_end_nowait (void); -@@ -1028,6 +1096,14 @@ gomp_work_share_init_done (void) - #include "omp-lock.h" - #define _LIBGOMP_OMP_LOCK_DEFINED 1 - #include "omp.h.in" -+#define omp_sched_monotonic 0x80000000U -+typedef enum omp_pause_resource_t -+{ -+ omp_pause_soft = 1, -+ omp_pause_hard = 2 -+} omp_pause_resource_t; -+extern int omp_pause_resource (omp_pause_resource_t, int) __GOMP_NOTHROW; -+extern int omp_pause_resource_all (omp_pause_resource_t) __GOMP_NOTHROW; - - #if !defined (HAVE_ATTRIBUTE_VISIBILITY) \ - || !defined (HAVE_ATTRIBUTE_ALIAS) \ -@@ -1082,16 +1158,26 @@ extern int gomp_test_nest_lock_25 (omp_n - # define attribute_hidden - #endif - -+#if __GNUC__ >= 9 -+# define HAVE_ATTRIBUTE_COPY -+#endif -+ -+#ifdef HAVE_ATTRIBUTE_COPY -+# define attribute_copy(arg) __attribute__ ((copy (arg))) -+#else -+# define attribute_copy(arg) -+#endif -+ - #ifdef HAVE_ATTRIBUTE_ALIAS - # define strong_alias(fn, al) \ -- extern __typeof (fn) al __attribute__ ((alias (#fn))); -+ extern __typeof (fn) al __attribute__ ((alias (#fn))) attribute_copy (fn); - - # define ialias_ulp ialias_str1(__USER_LABEL_PREFIX__) - # define ialias_str1(x) ialias_str2(x) - # define ialias_str2(x) #x - # define ialias(fn) \ - extern __typeof (fn) gomp_ialias_##fn \ -- __attribute__ ((alias (#fn))) attribute_hidden; -+ __attribute__ ((alias (#fn))) attribute_hidden attribute_copy (fn); - # define ialias_redirect(fn) \ - extern __typeof (fn) fn __asm__ (ialias_ulp "gomp_ialias_" #fn) attribute_hidden; - # define ialias_call(fn) gomp_ialias_ ## fn -@@ -1131,4 +1217,42 @@ task_to_priority_node (enum priority_que - return (struct priority_node *) ((char *) task - + priority_queue_offset (type)); - } -+ -+#ifdef LIBGOMP_USE_PTHREADS -+static inline gomp_thread_handle -+gomp_thread_self (void) -+{ -+ return pthread_self (); -+} -+ -+static inline gomp_thread_handle -+gomp_thread_to_pthread_t (struct gomp_thread *thr) -+{ -+ struct gomp_thread *this_thr = gomp_thread (); -+ if (thr == this_thr) -+ return pthread_self (); -+#ifdef GOMP_NEEDS_THREAD_HANDLE -+ return thr->handle; -+#else -+ /* On Linux with initial-exec TLS, the pthread_t of the thread containing -+ thr can be computed from thr, this_thr and pthread_self (), -+ as the distance between this_thr and pthread_self () is constant. */ -+ return pthread_self () + ((uintptr_t) thr - (uintptr_t) this_thr); -+#endif -+} -+#else -+static inline gomp_thread_handle -+gomp_thread_self (void) -+{ -+ return (gomp_thread_handle) {}; -+} -+ -+static inline gomp_thread_handle -+gomp_thread_to_pthread_t (struct gomp_thread *thr) -+{ -+ (void) thr; -+ return gomp_thread_self (); -+} -+#endif -+ - #endif /* LIBGOMP_H */ ---- libgomp/oacc-parallel.c.jj 2018-04-25 09:40:31.319655306 +0200 -+++ libgomp/oacc-parallel.c 2019-05-07 19:09:47.010991153 +0200 -@@ -27,6 +27,8 @@ - /* This file handles OpenACC constructs. */ - - #include "openacc.h" -+void acc_copyout_finalize (void *, size_t) __GOACC_NOTHROW; -+void acc_delete_finalize (void *, size_t) __GOACC_NOTHROW; - #include "libgomp.h" - #include "libgomp_g.h" - #include "gomp-constants.h" -@@ -38,31 +40,95 @@ - #include - #include - -+ -+/* In the ABI, the GOACC_FLAGs are encoded as an inverted bitmask, so that we -+ continue to support the following two legacy values. */ -+_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_ICV) == 0, -+ "legacy GOMP_DEVICE_ICV broken"); -+_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_HOST_FALLBACK) -+ == GOACC_FLAG_HOST_FALLBACK, -+ "legacy GOMP_DEVICE_HOST_FALLBACK broken"); -+ -+ -+/* Returns the number of mappings associated with the pointer or pset. PSET -+ have three mappings, whereas pointer have two. */ -+ - static int --find_pset (int pos, size_t mapnum, unsigned short *kinds) -+find_pointer (int pos, size_t mapnum, unsigned short *kinds) - { - if (pos + 1 >= mapnum) - return 0; - - unsigned char kind = kinds[pos+1] & 0xff; - -- return kind == GOMP_MAP_TO_PSET; -+ if (kind == GOMP_MAP_TO_PSET) -+ return 3; -+ else if (kind == GOMP_MAP_POINTER) -+ return 2; -+ -+ return 0; -+} -+ -+/* Handle the mapping pair that are presented when a -+ deviceptr clause is used with Fortran. */ -+ -+static void -+handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes, -+ unsigned short *kinds) -+{ -+ int i; -+ -+ for (i = 0; i < mapnum; i++) -+ { -+ unsigned short kind1 = kinds[i] & 0xff; -+ -+ /* Handle Fortran deviceptr clause. */ -+ if (kind1 == GOMP_MAP_FORCE_DEVICEPTR) -+ { -+ unsigned short kind2; -+ -+ if (i < (signed)mapnum - 1) -+ kind2 = kinds[i + 1] & 0xff; -+ else -+ kind2 = 0xffff; -+ -+ if (sizes[i] == sizeof (void *)) -+ continue; -+ -+ /* At this point, we're dealing with a Fortran deviceptr. -+ If the next element is not what we're expecting, then -+ this is an instance of where the deviceptr variable was -+ not used within the region and the pointer was removed -+ by the gimplifier. */ -+ if (kind2 == GOMP_MAP_POINTER -+ && sizes[i + 1] == 0 -+ && hostaddrs[i] == *(void **)hostaddrs[i + 1]) -+ { -+ kinds[i+1] = kinds[i]; -+ sizes[i+1] = sizeof (void *); -+ } -+ -+ /* Invalidate the entry. */ -+ hostaddrs[i] = NULL; -+ } -+ } - } - - static void goacc_wait (int async, int num_waits, va_list *ap); - - --/* Launch a possibly offloaded function on DEVICE. FN is the host fn -+/* Launch a possibly offloaded function with FLAGS. FN is the host fn - address. MAPNUM, HOSTADDRS, SIZES & KINDS describe the memory - blocks to be copied to/from the device. Varadic arguments are - keyed optional parameters terminated with a zero. */ - - void --GOACC_parallel_keyed (int device, void (*fn) (void *), -+GOACC_parallel_keyed (int flags_m, void (*fn) (void *), - size_t mapnum, void **hostaddrs, size_t *sizes, - unsigned short *kinds, ...) - { -- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; -+ int flags = GOACC_FLAGS_UNMARSHAL (flags_m); -+ - va_list ap; - struct goacc_thread *thr; - struct gomp_device_descr *acc_dev; -@@ -88,9 +154,11 @@ GOACC_parallel_keyed (int device, void ( - thr = goacc_thread (); - acc_dev = thr->dev; - -+ handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds); -+ - /* Host fallback if "if" clause is false or if the current device is set to - the host. */ -- if (host_fallback) -+ if (flags & GOACC_FLAG_HOST_FALLBACK) - { - goacc_save_and_set_bind (acc_device_host); - fn (hostaddrs); -@@ -140,9 +208,7 @@ GOACC_parallel_keyed (int device, void ( - case GOMP_LAUNCH_WAIT: - { - unsigned num_waits = GOMP_LAUNCH_OP (tag); -- -- if (num_waits) -- goacc_wait (async, num_waits, &ap); -+ goacc_wait (async, num_waits, &ap); - break; - } - -@@ -177,16 +243,36 @@ GOACC_parallel_keyed (int device, void ( - devaddrs = gomp_alloca (sizeof (void *) * mapnum); - for (i = 0; i < mapnum; i++) - devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start -- + tgt->list[i].key->tgt_offset); -+ + tgt->list[i].key->tgt_offset -+ + tgt->list[i].offset); - - acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs, - async, dims, tgt); - - /* If running synchronously, unmap immediately. */ -- if (async < acc_async_noval) -+ bool copyfrom = true; -+ if (async_synchronous_p (async)) - gomp_unmap_vars (tgt, true); - else -- tgt->device_descr->openacc.register_async_cleanup_func (tgt, async); -+ { -+ bool async_unmap = false; -+ for (size_t i = 0; i < tgt->list_count; i++) -+ { -+ splay_tree_key k = tgt->list[i].key; -+ if (k && k->refcount == 1) -+ { -+ async_unmap = true; -+ break; -+ } -+ } -+ if (async_unmap) -+ tgt->device_descr->openacc.register_async_cleanup_func (tgt, async); -+ else -+ { -+ copyfrom = false; -+ gomp_unmap_vars (tgt, copyfrom); -+ } -+ } - - acc_dev->openacc.async_set_async_func (acc_async_sync); - } -@@ -194,7 +280,7 @@ GOACC_parallel_keyed (int device, void ( - /* Legacy entry point, only provide host execution. */ - - void --GOACC_parallel (int device, void (*fn) (void *), -+GOACC_parallel (int flags_m, void (*fn) (void *), - size_t mapnum, void **hostaddrs, size_t *sizes, - unsigned short *kinds, - int num_gangs, int num_workers, int vector_length, -@@ -206,10 +292,11 @@ GOACC_parallel (int device, void (*fn) ( - } - - void --GOACC_data_start (int device, size_t mapnum, -+GOACC_data_start (int flags_m, size_t mapnum, - void **hostaddrs, size_t *sizes, unsigned short *kinds) - { -- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; -+ int flags = GOACC_FLAGS_UNMARSHAL (flags_m); -+ - struct target_mem_desc *tgt; - - #ifdef HAVE_INTTYPES_H -@@ -227,7 +314,7 @@ GOACC_data_start (int device, size_t map - - /* Host fallback or 'do nothing'. */ - if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) -- || host_fallback) -+ || (flags & GOACC_FLAG_HOST_FALLBACK)) - { - tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true, - GOMP_MAP_VARS_OPENACC); -@@ -258,13 +345,14 @@ GOACC_data_end (void) - } - - void --GOACC_enter_exit_data (int device, size_t mapnum, -+GOACC_enter_exit_data (int flags_m, size_t mapnum, - void **hostaddrs, size_t *sizes, unsigned short *kinds, - int async, int num_waits, ...) - { -+ int flags = GOACC_FLAGS_UNMARSHAL (flags_m); -+ - struct goacc_thread *thr; - struct gomp_device_descr *acc_dev; -- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; - bool data_enter = false; - size_t i; - -@@ -274,7 +362,7 @@ GOACC_enter_exit_data (int device, size_ - acc_dev = thr->dev; - - if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) -- || host_fallback) -+ || (flags & GOACC_FLAG_HOST_FALLBACK)) - return; - - if (num_waits) -@@ -286,6 +374,17 @@ GOACC_enter_exit_data (int device, size_ - va_end (ap); - } - -+ /* Determine whether "finalize" semantics apply to all mappings of this -+ OpenACC directive. */ -+ bool finalize = false; -+ if (mapnum > 0) -+ { -+ unsigned char kind = kinds[0] & 0xff; -+ if (kind == GOMP_MAP_DELETE -+ || kind == GOMP_MAP_FORCE_FROM) -+ finalize = true; -+ } -+ - acc_dev->openacc.async_set_async_func (async); - - /* Determine if this is an "acc enter data". */ -@@ -298,13 +397,17 @@ GOACC_enter_exit_data (int device, size_ - - if (kind == GOMP_MAP_FORCE_ALLOC - || kind == GOMP_MAP_FORCE_PRESENT -- || kind == GOMP_MAP_FORCE_TO) -+ || kind == GOMP_MAP_FORCE_TO -+ || kind == GOMP_MAP_TO -+ || kind == GOMP_MAP_ALLOC) - { - data_enter = true; - break; - } - -- if (kind == GOMP_MAP_DELETE -+ if (kind == GOMP_MAP_RELEASE -+ || kind == GOMP_MAP_DELETE -+ || kind == GOMP_MAP_FROM - || kind == GOMP_MAP_FORCE_FROM) - break; - -@@ -312,31 +415,35 @@ GOACC_enter_exit_data (int device, size_ - kind); - } - -+ /* In c, non-pointers and arrays are represented by a single data clause. -+ Dynamically allocated arrays and subarrays are represented by a data -+ clause followed by an internal GOMP_MAP_POINTER. -+ -+ In fortran, scalars and not allocated arrays are represented by a -+ single data clause. Allocated arrays and subarrays have three mappings: -+ 1) the original data clause, 2) a PSET 3) a pointer to the array data. -+ */ -+ - if (data_enter) - { - for (i = 0; i < mapnum; i++) - { - unsigned char kind = kinds[i] & 0xff; - -- /* Scan for PSETs. */ -- int psets = find_pset (i, mapnum, kinds); -+ /* Scan for pointers and PSETs. */ -+ int pointer = find_pointer (i, mapnum, kinds); - -- if (!psets) -+ if (!pointer) - { - switch (kind) - { -- case GOMP_MAP_POINTER: -- gomp_acc_insert_pointer (1, &hostaddrs[i], &sizes[i], -- &kinds[i]); -- break; -+ case GOMP_MAP_ALLOC: - case GOMP_MAP_FORCE_ALLOC: - acc_create (hostaddrs[i], sizes[i]); - break; -- case GOMP_MAP_FORCE_PRESENT: -- acc_present_or_copyin (hostaddrs[i], sizes[i]); -- break; -+ case GOMP_MAP_TO: - case GOMP_MAP_FORCE_TO: -- acc_present_or_copyin (hostaddrs[i], sizes[i]); -+ acc_copyin (hostaddrs[i], sizes[i]); - break; - default: - gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x", -@@ -346,12 +453,13 @@ GOACC_enter_exit_data (int device, size_ - } - else - { -- gomp_acc_insert_pointer (3, &hostaddrs[i], &sizes[i], &kinds[i]); -+ gomp_acc_insert_pointer (pointer, &hostaddrs[i], -+ &sizes[i], &kinds[i]); - /* Increment 'i' by two because OpenACC requires fortran - arrays to be contiguous, so each PSET is associated with - one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and - one MAP_POINTER. */ -- i += 2; -+ i += pointer - 1; - } - } - } -@@ -360,22 +468,28 @@ GOACC_enter_exit_data (int device, size_ - { - unsigned char kind = kinds[i] & 0xff; - -- int psets = find_pset (i, mapnum, kinds); -+ int pointer = find_pointer (i, mapnum, kinds); - -- if (!psets) -+ if (!pointer) - { - switch (kind) - { -- case GOMP_MAP_POINTER: -- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff) -- == GOMP_MAP_FORCE_FROM, -- async, 1); -- break; -+ case GOMP_MAP_RELEASE: - case GOMP_MAP_DELETE: -- acc_delete (hostaddrs[i], sizes[i]); -+ if (acc_is_present (hostaddrs[i], sizes[i])) -+ { -+ if (finalize) -+ acc_delete_finalize (hostaddrs[i], sizes[i]); -+ else -+ acc_delete (hostaddrs[i], sizes[i]); -+ } - break; -+ case GOMP_MAP_FROM: - case GOMP_MAP_FORCE_FROM: -- acc_copyout (hostaddrs[i], sizes[i]); -+ if (finalize) -+ acc_copyout_finalize (hostaddrs[i], sizes[i]); -+ else -+ acc_copyout (hostaddrs[i], sizes[i]); - break; - default: - gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x", -@@ -385,10 +499,12 @@ GOACC_enter_exit_data (int device, size_ - } - else - { -- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff) -- == GOMP_MAP_FORCE_FROM, async, 3); -+ bool copyfrom = (kind == GOMP_MAP_FORCE_FROM -+ || kind == GOMP_MAP_FROM); -+ gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async, -+ finalize, pointer); - /* See the above comment. */ -- i += 2; -+ i += pointer - 1; - } - } - -@@ -398,13 +514,20 @@ GOACC_enter_exit_data (int device, size_ - static void - goacc_wait (int async, int num_waits, va_list *ap) - { -- struct goacc_thread *thr = goacc_thread (); -- struct gomp_device_descr *acc_dev = thr->dev; -- - while (num_waits--) - { - int qid = va_arg (*ap, int); -- -+ -+ /* Waiting on ACC_ASYNC_NOVAL maps to 'wait all'. */ -+ if (qid == acc_async_noval) -+ { -+ if (async == acc_async_sync) -+ acc_wait_all (); -+ else -+ acc_wait_all_async (async); -+ break; -+ } -+ - if (acc_async_test (qid)) - continue; - -@@ -415,16 +538,17 @@ goacc_wait (int async, int num_waits, va - launching on, the queue itself will order work as - required, so there's no need to wait explicitly. */ - else -- acc_dev->openacc.async_wait_async_func (qid, async); -+ acc_wait_async (qid, async); - } - } - - void --GOACC_update (int device, size_t mapnum, -+GOACC_update (int flags_m, size_t mapnum, - void **hostaddrs, size_t *sizes, unsigned short *kinds, - int async, int num_waits, ...) - { -- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; -+ int flags = GOACC_FLAGS_UNMARSHAL (flags_m); -+ - size_t i; - - goacc_lazy_initialize (); -@@ -433,7 +557,7 @@ GOACC_update (int device, size_t mapnum, - struct gomp_device_descr *acc_dev = thr->dev; - - if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) -- || host_fallback) -+ || (flags & GOACC_FLAG_HOST_FALLBACK)) - return; - - if (num_waits) -@@ -447,6 +571,7 @@ GOACC_update (int device, size_t mapnum, - - acc_dev->openacc.async_set_async_func (async); - -+ bool update_device = false; - for (i = 0; i < mapnum; ++i) - { - unsigned char kind = kinds[i] & 0xff; -@@ -457,11 +582,46 @@ GOACC_update (int device, size_t mapnum, - case GOMP_MAP_TO_PSET: - break; - -+ case GOMP_MAP_ALWAYS_POINTER: -+ if (update_device) -+ { -+ /* Save the contents of the host pointer. */ -+ void *dptr = acc_deviceptr (hostaddrs[i-1]); -+ uintptr_t t = *(uintptr_t *) hostaddrs[i]; -+ -+ /* Update the contents of the host pointer to reflect -+ the value of the allocated device memory in the -+ previous pointer. */ -+ *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr; -+ acc_update_device (hostaddrs[i], sizeof (uintptr_t)); -+ -+ /* Restore the host pointer. */ -+ *(uintptr_t *) hostaddrs[i] = t; -+ update_device = false; -+ } -+ break; -+ -+ case GOMP_MAP_TO: -+ if (!acc_is_present (hostaddrs[i], sizes[i])) -+ { -+ update_device = false; -+ break; -+ } -+ /* Fallthru */ - case GOMP_MAP_FORCE_TO: -+ update_device = true; - acc_update_device (hostaddrs[i], sizes[i]); - break; - -+ case GOMP_MAP_FROM: -+ if (!acc_is_present (hostaddrs[i], sizes[i])) -+ { -+ update_device = false; -+ break; -+ } -+ /* Fallthru */ - case GOMP_MAP_FORCE_FROM: -+ update_device = false; - acc_update_self (hostaddrs[i], sizes[i]); - break; - -@@ -487,8 +647,8 @@ GOACC_wait (int async, int num_waits, .. - } - else if (async == acc_async_sync) - acc_wait_all (); -- else if (async == acc_async_noval) -- goacc_thread ()->dev->openacc.async_wait_all_async_func (acc_async_noval); -+ else -+ acc_wait_all_async (async); - } - - int -@@ -504,7 +664,7 @@ GOACC_get_thread_num (void) - } - - void --GOACC_declare (int device, size_t mapnum, -+GOACC_declare (int flags_m, size_t mapnum, - void **hostaddrs, size_t *sizes, unsigned short *kinds) - { - int i; -@@ -522,9 +682,10 @@ GOACC_declare (int device, size_t mapnum - case GOMP_MAP_FORCE_FROM: - case GOMP_MAP_FORCE_TO: - case GOMP_MAP_POINTER: -+ case GOMP_MAP_RELEASE: - case GOMP_MAP_DELETE: -- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i], -- &kinds[i], 0, 0); -+ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i], -+ &kinds[i], GOMP_ASYNC_SYNC, 0); - break; - - case GOMP_MAP_FORCE_DEVICEPTR: -@@ -532,20 +693,19 @@ GOACC_declare (int device, size_t mapnum - - case GOMP_MAP_ALLOC: - if (!acc_is_present (hostaddrs[i], sizes[i])) -- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i], -- &kinds[i], 0, 0); -+ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i], -+ &kinds[i], GOMP_ASYNC_SYNC, 0); - break; - - case GOMP_MAP_TO: -- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i], -- &kinds[i], 0, 0); -+ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i], -+ &kinds[i], GOMP_ASYNC_SYNC, 0); - - break; - - case GOMP_MAP_FROM: -- kinds[i] = GOMP_MAP_FORCE_FROM; -- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i], -- &kinds[i], 0, 0); -+ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i], -+ &kinds[i], GOMP_ASYNC_SYNC, 0); - break; - - case GOMP_MAP_FORCE_PRESENT: ---- libgomp/openacc2.f90.jj 2019-05-07 19:54:18.828514375 +0200 -+++ libgomp/openacc2.f90 2019-05-07 19:56:38.454296347 +0200 -@@ -0,0 +1,1502 @@ -+! OpenACC Runtime Library Definitions. -+ -+! Copyright (C) 2014-2019 Free Software Foundation, Inc. -+ -+! Contributed by Tobias Burnus -+! and Mentor Embedded. -+ -+! This file is part of the GNU Offloading and Multi Processing Library -+! (libgomp). -+ -+! Libgomp is free software; you can redistribute it and/or modify it -+! under the terms of the GNU General Public License as published by -+! the Free Software Foundation; either version 3, or (at your option) -+! any later version. -+ -+! Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+! FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+! more details. -+ -+! Under Section 7 of GPL version 3, you are granted additional -+! permissions described in the GCC Runtime Library Exception, version -+! 3.1, as published by the Free Software Foundation. -+ -+! You should have received a copy of the GNU General Public License and -+! a copy of the GCC Runtime Library Exception along with this program; -+! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+! . -+ -+module openacc_kinds2 -+ use iso_fortran_env, only: int32 -+ implicit none -+ -+ private :: int32 -+ public :: acc_device_kind -+ -+ integer, parameter :: acc_device_kind = int32 -+ -+ public :: acc_device_none, acc_device_default, acc_device_host -+ public :: acc_device_not_host, acc_device_nvidia -+ -+ ! Keep in sync with include/gomp-constants.h. -+ integer (acc_device_kind), parameter :: acc_device_none = 0 -+ integer (acc_device_kind), parameter :: acc_device_default = 1 -+ integer (acc_device_kind), parameter :: acc_device_host = 2 -+ ! integer (acc_device_kind), parameter :: acc_device_host_nonshm = 3 removed. -+ integer (acc_device_kind), parameter :: acc_device_not_host = 4 -+ integer (acc_device_kind), parameter :: acc_device_nvidia = 5 -+ -+ public :: acc_handle_kind -+ -+ integer, parameter :: acc_handle_kind = int32 -+ -+ public :: acc_async_noval, acc_async_sync -+ -+ ! Keep in sync with include/gomp-constants.h. -+ integer (acc_handle_kind), parameter :: acc_async_noval = -1 -+ integer (acc_handle_kind), parameter :: acc_async_sync = -2 -+ -+end module -+ -+module openacc_internal2 -+ use openacc_kinds2 -+ implicit none -+ -+ interface -+ function acc_get_num_devices_h (d) -+ import -+ integer acc_get_num_devices_h -+ integer (acc_device_kind) d -+ end function -+ -+ subroutine acc_set_device_type_h (d) -+ import -+ integer (acc_device_kind) d -+ end subroutine -+ -+ function acc_get_device_type_h () -+ import -+ integer (acc_device_kind) acc_get_device_type_h -+ end function -+ -+ subroutine acc_set_device_num_h (n, d) -+ import -+ integer n -+ integer (acc_device_kind) d -+ end subroutine -+ -+ function acc_get_device_num_h (d) -+ import -+ integer acc_get_device_num_h -+ integer (acc_device_kind) d -+ end function -+ -+ function acc_async_test_h (a) -+ logical acc_async_test_h -+ integer a -+ end function -+ -+ function acc_async_test_all_h () -+ logical acc_async_test_all_h -+ end function -+ -+ subroutine acc_wait_h (a) -+ integer a -+ end subroutine -+ -+ subroutine acc_wait_async_h (a1, a2) -+ integer a1, a2 -+ end subroutine -+ -+ subroutine acc_wait_all_h () -+ end subroutine -+ -+ subroutine acc_wait_all_async_h (a) -+ integer a -+ end subroutine -+ -+ subroutine acc_init_h (d) -+ import -+ integer (acc_device_kind) d -+ end subroutine -+ -+ subroutine acc_shutdown_h (d) -+ import -+ integer (acc_device_kind) d -+ end subroutine -+ -+ function acc_on_device_h (d) -+ import -+ integer (acc_device_kind) d -+ logical acc_on_device_h -+ end function -+ -+ subroutine acc_copyin_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_copyin_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_copyin_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_present_or_copyin_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_present_or_copyin_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_present_or_copyin_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_create_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_create_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_create_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_present_or_create_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_present_or_create_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_present_or_create_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_copyout_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_copyout_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_copyout_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_copyout_finalize_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_copyout_finalize_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_copyout_finalize_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_delete_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_delete_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_delete_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_delete_finalize_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_delete_finalize_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_delete_finalize_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_update_device_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_update_device_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_update_device_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ subroutine acc_update_self_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end subroutine -+ -+ subroutine acc_update_self_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end subroutine -+ -+ subroutine acc_update_self_array_h (a) -+ type (*), dimension (..), contiguous :: a -+ end subroutine -+ -+ function acc_is_present_32_h (a, len) -+ use iso_c_binding, only: c_int32_t -+ logical acc_is_present_32_h -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ end function -+ -+ function acc_is_present_64_h (a, len) -+ use iso_c_binding, only: c_int64_t -+ logical acc_is_present_64_h -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ end function -+ -+ function acc_is_present_array_h (a) -+ logical acc_is_present_array_h -+ type (*), dimension (..), contiguous :: a -+ end function -+ -+ subroutine acc_copyin_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_copyin_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_copyin_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_create_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_create_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_create_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_copyout_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_copyout_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_copyout_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_delete_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_delete_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_delete_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_device_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_device_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_device_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_self_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_self_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ end subroutine -+ -+ subroutine acc_update_self_async_array_h (a, async) -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ end subroutine -+ end interface -+ -+ interface -+ function acc_get_num_devices_l (d) & -+ bind (C, name = "acc_get_num_devices") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_get_num_devices_l -+ integer (c_int), value :: d -+ end function -+ -+ subroutine acc_set_device_type_l (d) & -+ bind (C, name = "acc_set_device_type") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: d -+ end subroutine -+ -+ function acc_get_device_type_l () & -+ bind (C, name = "acc_get_device_type") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_get_device_type_l -+ end function -+ -+ subroutine acc_set_device_num_l (n, d) & -+ bind (C, name = "acc_set_device_num") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: n, d -+ end subroutine -+ -+ function acc_get_device_num_l (d) & -+ bind (C, name = "acc_get_device_num") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_get_device_num_l -+ integer (c_int), value :: d -+ end function -+ -+ function acc_async_test_l (a) & -+ bind (C, name = "acc_async_test") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_async_test_l -+ integer (c_int), value :: a -+ end function -+ -+ function acc_async_test_all_l () & -+ bind (C, name = "acc_async_test_all") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_async_test_all_l -+ end function -+ -+ subroutine acc_wait_l (a) & -+ bind (C, name = "acc_wait") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: a -+ end subroutine -+ -+ subroutine acc_wait_async_l (a1, a2) & -+ bind (C, name = "acc_wait_async") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: a1, a2 -+ end subroutine -+ -+ subroutine acc_wait_all_l () & -+ bind (C, name = "acc_wait_all") -+ use iso_c_binding, only: c_int -+ end subroutine -+ -+ subroutine acc_wait_all_async_l (a) & -+ bind (C, name = "acc_wait_all_async") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: a -+ end subroutine -+ -+ subroutine acc_init_l (d) & -+ bind (C, name = "acc_init") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: d -+ end subroutine -+ -+ subroutine acc_shutdown_l (d) & -+ bind (C, name = "acc_shutdown") -+ use iso_c_binding, only: c_int -+ integer (c_int), value :: d -+ end subroutine -+ -+ function acc_on_device_l (d) & -+ bind (C, name = "acc_on_device") -+ use iso_c_binding, only: c_int -+ integer (c_int) :: acc_on_device_l -+ integer (c_int), value :: d -+ end function -+ -+ subroutine acc_copyin_l (a, len) & -+ bind (C, name = "acc_copyin") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_present_or_copyin_l (a, len) & -+ bind (C, name = "acc_present_or_copyin") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_create_l (a, len) & -+ bind (C, name = "acc_create") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_present_or_create_l (a, len) & -+ bind (C, name = "acc_present_or_create") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_copyout_l (a, len) & -+ bind (C, name = "acc_copyout") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_copyout_finalize_l (a, len) & -+ bind (C, name = "acc_copyout_finalize") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_delete_l (a, len) & -+ bind (C, name = "acc_delete") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_delete_finalize_l (a, len) & -+ bind (C, name = "acc_delete_finalize") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_update_device_l (a, len) & -+ bind (C, name = "acc_update_device") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ subroutine acc_update_self_l (a, len) & -+ bind (C, name = "acc_update_self") -+ use iso_c_binding, only: c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end subroutine -+ -+ function acc_is_present_l (a, len) & -+ bind (C, name = "acc_is_present") -+ use iso_c_binding, only: c_int32_t, c_size_t -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ integer (c_int32_t) :: acc_is_present_l -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ end function -+ -+ subroutine acc_copyin_async_l (a, len, async) & -+ bind (C, name = "acc_copyin_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ -+ subroutine acc_create_async_l (a, len, async) & -+ bind (C, name = "acc_create_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ -+ subroutine acc_copyout_async_l (a, len, async) & -+ bind (C, name = "acc_copyout_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ -+ subroutine acc_delete_async_l (a, len, async) & -+ bind (C, name = "acc_delete_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ -+ subroutine acc_update_device_async_l (a, len, async) & -+ bind (C, name = "acc_update_device_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ -+ subroutine acc_update_self_async_l (a, len, async) & -+ bind (C, name = "acc_update_self_async") -+ use iso_c_binding, only: c_size_t, c_int -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_size_t), value :: len -+ integer (c_int), value :: async -+ end subroutine -+ end interface -+end module -+ -+module openacc2 -+ use openacc_kinds2 -+ use openacc_internal2 -+ implicit none -+ -+ public :: openacc_version -+ -+ public :: acc_get_num_devices, acc_set_device_type, acc_get_device_type -+ public :: acc_set_device_num, acc_get_device_num, acc_async_test -+ public :: acc_async_test_all -+ public :: acc_wait, acc_async_wait, acc_wait_async -+ public :: acc_wait_all, acc_async_wait_all, acc_wait_all_async -+ public :: acc_init, acc_shutdown, acc_on_device -+ public :: acc_copyin, acc_present_or_copyin, acc_pcopyin, acc_create -+ public :: acc_present_or_create, acc_pcreate, acc_copyout, acc_delete -+ public :: acc_update_device, acc_update_self, acc_is_present -+ public :: acc_copyin_async, acc_create_async, acc_copyout_async -+ public :: acc_delete_async, acc_update_device_async, acc_update_self_async -+ -+ integer, parameter :: openacc_version = 201306 -+ -+ interface acc_get_num_devices -+ procedure :: acc_get_num_devices_h -+ end interface -+ -+ interface acc_set_device_type -+ procedure :: acc_set_device_type_h -+ end interface -+ -+ interface acc_get_device_type -+ procedure :: acc_get_device_type_h -+ end interface -+ -+ interface acc_set_device_num -+ procedure :: acc_set_device_num_h -+ end interface -+ -+ interface acc_get_device_num -+ procedure :: acc_get_device_num_h -+ end interface -+ -+ interface acc_async_test -+ procedure :: acc_async_test_h -+ end interface -+ -+ interface acc_async_test_all -+ procedure :: acc_async_test_all_h -+ end interface -+ -+ interface acc_wait -+ procedure :: acc_wait_h -+ end interface -+ -+ ! acc_async_wait is an OpenACC 1.0 compatibility name for acc_wait. -+ interface acc_async_wait -+ procedure :: acc_wait_h -+ end interface -+ -+ interface acc_wait_async -+ procedure :: acc_wait_async_h -+ end interface -+ -+ interface acc_wait_all -+ procedure :: acc_wait_all_h -+ end interface -+ -+ ! acc_async_wait_all is an OpenACC 1.0 compatibility name for acc_wait_all. -+ interface acc_async_wait_all -+ procedure :: acc_wait_all_h -+ end interface -+ -+ interface acc_wait_all_async -+ procedure :: acc_wait_all_async_h -+ end interface -+ -+ interface acc_init -+ procedure :: acc_init_h -+ end interface -+ -+ interface acc_shutdown -+ procedure :: acc_shutdown_h -+ end interface -+ -+ interface acc_on_device -+ procedure :: acc_on_device_h -+ end interface -+ -+ ! acc_malloc: Only available in C/C++ -+ ! acc_free: Only available in C/C++ -+ -+ ! As vendor extension, the following code supports both 32bit and 64bit -+ ! arguments for "size"; the OpenACC standard only permits default-kind -+ ! integers, which are of kind 4 (i.e. 32 bits). -+ ! Additionally, the two-argument version also takes arrays as argument. -+ ! and the one argument version also scalars. Note that the code assumes -+ ! that the arrays are contiguous. -+ -+ interface acc_copyin -+ procedure :: acc_copyin_32_h -+ procedure :: acc_copyin_64_h -+ procedure :: acc_copyin_array_h -+ end interface -+ -+ interface acc_present_or_copyin -+ procedure :: acc_present_or_copyin_32_h -+ procedure :: acc_present_or_copyin_64_h -+ procedure :: acc_present_or_copyin_array_h -+ end interface -+ -+ interface acc_pcopyin -+ procedure :: acc_present_or_copyin_32_h -+ procedure :: acc_present_or_copyin_64_h -+ procedure :: acc_present_or_copyin_array_h -+ end interface -+ -+ interface acc_create -+ procedure :: acc_create_32_h -+ procedure :: acc_create_64_h -+ procedure :: acc_create_array_h -+ end interface -+ -+ interface acc_present_or_create -+ procedure :: acc_present_or_create_32_h -+ procedure :: acc_present_or_create_64_h -+ procedure :: acc_present_or_create_array_h -+ end interface -+ -+ interface acc_pcreate -+ procedure :: acc_present_or_create_32_h -+ procedure :: acc_present_or_create_64_h -+ procedure :: acc_present_or_create_array_h -+ end interface -+ -+ interface acc_copyout -+ procedure :: acc_copyout_32_h -+ procedure :: acc_copyout_64_h -+ procedure :: acc_copyout_array_h -+ end interface -+ -+ interface acc_copyout_finalize -+ procedure :: acc_copyout_finalize_32_h -+ procedure :: acc_copyout_finalize_64_h -+ procedure :: acc_copyout_finalize_array_h -+ end interface -+ -+ interface acc_delete -+ procedure :: acc_delete_32_h -+ procedure :: acc_delete_64_h -+ procedure :: acc_delete_array_h -+ end interface -+ -+ interface acc_delete_finalize -+ procedure :: acc_delete_finalize_32_h -+ procedure :: acc_delete_finalize_64_h -+ procedure :: acc_delete_finalize_array_h -+ end interface -+ -+ interface acc_update_device -+ procedure :: acc_update_device_32_h -+ procedure :: acc_update_device_64_h -+ procedure :: acc_update_device_array_h -+ end interface -+ -+ interface acc_update_self -+ procedure :: acc_update_self_32_h -+ procedure :: acc_update_self_64_h -+ procedure :: acc_update_self_array_h -+ end interface -+ -+ ! acc_map_data: Only available in C/C++ -+ ! acc_unmap_data: Only available in C/C++ -+ ! acc_deviceptr: Only available in C/C++ -+ ! acc_hostptr: Only available in C/C++ -+ -+ interface acc_is_present -+ procedure :: acc_is_present_32_h -+ procedure :: acc_is_present_64_h -+ procedure :: acc_is_present_array_h -+ end interface -+ -+ ! acc_memcpy_to_device: Only available in C/C++ -+ ! acc_memcpy_from_device: Only available in C/C++ -+ -+ interface acc_copyin_async -+ procedure :: acc_copyin_async_32_h -+ procedure :: acc_copyin_async_64_h -+ procedure :: acc_copyin_async_array_h -+ end interface -+ -+ interface acc_create_async -+ procedure :: acc_create_async_32_h -+ procedure :: acc_create_async_64_h -+ procedure :: acc_create_async_array_h -+ end interface -+ -+ interface acc_copyout_async -+ procedure :: acc_copyout_async_32_h -+ procedure :: acc_copyout_async_64_h -+ procedure :: acc_copyout_async_array_h -+ end interface -+ -+ interface acc_delete_async -+ procedure :: acc_delete_async_32_h -+ procedure :: acc_delete_async_64_h -+ procedure :: acc_delete_async_array_h -+ end interface -+ -+ interface acc_update_device_async -+ procedure :: acc_update_device_async_32_h -+ procedure :: acc_update_device_async_64_h -+ procedure :: acc_update_device_async_array_h -+ end interface -+ -+ interface acc_update_self_async -+ procedure :: acc_update_self_async_32_h -+ procedure :: acc_update_self_async_64_h -+ procedure :: acc_update_self_async_array_h -+ end interface -+ -+end module -+ -+function acc_get_num_devices_h (d) -+ use openacc_internal2, only: acc_get_num_devices_l -+ use openacc_kinds2 -+ integer acc_get_num_devices_h -+ integer (acc_device_kind) d -+ acc_get_num_devices_h = acc_get_num_devices_l (d) -+end function -+ -+subroutine acc_set_device_type_h (d) -+ use openacc_internal2, only: acc_set_device_type_l -+ use openacc_kinds2 -+ integer (acc_device_kind) d -+ call acc_set_device_type_l (d) -+end subroutine -+ -+function acc_get_device_type_h () -+ use openacc_internal2, only: acc_get_device_type_l -+ use openacc_kinds2 -+ integer (acc_device_kind) acc_get_device_type_h -+ acc_get_device_type_h = acc_get_device_type_l () -+end function -+ -+subroutine acc_set_device_num_h (n, d) -+ use openacc_internal2, only: acc_set_device_num_l -+ use openacc_kinds2 -+ integer n -+ integer (acc_device_kind) d -+ call acc_set_device_num_l (n, d) -+end subroutine -+ -+function acc_get_device_num_h (d) -+ use openacc_internal2, only: acc_get_device_num_l -+ use openacc_kinds2 -+ integer acc_get_device_num_h -+ integer (acc_device_kind) d -+ acc_get_device_num_h = acc_get_device_num_l (d) -+end function -+ -+function acc_async_test_h (a) -+ use openacc_internal2, only: acc_async_test_l -+ logical acc_async_test_h -+ integer a -+ if (acc_async_test_l (a) .eq. 1) then -+ acc_async_test_h = .TRUE. -+ else -+ acc_async_test_h = .FALSE. -+ end if -+end function -+ -+function acc_async_test_all_h () -+ use openacc_internal2, only: acc_async_test_all_l -+ logical acc_async_test_all_h -+ if (acc_async_test_all_l () .eq. 1) then -+ acc_async_test_all_h = .TRUE. -+ else -+ acc_async_test_all_h = .FALSE. -+ end if -+end function -+ -+subroutine acc_wait_h (a) -+ use openacc_internal2, only: acc_wait_l -+ integer a -+ call acc_wait_l (a) -+end subroutine -+ -+subroutine acc_wait_async_h (a1, a2) -+ use openacc_internal2, only: acc_wait_async_l -+ integer a1, a2 -+ call acc_wait_async_l (a1, a2) -+end subroutine -+ -+subroutine acc_wait_all_h () -+ use openacc_internal2, only: acc_wait_all_l -+ call acc_wait_all_l () -+end subroutine -+ -+subroutine acc_wait_all_async_h (a) -+ use openacc_internal2, only: acc_wait_all_async_l -+ integer a -+ call acc_wait_all_async_l (a) -+end subroutine -+ -+subroutine acc_init_h (d) -+ use openacc_internal2, only: acc_init_l -+ use openacc_kinds2 -+ integer (acc_device_kind) d -+ call acc_init_l (d) -+end subroutine -+ -+subroutine acc_shutdown_h (d) -+ use openacc_internal2, only: acc_shutdown_l -+ use openacc_kinds2 -+ integer (acc_device_kind) d -+ call acc_shutdown_l (d) -+end subroutine -+ -+function acc_on_device_h (d) -+ use openacc_internal2, only: acc_on_device_l -+ use openacc_kinds2 -+ integer (acc_device_kind) d -+ logical acc_on_device_h -+ if (acc_on_device_l (d) .eq. 1) then -+ acc_on_device_h = .TRUE. -+ else -+ acc_on_device_h = .FALSE. -+ end if -+end function -+ -+subroutine acc_copyin_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_copyin_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_copyin_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyin_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_copyin_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_copyin_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyin_array_h (a) -+ use openacc_internal2, only: acc_copyin_l -+ type (*), dimension (..), contiguous :: a -+ call acc_copyin_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_present_or_copyin_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_present_or_copyin_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_present_or_copyin_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_present_or_copyin_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_present_or_copyin_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_present_or_copyin_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_present_or_copyin_array_h (a) -+ use openacc_internal2, only: acc_present_or_copyin_l -+ type (*), dimension (..), contiguous :: a -+ call acc_present_or_copyin_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_create_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_create_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_create_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_create_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_create_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_create_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_create_array_h (a) -+ use openacc_internal2, only: acc_create_l -+ type (*), dimension (..), contiguous :: a -+ call acc_create_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_present_or_create_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_present_or_create_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_present_or_create_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_present_or_create_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_present_or_create_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_present_or_create_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_present_or_create_array_h (a) -+ use openacc_internal2, only: acc_present_or_create_l -+ type (*), dimension (..), contiguous :: a -+ call acc_present_or_create_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_copyout_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_copyout_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_copyout_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyout_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_copyout_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_copyout_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyout_array_h (a) -+ use openacc_internal2, only: acc_copyout_l -+ type (*), dimension (..), contiguous :: a -+ call acc_copyout_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_copyout_finalize_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_copyout_finalize_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_copyout_finalize_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyout_finalize_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_copyout_finalize_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_copyout_finalize_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_copyout_finalize_array_h (a) -+ use openacc_internal2, only: acc_copyout_finalize_l -+ type (*), dimension (..), contiguous :: a -+ call acc_copyout_finalize_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_delete_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_delete_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_delete_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_delete_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_delete_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_delete_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_delete_array_h (a) -+ use openacc_internal2, only: acc_delete_l -+ type (*), dimension (..), contiguous :: a -+ call acc_delete_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_delete_finalize_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_delete_finalize_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_delete_finalize_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_delete_finalize_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_delete_finalize_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_delete_finalize_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_delete_finalize_array_h (a) -+ use openacc_internal2, only: acc_delete_finalize_l -+ type (*), dimension (..), contiguous :: a -+ call acc_delete_finalize_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_update_device_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_update_device_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_update_device_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_update_device_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_update_device_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_update_device_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_update_device_array_h (a) -+ use openacc_internal2, only: acc_update_device_l -+ type (*), dimension (..), contiguous :: a -+ call acc_update_device_l (a, sizeof (a)) -+end subroutine -+ -+subroutine acc_update_self_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_update_self_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ call acc_update_self_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_update_self_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_update_self_l -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ call acc_update_self_l (a, int (len, kind = c_size_t)) -+end subroutine -+ -+subroutine acc_update_self_array_h (a) -+ use openacc_internal2, only: acc_update_self_l -+ type (*), dimension (..), contiguous :: a -+ call acc_update_self_l (a, sizeof (a)) -+end subroutine -+ -+function acc_is_present_32_h (a, len) -+ use iso_c_binding, only: c_int32_t, c_size_t -+ use openacc_internal2, only: acc_is_present_l -+ logical acc_is_present_32_h -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ if (acc_is_present_l (a, int (len, kind = c_size_t)) .eq. 1) then -+ acc_is_present_32_h = .TRUE. -+ else -+ acc_is_present_32_h = .FALSE. -+ end if -+end function -+ -+function acc_is_present_64_h (a, len) -+ use iso_c_binding, only: c_int64_t, c_size_t -+ use openacc_internal2, only: acc_is_present_l -+ logical acc_is_present_64_h -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ if (acc_is_present_l (a, int (len, kind = c_size_t)) .eq. 1) then -+ acc_is_present_64_h = .TRUE. -+ else -+ acc_is_present_64_h = .FALSE. -+ end if -+end function -+ -+function acc_is_present_array_h (a) -+ use openacc_internal2, only: acc_is_present_l -+ logical acc_is_present_array_h -+ type (*), dimension (..), contiguous :: a -+ acc_is_present_array_h = acc_is_present_l (a, sizeof (a)) == 1 -+end function -+ -+subroutine acc_copyin_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_copyin_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_copyin_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_copyin_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_copyin_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_copyin_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_copyin_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_copyin_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_copyin_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_create_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_create_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_create_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_create_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_create_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_create_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_create_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_create_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_create_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_copyout_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_copyout_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_copyout_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_copyout_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_copyout_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_copyout_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_copyout_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_copyout_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_copyout_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_delete_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_delete_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_delete_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_delete_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_delete_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_delete_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_delete_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_delete_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_delete_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_device_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_update_device_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_update_device_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_device_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_update_device_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_update_device_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_device_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_update_device_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_update_device_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_self_async_32_h (a, len, async) -+ use iso_c_binding, only: c_int32_t, c_size_t, c_int -+ use openacc_internal2, only: acc_update_self_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int32_t) len -+ integer (acc_handle_kind) async -+ call acc_update_self_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_self_async_64_h (a, len, async) -+ use iso_c_binding, only: c_int64_t, c_size_t, c_int -+ use openacc_internal2, only: acc_update_self_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a -+ type (*), dimension (*) :: a -+ integer (c_int64_t) len -+ integer (acc_handle_kind) async -+ call acc_update_self_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int)) -+end subroutine -+ -+subroutine acc_update_self_async_array_h (a, async) -+ use iso_c_binding, only: c_int -+ use openacc_internal2, only: acc_update_self_async_l -+ use openacc_kinds2, only: acc_handle_kind -+ type (*), dimension (..), contiguous :: a -+ integer (acc_handle_kind) async -+ call acc_update_self_async_l (a, sizeof (a), int (async, kind = c_int)) -+end subroutine ---- libgomp/taskloop.c.jj 2018-04-25 09:40:31.913655581 +0200 -+++ libgomp/taskloop.c 2019-05-07 18:46:36.547109400 +0200 -@@ -149,11 +149,28 @@ GOMP_taskloop (void (*fn) (void *), void - - if (flags & GOMP_TASK_FLAG_NOGROUP) - { -- if (thr->task && thr->task->taskgroup && thr->task->taskgroup->cancelled) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) -+ && thr->task -+ && thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } - } - else -- ialias_call (GOMP_taskgroup_start) (); -+ { -+ ialias_call (GOMP_taskgroup_start) (); -+ if (flags & GOMP_TASK_FLAG_REDUCTION) -+ { -+ struct gomp_data_head { TYPE t1, t2; uintptr_t *ptr; }; -+ uintptr_t *ptr = ((struct gomp_data_head *) data)->ptr; -+ ialias_call (GOMP_taskgroup_reduction_register) (ptr); -+ } -+ } - - if (priority > gomp_max_task_priority_var) - priority = gomp_max_task_priority_var; -@@ -284,19 +301,31 @@ GOMP_taskloop (void (*fn) (void *), void - gomp_mutex_lock (&team->task_lock); - /* If parallel or taskgroup has been cancelled, don't start new - tasks. */ -- if (__builtin_expect ((gomp_team_barrier_cancelled (&team->barrier) -- || (taskgroup && taskgroup->cancelled)) -- && cpyfn == NULL, 0)) -+ if (__builtin_expect (gomp_cancel_var, 0) -+ && cpyfn == NULL) - { -- gomp_mutex_unlock (&team->task_lock); -- for (i = 0; i < num_tasks; i++) -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ { -+ do_cancel: -+ gomp_mutex_unlock (&team->task_lock); -+ for (i = 0; i < num_tasks; i++) -+ { -+ gomp_finish_task (tasks[i]); -+ free (tasks[i]); -+ } -+ if ((flags & GOMP_TASK_FLAG_NOGROUP) == 0) -+ ialias_call (GOMP_taskgroup_end) (); -+ return; -+ } -+ if (taskgroup) - { -- gomp_finish_task (tasks[i]); -- free (tasks[i]); -+ if (taskgroup->cancelled) -+ goto do_cancel; -+ if (taskgroup->workshare -+ && taskgroup->prev -+ && taskgroup->prev->cancelled) -+ goto do_cancel; - } -- if ((flags & GOMP_TASK_FLAG_NOGROUP) == 0) -- ialias_call (GOMP_taskgroup_end) (); -- return; - } - if (taskgroup) - taskgroup->num_children += num_tasks; ---- libgomp/parallel.c.jj 2018-04-25 09:40:31.926655587 +0200 -+++ libgomp/parallel.c 2019-05-07 18:46:36.532109640 +0200 -@@ -123,7 +123,8 @@ void - GOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads) - { - num_threads = gomp_resolve_num_threads (num_threads, 0); -- gomp_team_start (fn, data, num_threads, 0, gomp_new_team (num_threads)); -+ gomp_team_start (fn, data, num_threads, 0, gomp_new_team (num_threads), -+ NULL); - } - - void -@@ -161,14 +162,33 @@ GOMP_parallel_end (void) - ialias (GOMP_parallel_end) - - void --GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, unsigned int flags) -+GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, -+ unsigned int flags) - { - num_threads = gomp_resolve_num_threads (num_threads, 0); -- gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads)); -+ gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads), -+ NULL); - fn (data); - ialias_call (GOMP_parallel_end) (); - } - -+unsigned -+GOMP_parallel_reductions (void (*fn) (void *), void *data, -+ unsigned num_threads, unsigned int flags) -+{ -+ struct gomp_taskgroup *taskgroup; -+ num_threads = gomp_resolve_num_threads (num_threads, 0); -+ uintptr_t *rdata = *(uintptr_t **)data; -+ taskgroup = gomp_parallel_reduction_register (rdata, num_threads); -+ gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads), -+ taskgroup); -+ fn (data); -+ ialias_call (GOMP_parallel_end) (); -+ gomp_sem_destroy (&taskgroup->taskgroup_sem); -+ free (taskgroup); -+ return num_threads; -+} -+ - bool - GOMP_cancellation_point (int which) - { -@@ -185,8 +205,15 @@ GOMP_cancellation_point (int which) - } - else if (which & GOMP_CANCEL_TASKGROUP) - { -- if (thr->task->taskgroup && thr->task->taskgroup->cancelled) -- return true; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return true; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return true; -+ } - /* FALLTHRU into the GOMP_CANCEL_PARALLEL case, - as #pragma omp cancel parallel also cancels all explicit - tasks. */ -@@ -218,11 +245,17 @@ GOMP_cancel (int which, bool do_cancel) - } - else if (which & GOMP_CANCEL_TASKGROUP) - { -- if (thr->task->taskgroup && !thr->task->taskgroup->cancelled) -+ if (thr->task->taskgroup) - { -- gomp_mutex_lock (&team->task_lock); -- thr->task->taskgroup->cancelled = true; -- gomp_mutex_unlock (&team->task_lock); -+ struct gomp_taskgroup *taskgroup = thr->task->taskgroup; -+ if (taskgroup->workshare && taskgroup->prev) -+ taskgroup = taskgroup->prev; -+ if (!taskgroup->cancelled) -+ { -+ gomp_mutex_lock (&team->task_lock); -+ taskgroup->cancelled = true; -+ gomp_mutex_unlock (&team->task_lock); -+ } - } - return true; - } ---- libgomp/oacc-plugin.h.jj 2018-04-25 09:40:31.322655307 +0200 -+++ libgomp/oacc-plugin.h 2019-05-07 18:46:36.531109656 +0200 -@@ -29,5 +29,6 @@ - - extern void GOMP_PLUGIN_async_unmap_vars (void *, int); - extern void *GOMP_PLUGIN_acc_thread (void); -+extern int GOMP_PLUGIN_acc_default_dim (unsigned int); - - #endif ---- libgomp/target.c.jj 2018-04-25 09:40:31.912655580 +0200 -+++ libgomp/target.c 2019-05-07 19:07:21.032306327 +0200 -@@ -180,16 +180,22 @@ gomp_device_copy (struct gomp_device_des - /* Infrastructure for coalescing adjacent or nearly adjacent (in device addresses) - host to device memory transfers. */ - -+struct gomp_coalesce_chunk -+{ -+ /* The starting and ending point of a coalesced chunk of memory. */ -+ size_t start, end; -+}; -+ - struct gomp_coalesce_buf - { - /* Buffer into which gomp_copy_host2dev will memcpy data and from which - it will be copied to the device. */ - void *buf; - struct target_mem_desc *tgt; -- /* Array with offsets, chunks[2 * i] is the starting offset and -- chunks[2 * i + 1] ending offset relative to tgt->tgt_start device address -+ /* Array with offsets, chunks[i].start is the starting offset and -+ chunks[i].end ending offset relative to tgt->tgt_start device address - of chunks which are to be copied to buf and later copied to device. */ -- size_t *chunks; -+ struct gomp_coalesce_chunk *chunks; - /* Number of chunks in chunks array, or -1 if coalesce buffering should not - be performed. */ - long chunk_cnt; -@@ -222,14 +228,14 @@ gomp_coalesce_buf_add (struct gomp_coale - { - if (cbuf->chunk_cnt < 0) - return; -- if (start < cbuf->chunks[2 * cbuf->chunk_cnt - 1]) -+ if (start < cbuf->chunks[cbuf->chunk_cnt - 1].end) - { - cbuf->chunk_cnt = -1; - return; - } -- if (start < cbuf->chunks[2 * cbuf->chunk_cnt - 1] + MAX_COALESCE_BUF_GAP) -+ if (start < cbuf->chunks[cbuf->chunk_cnt - 1].end + MAX_COALESCE_BUF_GAP) - { -- cbuf->chunks[2 * cbuf->chunk_cnt - 1] = start + len; -+ cbuf->chunks[cbuf->chunk_cnt - 1].end = start + len; - cbuf->use_cnt++; - return; - } -@@ -239,8 +245,8 @@ gomp_coalesce_buf_add (struct gomp_coale - if (cbuf->use_cnt == 1) - cbuf->chunk_cnt--; - } -- cbuf->chunks[2 * cbuf->chunk_cnt] = start; -- cbuf->chunks[2 * cbuf->chunk_cnt + 1] = start + len; -+ cbuf->chunks[cbuf->chunk_cnt].start = start; -+ cbuf->chunks[cbuf->chunk_cnt].end = start + len; - cbuf->chunk_cnt++; - cbuf->use_cnt = 1; - } -@@ -271,20 +277,20 @@ gomp_copy_host2dev (struct gomp_device_d - if (cbuf) - { - uintptr_t doff = (uintptr_t) d - cbuf->tgt->tgt_start; -- if (doff < cbuf->chunks[2 * cbuf->chunk_cnt - 1]) -+ if (doff < cbuf->chunks[cbuf->chunk_cnt - 1].end) - { - long first = 0; - long last = cbuf->chunk_cnt - 1; - while (first <= last) - { - long middle = (first + last) >> 1; -- if (cbuf->chunks[2 * middle + 1] <= doff) -+ if (cbuf->chunks[middle].end <= doff) - first = middle + 1; -- else if (cbuf->chunks[2 * middle] <= doff) -+ else if (cbuf->chunks[middle].start <= doff) - { -- if (doff + sz > cbuf->chunks[2 * middle + 1]) -+ if (doff + sz > cbuf->chunks[middle].end) - gomp_fatal ("internal libgomp cbuf error"); -- memcpy ((char *) cbuf->buf + (doff - cbuf->chunks[0]), -+ memcpy ((char *) cbuf->buf + (doff - cbuf->chunks[0].start), - h, sz); - return; - } -@@ -510,8 +516,8 @@ gomp_map_vars (struct gomp_device_descr - cbuf.buf = NULL; - if (mapnum > 1 || pragma_kind == GOMP_MAP_VARS_TARGET) - { -- cbuf.chunks -- = (size_t *) gomp_alloca ((2 * mapnum + 2) * sizeof (size_t)); -+ size_t chunks_size = (mapnum + 1) * sizeof (struct gomp_coalesce_chunk); -+ cbuf.chunks = (struct gomp_coalesce_chunk *) gomp_alloca (chunks_size); - cbuf.chunk_cnt = 0; - } - if (pragma_kind == GOMP_MAP_VARS_TARGET) -@@ -521,8 +527,8 @@ gomp_map_vars (struct gomp_device_descr - tgt_size = mapnum * sizeof (void *); - cbuf.chunk_cnt = 1; - cbuf.use_cnt = 1 + (mapnum > 1); -- cbuf.chunks[0] = 0; -- cbuf.chunks[1] = tgt_size; -+ cbuf.chunks[0].start = 0; -+ cbuf.chunks[0].end = tgt_size; - } - - gomp_mutex_lock (&devicep->lock); -@@ -707,7 +713,7 @@ gomp_map_vars (struct gomp_device_descr - if (cbuf.chunk_cnt > 0) - { - cbuf.buf -- = malloc (cbuf.chunks[2 * cbuf.chunk_cnt - 1] - cbuf.chunks[0]); -+ = malloc (cbuf.chunks[cbuf.chunk_cnt - 1].end - cbuf.chunks[0].start); - if (cbuf.buf) - { - cbuf.tgt = tgt; -@@ -859,6 +865,7 @@ gomp_map_vars (struct gomp_device_descr - tgt->list[i].offset = 0; - tgt->list[i].length = k->host_end - k->host_start; - k->refcount = 1; -+ k->dynamic_refcount = 0; - tgt->refcount++; - array->left = NULL; - array->right = NULL; -@@ -956,9 +963,10 @@ gomp_map_vars (struct gomp_device_descr - /* Set link pointer on target to the device address of the - mapped object. */ - void *tgt_addr = (void *) (tgt->tgt_start + k->tgt_offset); -- devicep->host2dev_func (devicep->target_id, -- (void *) n->tgt_offset, -- &tgt_addr, sizeof (void *)); -+ /* We intentionally do not use coalescing here, as it's not -+ data allocated by the current call to this function. */ -+ gomp_copy_host2dev (devicep, (void *) n->tgt_offset, -+ &tgt_addr, sizeof (void *), NULL); - } - array++; - } -@@ -981,10 +989,14 @@ gomp_map_vars (struct gomp_device_descr - { - long c = 0; - for (c = 0; c < cbuf.chunk_cnt; ++c) -- gomp_copy_host2dev (devicep, (void *) (tgt->tgt_start + cbuf.chunks[2 * c]), -- (char *) cbuf.buf + (cbuf.chunks[2 * c] - cbuf.chunks[0]), -- cbuf.chunks[2 * c + 1] - cbuf.chunks[2 * c], NULL); -+ gomp_copy_host2dev (devicep, -+ (void *) (tgt->tgt_start + cbuf.chunks[c].start), -+ (char *) cbuf.buf + (cbuf.chunks[c].start -+ - cbuf.chunks[0].start), -+ cbuf.chunks[c].end - cbuf.chunks[c].start, NULL); - free (cbuf.buf); -+ cbuf.buf = NULL; -+ cbufp = NULL; - } - - /* If the variable from "omp target enter data" map-list was already mapped, -@@ -1011,6 +1023,23 @@ gomp_unmap_tgt (struct target_mem_desc * - free (tgt); - } - -+attribute_hidden bool -+gomp_remove_var (struct gomp_device_descr *devicep, splay_tree_key k) -+{ -+ bool is_tgt_unmapped = false; -+ splay_tree_remove (&devicep->mem_map, k); -+ if (k->link_key) -+ splay_tree_insert (&devicep->mem_map, (splay_tree_node) k->link_key); -+ if (k->tgt->refcount > 1) -+ k->tgt->refcount--; -+ else -+ { -+ is_tgt_unmapped = true; -+ gomp_unmap_tgt (k->tgt); -+ } -+ return is_tgt_unmapped; -+} -+ - /* Unmap variables described by TGT. If DO_COPYFROM is true, copy relevant - variables back from device to host: if it is false, it is assumed that this - has been done already. */ -@@ -1059,16 +1088,7 @@ gomp_unmap_vars (struct target_mem_desc - + tgt->list[i].offset), - tgt->list[i].length); - if (do_unmap) -- { -- splay_tree_remove (&devicep->mem_map, k); -- if (k->link_key) -- splay_tree_insert (&devicep->mem_map, -- (splay_tree_node) k->link_key); -- if (k->tgt->refcount > 1) -- k->tgt->refcount--; -- else -- gomp_unmap_tgt (k->tgt); -- } -+ gomp_remove_var (devicep, k); - } - - if (tgt->refcount > 1) -@@ -1298,17 +1318,7 @@ gomp_unload_image_from_device (struct go - else - { - splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &k); -- splay_tree_remove (&devicep->mem_map, n); -- if (n->link_key) -- { -- if (n->tgt->refcount > 1) -- n->tgt->refcount--; -- else -- { -- is_tgt_unmapped = true; -- gomp_unmap_tgt (n->tgt); -- } -- } -+ is_tgt_unmapped = gomp_remove_var (devicep, n); - } - } - -@@ -1855,11 +1865,20 @@ GOMP_target_update_ext (int device, size - struct gomp_team *team = thr->ts.team; - /* If parallel or taskgroup has been cancelled, don't start new - tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup -- && thr->task->taskgroup->cancelled))) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } - - gomp_task_maybe_wait_for_dependencies (depend); - } -@@ -1874,10 +1893,20 @@ GOMP_target_update_ext (int device, size - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; - /* If parallel or taskgroup has been cancelled, don't start new tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup && thr->task->taskgroup->cancelled))) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } - - gomp_update (devicep, mapnum, hostaddrs, sizes, kinds, true); - } -@@ -1986,11 +2015,20 @@ GOMP_target_enter_exit_data (int device, - struct gomp_team *team = thr->ts.team; - /* If parallel or taskgroup has been cancelled, don't start new - tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup -- && thr->task->taskgroup->cancelled))) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } - - gomp_task_maybe_wait_for_dependencies (depend); - } -@@ -2005,10 +2043,20 @@ GOMP_target_enter_exit_data (int device, - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; - /* If parallel or taskgroup has been cancelled, don't start new tasks. */ -- if (team -- && (gomp_team_barrier_cancelled (&team->barrier) -- || (thr->task->taskgroup && thr->task->taskgroup->cancelled))) -- return; -+ if (__builtin_expect (gomp_cancel_var, 0) && team) -+ { -+ if (gomp_team_barrier_cancelled (&team->barrier)) -+ return; -+ if (thr->task->taskgroup) -+ { -+ if (thr->task->taskgroup->cancelled) -+ return; -+ if (thr->task->taskgroup->workshare -+ && thr->task->taskgroup->prev -+ && thr->task->taskgroup->prev->cancelled) -+ return; -+ } -+ } - - size_t i; - if ((flags & GOMP_TARGET_FLAG_EXIT_DATA) == 0) -@@ -2197,8 +2245,9 @@ omp_target_is_present (void *ptr, int de - } - - int --omp_target_memcpy (void *dst, void *src, size_t length, size_t dst_offset, -- size_t src_offset, int dst_device_num, int src_device_num) -+omp_target_memcpy (void *dst, void *src, size_t length, -+ size_t dst_offset, size_t src_offset, int dst_device_num, -+ int src_device_num) - { - struct gomp_device_descr *dst_devicep = NULL, *src_devicep = NULL; - bool ret; -@@ -2287,21 +2336,25 @@ omp_target_memcpy_rect_worker (void *dst - return EINVAL; - if (dst_devicep == NULL && src_devicep == NULL) - { -- memcpy ((char *) dst + dst_off, (char *) src + src_off, length); -+ memcpy ((char *) dst + dst_off, (char *) src + src_off, -+ length); - ret = 1; - } - else if (src_devicep == NULL) - ret = dst_devicep->host2dev_func (dst_devicep->target_id, - (char *) dst + dst_off, -- (char *) src + src_off, length); -+ (char *) src + src_off, -+ length); - else if (dst_devicep == NULL) - ret = src_devicep->dev2host_func (src_devicep->target_id, - (char *) dst + dst_off, -- (char *) src + src_off, length); -+ (char *) src + src_off, -+ length); - else if (src_devicep == dst_devicep) - ret = src_devicep->dev2dev_func (src_devicep->target_id, - (char *) dst + dst_off, -- (char *) src + src_off, length); -+ (char *) src + src_off, -+ length); - else - ret = 0; - return ret ? 0 : EINVAL; -@@ -2396,8 +2449,8 @@ omp_target_memcpy_rect (void *dst, void - } - - int --omp_target_associate_ptr (void *host_ptr, void *device_ptr, size_t size, -- size_t device_offset, int device_num) -+omp_target_associate_ptr (void *host_ptr, void *device_ptr, -+ size_t size, size_t device_offset, int device_num) - { - if (device_num == GOMP_DEVICE_HOST_FALLBACK) - return EINVAL; -@@ -2499,6 +2552,31 @@ omp_target_disassociate_ptr (void *ptr, - return ret; - } - -+int -+omp_pause_resource (omp_pause_resource_t kind, int device_num) -+{ -+ (void) kind; -+ if (device_num == GOMP_DEVICE_HOST_FALLBACK) -+ return gomp_pause_host (); -+ if (device_num < 0 || device_num >= gomp_get_num_devices ()) -+ return -1; -+ /* Do nothing for target devices for now. */ -+ return 0; -+} -+ -+int -+omp_pause_resource_all (omp_pause_resource_t kind) -+{ -+ (void) kind; -+ if (gomp_pause_host ()) -+ return -1; -+ /* Do nothing for target devices for now. */ -+ return 0; -+} -+ -+ialias (omp_pause_resource) -+ialias (omp_pause_resource_all) -+ - #ifdef PLUGIN_SUPPORT - - /* This function tries to load a plugin for DEVICE. Name of plugin is passed -@@ -2632,9 +2710,9 @@ gomp_target_fini (void) - } - } - --/* This function initializes the runtime needed for offloading. -- It parses the list of offload targets and tries to load the plugins for -- these targets. On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP -+/* This function initializes the runtime for offloading. -+ It parses the list of offload plugins, and tries to load these. -+ On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP - will be set, and the array DEVICES initialized, containing descriptors for - corresponding devices, first the GOMP_OFFLOAD_CAP_OPENMP_400 ones, follows - by the others. */ -@@ -2651,7 +2729,7 @@ gomp_target_init (void) - num_devices = 0; - devices = NULL; - -- cur = OFFLOAD_TARGETS; -+ cur = OFFLOAD_PLUGINS; - if (*cur) - do - { ---- libgomp/ordered.c.jj 2018-04-25 09:40:31.926655587 +0200 -+++ libgomp/ordered.c 2019-05-07 18:46:36.532109640 +0200 -@@ -259,7 +259,8 @@ GOMP_ordered_end (void) - #define MAX_COLLAPSED_BITS (__SIZEOF_LONG__ * __CHAR_BIT__) - - void --gomp_doacross_init (unsigned ncounts, long *counts, long chunk_size) -+gomp_doacross_init (unsigned ncounts, long *counts, long chunk_size, -+ size_t extra) - { - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; -@@ -269,13 +270,24 @@ gomp_doacross_init (unsigned ncounts, lo - struct gomp_doacross_work_share *doacross; - - if (team == NULL || team->nthreads == 1) -- return; -+ { -+ empty: -+ if (!extra) -+ ws->doacross = NULL; -+ else -+ { -+ doacross = gomp_malloc_cleared (sizeof (*doacross) + extra); -+ doacross->extra = (void *) (doacross + 1); -+ ws->doacross = doacross; -+ } -+ return; -+ } - - for (i = 0; i < ncounts; i++) - { - /* If any count is 0, GOMP_doacross_{post,wait} can't be called. */ - if (counts[i] == 0) -- return; -+ goto empty; - - if (num_bits <= MAX_COLLAPSED_BITS) - { -@@ -314,7 +326,7 @@ gomp_doacross_init (unsigned ncounts, lo - elt_sz = (elt_sz + 63) & ~63UL; - - doacross = gomp_malloc (sizeof (*doacross) + 63 + num_ents * elt_sz -- + shift_sz); -+ + shift_sz + extra); - doacross->chunk_size = chunk_size; - doacross->elt_sz = elt_sz; - doacross->ncounts = ncounts; -@@ -322,6 +334,13 @@ gomp_doacross_init (unsigned ncounts, lo - doacross->array = (unsigned char *) - ((((uintptr_t) (doacross + 1)) + 63 + shift_sz) - & ~(uintptr_t) 63); -+ if (extra) -+ { -+ doacross->extra = doacross->array + num_ents * elt_sz; -+ memset (doacross->extra, '\0', extra); -+ } -+ else -+ doacross->extra = NULL; - if (num_bits <= MAX_COLLAPSED_BITS) - { - unsigned int shift_count = 0; -@@ -360,7 +379,8 @@ GOMP_doacross_post (long *counts) - unsigned long ent; - unsigned int i; - -- if (__builtin_expect (doacross == NULL, 0)) -+ if (__builtin_expect (doacross == NULL, 0) -+ || __builtin_expect (doacross->array == NULL, 0)) - { - __sync_synchronize (); - return; -@@ -411,7 +431,8 @@ GOMP_doacross_wait (long first, ...) - unsigned long ent; - unsigned int i; - -- if (__builtin_expect (doacross == NULL, 0)) -+ if (__builtin_expect (doacross == NULL, 0) -+ || __builtin_expect (doacross->array == NULL, 0)) - { - __sync_synchronize (); - return; -@@ -488,7 +509,8 @@ GOMP_doacross_wait (long first, ...) - typedef unsigned long long gomp_ull; - - void --gomp_doacross_ull_init (unsigned ncounts, gomp_ull *counts, gomp_ull chunk_size) -+gomp_doacross_ull_init (unsigned ncounts, gomp_ull *counts, -+ gomp_ull chunk_size, size_t extra) - { - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; -@@ -498,13 +520,24 @@ gomp_doacross_ull_init (unsigned ncounts - struct gomp_doacross_work_share *doacross; - - if (team == NULL || team->nthreads == 1) -- return; -+ { -+ empty: -+ if (!extra) -+ ws->doacross = NULL; -+ else -+ { -+ doacross = gomp_malloc_cleared (sizeof (*doacross) + extra); -+ doacross->extra = (void *) (doacross + 1); -+ ws->doacross = doacross; -+ } -+ return; -+ } - - for (i = 0; i < ncounts; i++) - { - /* If any count is 0, GOMP_doacross_{post,wait} can't be called. */ - if (counts[i] == 0) -- return; -+ goto empty; - - if (num_bits <= MAX_COLLAPSED_BITS) - { -@@ -557,6 +590,13 @@ gomp_doacross_ull_init (unsigned ncounts - doacross->array = (unsigned char *) - ((((uintptr_t) (doacross + 1)) + 63 + shift_sz) - & ~(uintptr_t) 63); -+ if (extra) -+ { -+ doacross->extra = doacross->array + num_ents * elt_sz; -+ memset (doacross->extra, '\0', extra); -+ } -+ else -+ doacross->extra = NULL; - if (num_bits <= MAX_COLLAPSED_BITS) - { - unsigned int shift_count = 0; -@@ -595,7 +635,8 @@ GOMP_doacross_ull_post (gomp_ull *counts - unsigned long ent; - unsigned int i; - -- if (__builtin_expect (doacross == NULL, 0)) -+ if (__builtin_expect (doacross == NULL, 0) -+ || __builtin_expect (doacross->array == NULL, 0)) - { - __sync_synchronize (); - return; -@@ -667,7 +708,8 @@ GOMP_doacross_ull_wait (gomp_ull first, - unsigned long ent; - unsigned int i; - -- if (__builtin_expect (doacross == NULL, 0)) -+ if (__builtin_expect (doacross == NULL, 0) -+ || __builtin_expect (doacross->array == NULL, 0)) - { - __sync_synchronize (); - return; ---- libgomp/alloc.c.jj 2018-04-25 09:40:31.926655587 +0200 -+++ libgomp/alloc.c 2019-05-07 18:46:36.336112770 +0200 -@@ -57,3 +57,50 @@ gomp_realloc (void *old, size_t size) - gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size); - return ret; - } -+ -+void * -+gomp_aligned_alloc (size_t al, size_t size) -+{ -+ void *ret; -+ if (al < sizeof (void *)) -+ al = sizeof (void *); -+#ifdef HAVE_ALIGNED_ALLOC -+ ret = aligned_alloc (al, size); -+#elif defined(HAVE__ALIGNED_MALLOC) -+ ret = _aligned_malloc (size, al); -+#elif defined(HAVE_POSIX_MEMALIGN) -+ if (posix_memalign (&ret, al, size) != 0) -+ ret = NULL; -+#elif defined(HAVE_MEMALIGN) -+ { -+ extern void *memalign (size_t, size_t); -+ ret = memalign (al, size); -+ } -+#else -+ ret = NULL; -+ if ((al & (al - 1)) == 0 && size) -+ { -+ void *p = malloc (size + al); -+ if (p) -+ { -+ void *ap = (void *) (((uintptr_t) p + al) & -al); -+ ((void **) ap)[-1] = p; -+ ret = ap; -+ } -+ } -+#endif -+ if (ret == NULL) -+ gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size); -+ return ret; -+} -+ -+void -+gomp_aligned_free (void *ptr) -+{ -+#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC -+ free (ptr); -+#else -+ if (ptr) -+ free (((void **) ptr)[-1]); -+#endif -+} ---- libgomp/configure.ac.jj 2018-04-25 09:40:31.321655307 +0200 -+++ libgomp/configure.ac 2019-05-07 18:46:36.471110614 +0200 -@@ -219,6 +219,7 @@ m4_include([plugin/configfrag.ac]) - - # Check for functions needed. - AC_CHECK_FUNCS(getloadavg clock_gettime strtoull) -+AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc) - - # Check for broken semaphore implementation on darwin. - # sem_init returns: sem_init error: Function not implemented. -@@ -266,6 +267,41 @@ if test $ac_cv_func_clock_gettime = no; - [Define to 1 if you have the `clock_gettime' function.])]) - fi - -+# Check for uname. -+AC_COMPILE_IFELSE( -+ [AC_LANG_PROGRAM( -+ [#include -+ #include -+ #include ], -+ [struct utsname buf; -+ volatile size_t len = 0; -+ if (!uname (buf)) -+ len = strlen (buf.nodename);])], -+ AC_DEFINE(HAVE_UNAME, 1, -+[ Define if uname is supported and struct utsname has nodename field.])) -+ -+# Check for gethostname. -+AC_COMPILE_IFELSE( -+ [AC_LANG_PROGRAM( -+ [#include ], -+ [ -+changequote(,)dnl -+ char buf[256]; -+ if (gethostname (buf, sizeof (buf) - 1) == 0) -+ buf[255] = '\0'; -+changequote([,])dnl -+ ])], -+ AC_DEFINE(HAVE_GETHOSTNAME, 1, -+[ Define if gethostname is supported.])) -+ -+# Check for getpid. -+AC_COMPILE_IFELSE( -+ [AC_LANG_PROGRAM( -+ [#include ], -+ [int pid = getpid ();])], -+ AC_DEFINE(HAVE_GETPID, 1, -+[ Define if getpid is supported.])) -+ - # See if we support thread-local storage. - GCC_CHECK_TLS - ---- libgomp/icv.c.jj 2018-04-25 09:40:31.870655561 +0200 -+++ libgomp/icv.c 2019-05-07 18:46:36.501110134 +0200 -@@ -69,7 +69,7 @@ void - omp_set_schedule (omp_sched_t kind, int chunk_size) - { - struct gomp_task_icv *icv = gomp_icv (true); -- switch (kind) -+ switch (kind & ~omp_sched_monotonic) - { - case omp_sched_static: - if (chunk_size < 1) ---- libgomp/configure.jj 2018-04-25 09:40:31.913655581 +0200 -+++ libgomp/configure 2019-05-07 18:47:37.961128420 +0200 -@@ -636,6 +636,8 @@ PLUGIN_NVPTX_FALSE - PLUGIN_NVPTX_TRUE - offload_additional_lib_paths - offload_additional_options -+offload_targets -+offload_plugins - PLUGIN_HSA_LIBS - PLUGIN_HSA_LDFLAGS - PLUGIN_HSA_CPPFLAGS -@@ -648,7 +650,6 @@ PLUGIN_NVPTX_CPPFLAGS - PLUGIN_NVPTX - CUDA_DRIVER_LIB - CUDA_DRIVER_INCLUDE --offload_targets - libtool_VERSION - ac_ct_FC - FCFLAGS -@@ -11157,7 +11158,7 @@ else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF --#line 11160 "configure" -+#line 11161 "configure" - #include "confdefs.h" - - #if HAVE_DLFCN_H -@@ -11263,7 +11264,7 @@ else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF --#line 11266 "configure" -+#line 11267 "configure" - #include "confdefs.h" - - #if HAVE_DLFCN_H -@@ -15167,8 +15168,6 @@ fi - # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - # . - --offload_targets= -- - plugin_support=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5 - $as_echo_n "checking for dlsym in -ldl... " >&6; } -@@ -15302,7 +15301,11 @@ if test "${with_cuda_driver_lib+set}" = - fi - - case "x$with_cuda_driver" in -- x | xno) ;; -+ x) ;; -+ xno) -+ CUDA_DRIVER_INCLUDE=no -+ CUDA_DRIVER_LIB=no -+ ;; - *) CUDA_DRIVER_INCLUDE=$with_cuda_driver/include - CUDA_DRIVER_LIB=$with_cuda_driver/lib - ;; -@@ -15313,10 +15316,12 @@ fi - if test "x$with_cuda_driver_lib" != x; then - CUDA_DRIVER_LIB=$with_cuda_driver_lib - fi --if test "x$CUDA_DRIVER_INCLUDE" != x; then -+if test "x$CUDA_DRIVER_INCLUDE" != x \ -+ && test "x$CUDA_DRIVER_INCLUDE" != xno; then - CUDA_DRIVER_CPPFLAGS=-I$CUDA_DRIVER_INCLUDE - fi --if test "x$CUDA_DRIVER_LIB" != x; then -+if test "x$CUDA_DRIVER_LIB" != x \ -+ && test "x$CUDA_DRIVER_LIB" != xno; then - CUDA_DRIVER_LDFLAGS=-L$CUDA_DRIVER_LIB - fi - -@@ -15383,7 +15388,13 @@ PLUGIN_HSA_LIBS= - - - --# Get offload targets and path to install tree of offloading compiler. -+# Parse '--enable-offload-targets', figure out the corresponding libgomp -+# plugins, and configure to find the corresponding offload compilers. -+# 'offload_plugins' and 'offload_targets' will be populated in the same order. -+offload_plugins= -+offload_targets= -+ -+ - offload_additional_options= - offload_additional_lib_paths= - -@@ -15403,10 +15403,10 @@ if test x"$enable_offload_targets" != x; - for tgt in `echo $enable_offload_targets | sed -e 's#,# #g'`; do - tgt_dir=`echo $tgt | grep '=' | sed 's/.*=//'` - tgt=`echo $tgt | sed 's/=.*//'` -- tgt_name= -+ tgt_plugin= - case $tgt in - *-intelmic-* | *-intelmicemul-*) -- tgt_name=intelmic -+ tgt_plugin=intelmic - ;; - nvptx*) - case "${target}" in -@@ -15418,19 +15418,21 @@ if test x"$enable_offload_targets" != x; - PLUGIN_NVPTX=0 - ;; - *) -- tgt_name=nvptx -+ tgt_plugin=nvptx - PLUGIN_NVPTX=$tgt -- PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS -- PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS -- PLUGIN_NVPTX_LIBS='-lcuda' -+ if test "x$CUDA_DRIVER_LIB" != xno \ -+ && test "x$CUDA_DRIVER_LIB" != xno; then -+ PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS -+ PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS -+ PLUGIN_NVPTX_LIBS='-lcuda' - -- PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS -- CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS" -- PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS -- LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS" -- PLUGIN_NVPTX_save_LIBS=$LIBS -- LIBS="$PLUGIN_NVPTX_LIBS $LIBS" -- cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+ PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS -+ CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS" -+ PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS -+ LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS" -+ PLUGIN_NVPTX_save_LIBS=$LIBS -+ LIBS="$PLUGIN_NVPTX_LIBS $LIBS" -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #include "cuda.h" - int -@@ -15446,13 +15448,16 @@ if ac_fn_c_try_link "$LINENO"; then : - fi - rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -- CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS -- LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS -- LIBS=$PLUGIN_NVPTX_save_LIBS -+ CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS -+ LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS -+ LIBS=$PLUGIN_NVPTX_save_LIBS -+ fi - case $PLUGIN_NVPTX in - nvptx*) -- if test "x$CUDA_DRIVER_INCLUDE" = x \ -- && test "x$CUDA_DRIVER_LIB" = x; then -+ if (test "x$CUDA_DRIVER_INCLUDE" = x \ -+ || test "x$CUDA_DRIVER_INCLUDE" = xno) \ -+ && (test "x$CUDA_DRIVER_LIB" = x \ -+ || test "x$CUDA_DRIVER_LIB" = xno); then - PLUGIN_NVPTX=1 - PLUGIN_NVPTX_CPPFLAGS='-I$(srcdir)/plugin/cuda' - PLUGIN_NVPTX_LIBS='-ldl' -@@ -15452,7 +15468,7 @@ rm -f core conftest.err conftest.$ac_obj - PLUGIN_HSA=0 - ;; - *) -- tgt_name=hsa -+ tgt_plugin=hsa - PLUGIN_HSA=$tgt - PLUGIN_HSA_CPPFLAGS=$HSA_RUNTIME_CPPFLAGS - PLUGIN_HSA_LDFLAGS="$HSA_RUNTIME_LDFLAGS" -@@ -15470,7 +15486,7 @@ rm -f core conftest.err conftest.$ac_obj - LDFLAGS=$PLUGIN_HSA_save_LDFLAGS - LIBS=$PLUGIN_HSA_save_LIBS - case $PLUGIN_HSA in -- hsa*) -+ hsa*) - HSA_PLUGIN=0 - as_fn_error "HSA run-time package required for HSA support" "$LINENO" 5 - ;; -@@ -15487,16 +15503,19 @@ rm -f core conftest.err conftest.$ac_obj - as_fn_error "unknown offload target specified" "$LINENO" 5 - ;; - esac -- if test x"$tgt_name" = x; then -- # Don't configure libgomp for this offloading target if we don't build -- # the corresponding plugin. -+ if test x"$tgt_plugin" = x; then -+ # Not configuring libgomp for this offload target if we're not building -+ # the corresponding offload plugin. - continue -- elif test x"$offload_targets" = x; then -- offload_targets=$tgt_name -+ elif test x"$offload_plugins" = x; then -+ offload_plugins=$tgt_plugin -+ offload_targets=$tgt - else -- offload_targets=$offload_targets,$tgt_name -+ offload_plugins=$offload_plugins,$tgt_plugin -+ offload_targets=$offload_targets,$tgt - fi -- if test "$tgt_name" = hsa; then -+ # Configure additional search paths. -+ if test "$tgt_plugin" = hsa; then - # Offloading compilation is all handled by the target compiler. - : - elif test x"$tgt_dir" != x; then -@@ -15510,7 +15529,7 @@ rm -f core conftest.err conftest.$ac_obj - fi - - cat >>confdefs.h <<_ACEOF --#define OFFLOAD_TARGETS "$offload_targets" -+#define OFFLOAD_PLUGINS "$offload_plugins" - _ACEOF - - if test $PLUGIN_NVPTX = 1; then -@@ -15570,6 +15589,19 @@ _ACEOF - fi - done - -+for ac_func in aligned_alloc posix_memalign memalign _aligned_malloc -+do : -+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -+eval as_val=\$$as_ac_var -+ if test "x$as_val" = x""yes; then : -+ cat >>confdefs.h <<_ACEOF -+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -+_ACEOF -+ -+fi -+done -+ - - # Check for broken semaphore implementation on darwin. - # sem_init returns: sem_init error: Function not implemented. -@@ -15784,6 +15816,72 @@ fi - - fi - -+# Check for uname. -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+#include -+ #include -+ #include -+int -+main () -+{ -+struct utsname buf; -+ volatile size_t len = 0; -+ if (!uname (buf)) -+ len = strlen (buf.nodename); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ -+$as_echo "#define HAVE_UNAME 1" >>confdefs.h -+ -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ -+# Check for gethostname. -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+#include -+int -+main () -+{ -+ -+ char buf[256]; -+ if (gethostname (buf, sizeof (buf) - 1) == 0) -+ buf[255] = '\0'; -+ -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ -+$as_echo "#define HAVE_GETHOSTNAME 1" >>confdefs.h -+ -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ -+# Check for getpid. -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+#include -+int -+main () -+{ -+int pid = getpid (); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ -+$as_echo "#define HAVE_GETPID 1" >>confdefs.h -+ -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ - # See if we support thread-local storage. - - ---- libgomp/Makefile.am.jj 2018-04-25 09:40:31.926655587 +0200 -+++ libgomp/Makefile.am 2019-05-07 19:59:03.683989317 +0200 -@@ -63,12 +63,13 @@ libgomp_la_SOURCES = alloc.c atomic.c ba - parallel.c sections.c single.c task.c team.c work.c lock.c mutex.c \ - proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c target.c \ - splay-tree.c libgomp-plugin.c oacc-parallel.c oacc-host.c oacc-init.c \ -- oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c -+ oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \ -+ affinity-fmt.c teams.c - - include $(top_srcdir)/plugin/Makefrag.am - - if USE_FORTRAN --libgomp_la_SOURCES += openacc.f90 -+libgomp_la_SOURCES += openacc2.f90 - endif - - nodist_noinst_HEADERS = libgomp_f.h -@@ -87,8 +88,6 @@ omp_lib_kinds.mod: omp_lib.mod - : - openacc_kinds.mod: openacc.mod - : --openacc.mod: openacc.lo -- : - %.mod: %.f90 - $(FC) $(FCFLAGS) -fsyntax-only $< - fortran.lo: libgomp_f.h ---- libgomp/oacc-mem.c.jj 2018-04-25 09:40:31.924655586 +0200 -+++ libgomp/oacc-mem.c 2019-05-07 18:46:36.530109672 +0200 -@@ -153,8 +153,9 @@ acc_free (void *d) - gomp_fatal ("error in freeing device memory in %s", __FUNCTION__); - } - --void --acc_memcpy_to_device (void *d, void *h, size_t s) -+static void -+memcpy_tofrom_device (bool from, void *d, void *h, size_t s, int async, -+ const char *libfnname) - { - /* No need to call lazy open here, as the device pointer must have - been obtained from a routine that did that. */ -@@ -164,31 +165,49 @@ acc_memcpy_to_device (void *d, void *h, - - if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) - { -- memmove (d, h, s); -+ if (from) -+ memmove (h, d, s); -+ else -+ memmove (d, h, s); - return; - } - -- if (!thr->dev->host2dev_func (thr->dev->target_id, d, h, s)) -- gomp_fatal ("error in %s", __FUNCTION__); -+ if (async > acc_async_sync) -+ thr->dev->openacc.async_set_async_func (async); -+ -+ bool ret = (from -+ ? thr->dev->dev2host_func (thr->dev->target_id, h, d, s) -+ : thr->dev->host2dev_func (thr->dev->target_id, d, h, s)); -+ -+ if (async > acc_async_sync) -+ thr->dev->openacc.async_set_async_func (acc_async_sync); -+ -+ if (!ret) -+ gomp_fatal ("error in %s", libfnname); - } - - void --acc_memcpy_from_device (void *h, void *d, size_t s) -+acc_memcpy_to_device (void *d, void *h, size_t s) - { -- /* No need to call lazy open here, as the device pointer must have -- been obtained from a routine that did that. */ -- struct goacc_thread *thr = goacc_thread (); -+ memcpy_tofrom_device (false, d, h, s, acc_async_sync, __FUNCTION__); -+} - -- assert (thr && thr->dev); -+void -+acc_memcpy_to_device_async (void *d, void *h, size_t s, int async) -+{ -+ memcpy_tofrom_device (false, d, h, s, async, __FUNCTION__); -+} - -- if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) -- { -- memmove (h, d, s); -- return; -- } -+void -+acc_memcpy_from_device (void *h, void *d, size_t s) -+{ -+ memcpy_tofrom_device (true, d, h, s, acc_async_sync, __FUNCTION__); -+} - -- if (!thr->dev->dev2host_func (thr->dev->target_id, h, d, s)) -- gomp_fatal ("error in %s", __FUNCTION__); -+void -+acc_memcpy_from_device_async (void *h, void *d, size_t s, int async) -+{ -+ memcpy_tofrom_device (true, d, h, s, async, __FUNCTION__); - } - - /* Return the device pointer that corresponds to host data H. Or NULL -@@ -347,6 +366,7 @@ acc_map_data (void *h, void *d, size_t s - - tgt = gomp_map_vars (acc_dev, mapnum, &hostaddrs, &devaddrs, &sizes, - &kinds, true, GOMP_MAP_VARS_OPENACC); -+ tgt->list[0].key->refcount = REFCOUNT_INFINITY; - } - - gomp_mutex_lock (&acc_dev->lock); -@@ -389,6 +409,9 @@ acc_unmap_data (void *h) - (void *) n->host_start, (int) host_size, (void *) h); - } - -+ /* Mark for removal. */ -+ n->refcount = 1; -+ - t = n->tgt; - - if (t->refcount == 2) -@@ -424,7 +447,7 @@ acc_unmap_data (void *h) - #define FLAG_COPY (1 << 2) - - static void * --present_create_copy (unsigned f, void *h, size_t s) -+present_create_copy (unsigned f, void *h, size_t s, int async) - { - void *d; - splay_tree_key n; -@@ -460,6 +483,11 @@ present_create_copy (unsigned f, void *h - gomp_fatal ("[%p,+%d] not mapped", (void *)h, (int)s); - } - -+ if (n->refcount != REFCOUNT_INFINITY) -+ { -+ n->refcount++; -+ n->dynamic_refcount++; -+ } - gomp_mutex_unlock (&acc_dev->lock); - } - else if (!(f & FLAG_CREATE)) -@@ -481,8 +509,16 @@ present_create_copy (unsigned f, void *h - - gomp_mutex_unlock (&acc_dev->lock); - -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (async); -+ - tgt = gomp_map_vars (acc_dev, mapnum, &hostaddrs, NULL, &s, &kinds, true, - GOMP_MAP_VARS_OPENACC); -+ /* Initialize dynamic refcount. */ -+ tgt->list[0].key->dynamic_refcount = 1; -+ -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (acc_async_sync); - - gomp_mutex_lock (&acc_dev->lock); - -@@ -499,53 +535,71 @@ present_create_copy (unsigned f, void *h - void * - acc_create (void *h, size_t s) - { -- return present_create_copy (FLAG_CREATE, h, s); -+ return present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s, acc_async_sync); - } - --void * --acc_copyin (void *h, size_t s) -+void -+acc_create_async (void *h, size_t s, int async) - { -- return present_create_copy (FLAG_CREATE | FLAG_COPY, h, s); -+ present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s, async); - } - -+/* acc_present_or_create used to be what acc_create is now. */ -+/* acc_pcreate is acc_present_or_create by a different name. */ -+#ifdef HAVE_ATTRIBUTE_ALIAS -+strong_alias (acc_create, acc_present_or_create) -+strong_alias (acc_create, acc_pcreate) -+#else - void * - acc_present_or_create (void *h, size_t s) - { -- return present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s); -+ return acc_create (h, s); - } - --/* acc_pcreate is acc_present_or_create by a different name. */ --#ifdef HAVE_ATTRIBUTE_ALIAS --strong_alias (acc_present_or_create, acc_pcreate) --#else - void * - acc_pcreate (void *h, size_t s) - { -- return acc_present_or_create (h, s); -+ return acc_create (h, s); - } - #endif - - void * --acc_present_or_copyin (void *h, size_t s) -+acc_copyin (void *h, size_t s) -+{ -+ return present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s, -+ acc_async_sync); -+} -+ -+void -+acc_copyin_async (void *h, size_t s, int async) - { -- return present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s); -+ present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s, async); - } - -+/* acc_present_or_copyin used to be what acc_copyin is now. */ - /* acc_pcopyin is acc_present_or_copyin by a different name. */ - #ifdef HAVE_ATTRIBUTE_ALIAS --strong_alias (acc_present_or_copyin, acc_pcopyin) -+strong_alias (acc_copyin, acc_present_or_copyin) -+strong_alias (acc_copyin, acc_pcopyin) - #else - void * -+acc_present_or_copyin (void *h, size_t s) -+{ -+ return acc_copyin (h, s); -+} -+ -+void * - acc_pcopyin (void *h, size_t s) - { -- return acc_present_or_copyin (h, s); -+ return acc_copyin (h, s); - } - #endif - --#define FLAG_COPYOUT (1 << 0) -+#define FLAG_COPYOUT (1 << 0) -+#define FLAG_FINALIZE (1 << 1) - - static void --delete_copyout (unsigned f, void *h, size_t s, const char *libfnname) -+delete_copyout (unsigned f, void *h, size_t s, int async, const char *libfnname) - { - size_t host_size; - splay_tree_key n; -@@ -581,31 +635,111 @@ delete_copyout (unsigned f, void *h, siz - (void *) n->host_start, (int) host_size, (void *) h, (int) s); - } - -- gomp_mutex_unlock (&acc_dev->lock); -+ if (n->refcount == REFCOUNT_INFINITY) -+ { -+ n->refcount = 0; -+ n->dynamic_refcount = 0; -+ } -+ if (n->refcount < n->dynamic_refcount) -+ { -+ gomp_mutex_unlock (&acc_dev->lock); -+ gomp_fatal ("Dynamic reference counting assert fail\n"); -+ } - -- if (f & FLAG_COPYOUT) -- acc_dev->dev2host_func (acc_dev->target_id, h, d, s); -+ if (f & FLAG_FINALIZE) -+ { -+ n->refcount -= n->dynamic_refcount; -+ n->dynamic_refcount = 0; -+ } -+ else if (n->dynamic_refcount) -+ { -+ n->dynamic_refcount--; -+ n->refcount--; -+ } -+ -+ if (n->refcount == 0) -+ { -+ if (n->tgt->refcount == 2) -+ { -+ struct target_mem_desc *tp, *t; -+ for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL; -+ tp = t, t = t->prev) -+ if (n->tgt == t) -+ { -+ if (tp) -+ tp->prev = t->prev; -+ else -+ acc_dev->openacc.data_environ = t->prev; -+ break; -+ } -+ } -+ -+ if (f & FLAG_COPYOUT) -+ { -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (async); -+ acc_dev->dev2host_func (acc_dev->target_id, h, d, s); -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (acc_async_sync); -+ } - -- acc_unmap_data (h); -+ gomp_remove_var (acc_dev, n); -+ } - -- if (!acc_dev->free_func (acc_dev->target_id, d)) -- gomp_fatal ("error in freeing device memory in %s", libfnname); -+ gomp_mutex_unlock (&acc_dev->lock); - } - - void - acc_delete (void *h , size_t s) - { -- delete_copyout (0, h, s, __FUNCTION__); -+ delete_copyout (0, h, s, acc_async_sync, __FUNCTION__); -+} -+ -+void -+acc_delete_async (void *h , size_t s, int async) -+{ -+ delete_copyout (0, h, s, async, __FUNCTION__); -+} -+ -+void -+acc_delete_finalize (void *h , size_t s) -+{ -+ delete_copyout (FLAG_FINALIZE, h, s, acc_async_sync, __FUNCTION__); -+} -+ -+void -+acc_delete_finalize_async (void *h , size_t s, int async) -+{ -+ delete_copyout (FLAG_FINALIZE, h, s, async, __FUNCTION__); - } - - void - acc_copyout (void *h, size_t s) - { -- delete_copyout (FLAG_COPYOUT, h, s, __FUNCTION__); -+ delete_copyout (FLAG_COPYOUT, h, s, acc_async_sync, __FUNCTION__); -+} -+ -+void -+acc_copyout_async (void *h, size_t s, int async) -+{ -+ delete_copyout (FLAG_COPYOUT, h, s, async, __FUNCTION__); -+} -+ -+void -+acc_copyout_finalize (void *h, size_t s) -+{ -+ delete_copyout (FLAG_COPYOUT | FLAG_FINALIZE, h, s, acc_async_sync, -+ __FUNCTION__); -+} -+ -+void -+acc_copyout_finalize_async (void *h, size_t s, int async) -+{ -+ delete_copyout (FLAG_COPYOUT | FLAG_FINALIZE, h, s, async, __FUNCTION__); - } - - static void --update_dev_host (int is_dev, void *h, size_t s) -+update_dev_host (int is_dev, void *h, size_t s, int async) - { - splay_tree_key n; - void *d; -@@ -631,24 +765,42 @@ update_dev_host (int is_dev, void *h, si - d = (void *) (n->tgt->tgt_start + n->tgt_offset - + (uintptr_t) h - n->host_start); - -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (async); -+ - if (is_dev) - acc_dev->host2dev_func (acc_dev->target_id, d, h, s); - else - acc_dev->dev2host_func (acc_dev->target_id, h, d, s); - -+ if (async > acc_async_sync) -+ acc_dev->openacc.async_set_async_func (acc_async_sync); -+ - gomp_mutex_unlock (&acc_dev->lock); - } - - void - acc_update_device (void *h, size_t s) - { -- update_dev_host (1, h, s); -+ update_dev_host (1, h, s, acc_async_sync); -+} -+ -+void -+acc_update_device_async (void *h, size_t s, int async) -+{ -+ update_dev_host (1, h, s, async); - } - - void - acc_update_self (void *h, size_t s) - { -- update_dev_host (0, h, s); -+ update_dev_host (0, h, s, acc_async_sync); -+} -+ -+void -+acc_update_self_async (void *h, size_t s, int async) -+{ -+ update_dev_host (0, h, s, async); - } - - void -@@ -659,11 +811,37 @@ gomp_acc_insert_pointer (size_t mapnum, - struct goacc_thread *thr = goacc_thread (); - struct gomp_device_descr *acc_dev = thr->dev; - -+ if (acc_is_present (*hostaddrs, *sizes)) -+ { -+ splay_tree_key n; -+ gomp_mutex_lock (&acc_dev->lock); -+ n = lookup_host (acc_dev, *hostaddrs, *sizes); -+ gomp_mutex_unlock (&acc_dev->lock); -+ -+ tgt = n->tgt; -+ for (size_t i = 0; i < tgt->list_count; i++) -+ if (tgt->list[i].key == n) -+ { -+ for (size_t j = 0; j < mapnum; j++) -+ if (i + j < tgt->list_count && tgt->list[i + j].key) -+ { -+ tgt->list[i + j].key->refcount++; -+ tgt->list[i + j].key->dynamic_refcount++; -+ } -+ return; -+ } -+ /* Should not reach here. */ -+ gomp_fatal ("Dynamic refcount incrementing failed for pointer/pset"); -+ } -+ - gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__); - tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, - NULL, sizes, kinds, true, GOMP_MAP_VARS_OPENACC); - gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__); - -+ /* Initialize dynamic refcount. */ -+ tgt->list[0].key->dynamic_refcount = 1; -+ - gomp_mutex_lock (&acc_dev->lock); - tgt->prev = acc_dev->openacc.data_environ; - acc_dev->openacc.data_environ = tgt; -@@ -671,7 +849,8 @@ gomp_acc_insert_pointer (size_t mapnum, - } - - void --gomp_acc_remove_pointer (void *h, bool force_copyfrom, int async, int mapnum) -+gomp_acc_remove_pointer (void *h, size_t s, bool force_copyfrom, int async, -+ int finalize, int mapnum) - { - struct goacc_thread *thr = goacc_thread (); - struct gomp_device_descr *acc_dev = thr->dev; -@@ -679,6 +858,9 @@ gomp_acc_remove_pointer (void *h, bool f - struct target_mem_desc *t; - int minrefs = (mapnum == 1) ? 2 : 3; - -+ if (!acc_is_present (h, s)) -+ return; -+ - gomp_mutex_lock (&acc_dev->lock); - - n = lookup_host (acc_dev, h, 1); -@@ -693,40 +875,65 @@ gomp_acc_remove_pointer (void *h, bool f - - t = n->tgt; - -- struct target_mem_desc *tp; -+ if (n->refcount < n->dynamic_refcount) -+ { -+ gomp_mutex_unlock (&acc_dev->lock); -+ gomp_fatal ("Dynamic reference counting assert fail\n"); -+ } - -- if (t->refcount == minrefs) -+ if (finalize) - { -- /* This is the last reference, so pull the descriptor off the -- chain. This avoids gomp_unmap_vars via gomp_unmap_tgt from -- freeing the device memory. */ -- t->tgt_end = 0; -- t->to_free = 0; -+ n->refcount -= n->dynamic_refcount; -+ n->dynamic_refcount = 0; -+ } -+ else if (n->dynamic_refcount) -+ { -+ n->dynamic_refcount--; -+ n->refcount--; -+ } - -- for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL; -- tp = t, t = t->prev) -+ gomp_mutex_unlock (&acc_dev->lock); -+ -+ if (n->refcount == 0) -+ { -+ if (t->refcount == minrefs) - { -- if (n->tgt == t) -+ /* This is the last reference, so pull the descriptor off the -+ chain. This prevents gomp_unmap_vars via gomp_unmap_tgt from -+ freeing the device memory. */ -+ struct target_mem_desc *tp; -+ for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL; -+ tp = t, t = t->prev) - { -- if (tp) -- tp->prev = t->prev; -- else -- acc_dev->openacc.data_environ = t->prev; -- break; -+ if (n->tgt == t) -+ { -+ if (tp) -+ tp->prev = t->prev; -+ else -+ acc_dev->openacc.data_environ = t->prev; -+ break; -+ } - } - } -- } - -- if (force_copyfrom) -- t->list[0].copy_from = 1; -+ /* Set refcount to 1 to allow gomp_unmap_vars to unmap it. */ -+ n->refcount = 1; -+ t->refcount = minrefs; -+ for (size_t i = 0; i < t->list_count; i++) -+ if (t->list[i].key == n) -+ { -+ t->list[i].copy_from = force_copyfrom ? 1 : 0; -+ break; -+ } - -- gomp_mutex_unlock (&acc_dev->lock); -+ /* If running synchronously, unmap immediately. */ -+ if (async < acc_async_noval) -+ gomp_unmap_vars (t, true); -+ else -+ t->device_descr->openacc.register_async_cleanup_func (t, async); -+ } - -- /* If running synchronously, unmap immediately. */ -- if (async < acc_async_noval) -- gomp_unmap_vars (t, true); -- else -- t->device_descr->openacc.register_async_cleanup_func (t, async); -+ gomp_mutex_unlock (&acc_dev->lock); - - gomp_debug (0, " %s: mappings restored\n", __FUNCTION__); - } ---- libgomp/env.c.jj 2018-04-25 09:40:31.924655586 +0200 -+++ libgomp/env.c 2019-05-07 18:46:36.482110438 +0200 -@@ -88,8 +88,12 @@ void **gomp_places_list; - unsigned long gomp_places_list_len; - int gomp_debug_var; - unsigned int gomp_num_teams_var; -+bool gomp_display_affinity_var; -+char *gomp_affinity_format_var = "level %L thread %i affinity %A"; -+size_t gomp_affinity_format_len; - char *goacc_device_type; - int goacc_device_num; -+int goacc_default_dims[GOMP_DIM_MAX]; - - #ifndef LIBGOMP_OFFLOADED_ONLY - -@@ -100,6 +104,7 @@ parse_schedule (void) - { - char *env, *end; - unsigned long value; -+ int monotonic = 0; - - env = getenv ("OMP_SCHEDULE"); - if (env == NULL) -@@ -107,6 +112,26 @@ parse_schedule (void) - - while (isspace ((unsigned char) *env)) - ++env; -+ if (strncasecmp (env, "monotonic", 9) == 0) -+ { -+ monotonic = 1; -+ env += 9; -+ } -+ else if (strncasecmp (env, "nonmonotonic", 12) == 0) -+ { -+ monotonic = -1; -+ env += 12; -+ } -+ if (monotonic) -+ { -+ while (isspace ((unsigned char) *env)) -+ ++env; -+ if (*env != ':') -+ goto unknown; -+ ++env; -+ while (isspace ((unsigned char) *env)) -+ ++env; -+ } - if (strncasecmp (env, "static", 6) == 0) - { - gomp_global_icv.run_sched_var = GFS_STATIC; -@@ -130,12 +155,16 @@ parse_schedule (void) - else - goto unknown; - -+ if (monotonic == 1 -+ || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC)) -+ gomp_global_icv.run_sched_var |= GFS_MONOTONIC; -+ - while (isspace ((unsigned char) *env)) - ++env; - if (*env == '\0') - { - gomp_global_icv.run_sched_chunk_size -- = gomp_global_icv.run_sched_var != GFS_STATIC; -+ = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC; - return; - } - if (*env++ != ',') -@@ -158,7 +187,8 @@ parse_schedule (void) - if ((int)value != value) - goto invalid; - -- if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC) -+ if (value == 0 -+ && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC) - value = 1; - gomp_global_icv.run_sched_chunk_size = value; - return; -@@ -1066,6 +1096,36 @@ parse_acc_device_type (void) - } - - static void -+parse_gomp_openacc_dim (void) -+{ -+ /* The syntax is the same as for the -fopenacc-dim compilation option. */ -+ const char *var_name = "GOMP_OPENACC_DIM"; -+ const char *env_var = getenv (var_name); -+ if (!env_var) -+ return; -+ -+ const char *pos = env_var; -+ int i; -+ for (i = 0; *pos && i != GOMP_DIM_MAX; i++) -+ { -+ if (i && *pos++ != ':') -+ break; -+ -+ if (*pos == ':') -+ continue; -+ -+ const char *eptr; -+ errno = 0; -+ long val = strtol (pos, (char **)&eptr, 10); -+ if (errno || val < 0 || (unsigned)val != val) -+ break; -+ -+ goacc_default_dims[i] = (int)val; -+ pos = eptr; -+ } -+} -+ -+static void - handle_omp_display_env (unsigned long stacksize, int wait_policy) - { - const char *env; -@@ -1119,19 +1179,34 @@ handle_omp_display_env (unsigned long st - fputs ("'\n", stderr); - - fprintf (stderr, " OMP_SCHEDULE = '"); -- switch (gomp_global_icv.run_sched_var) -+ if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC)) -+ { -+ if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC)) -+ fputs ("MONOTONIC:", stderr); -+ } -+ else if (gomp_global_icv.run_sched_var == GFS_STATIC) -+ fputs ("NONMONOTONIC:", stderr); -+ switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) - { - case GFS_RUNTIME: - fputs ("RUNTIME", stderr); -+ if (gomp_global_icv.run_sched_chunk_size != 1) -+ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size); - break; - case GFS_STATIC: - fputs ("STATIC", stderr); -+ if (gomp_global_icv.run_sched_chunk_size != 0) -+ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size); - break; - case GFS_DYNAMIC: - fputs ("DYNAMIC", stderr); -+ if (gomp_global_icv.run_sched_chunk_size != 1) -+ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size); - break; - case GFS_GUIDED: - fputs ("GUIDED", stderr); -+ if (gomp_global_icv.run_sched_chunk_size != 1) -+ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size); - break; - case GFS_AUTO: - fputs ("AUTO", stderr); -@@ -1197,6 +1272,10 @@ handle_omp_display_env (unsigned long st - gomp_global_icv.default_device_var); - fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n", - gomp_max_task_priority_var); -+ fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n", -+ gomp_display_affinity_var ? "TRUE" : "FALSE"); -+ fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n", -+ gomp_affinity_format_var); - - if (verbose) - { -@@ -1228,6 +1307,7 @@ initialize_env (void) - parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var); - parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var); - parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var); -+ parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var); - parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true); - parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true); - parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var, -@@ -1277,6 +1357,13 @@ initialize_env (void) - } - if (gomp_global_icv.bind_var != omp_proc_bind_false) - gomp_init_affinity (); -+ -+ { -+ const char *env = getenv ("OMP_AFFINITY_FORMAT"); -+ if (env != NULL) -+ gomp_set_affinity_format (env, strlen (env)); -+ } -+ - wait_policy = parse_wait_policy (); - if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var)) - { -@@ -1302,7 +1389,6 @@ initialize_env (void) - - /* Not strictly environment related, but ordering constructors is tricky. */ - pthread_attr_init (&gomp_thread_attr); -- pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED); - - if (parse_stacksize ("OMP_STACKSIZE", &stacksize) - || parse_stacksize ("GOMP_STACKSIZE", &stacksize) -@@ -1336,6 +1422,7 @@ initialize_env (void) - goacc_device_num = 0; - - parse_acc_device_type (); -+ parse_gomp_openacc_dim (); - - goacc_runtime_initialize (); - } ---- libgomp/fortran.c.jj 2018-04-25 09:40:31.913655581 +0200 -+++ libgomp/fortran.c 2019-05-07 18:46:36.491110295 +0200 -@@ -28,6 +28,8 @@ - #include "libgomp.h" - #include "libgomp_f.h" - #include -+#include -+#include - #include - - #ifdef HAVE_ATTRIBUTE_ALIAS -@@ -82,6 +84,8 @@ ialias_redirect (omp_get_team_num) - ialias_redirect (omp_is_initial_device) - ialias_redirect (omp_get_initial_device) - ialias_redirect (omp_get_max_task_priority) -+ialias_redirect (omp_pause_resource) -+ialias_redirect (omp_pause_resource_all) - #endif - - #ifndef LIBGOMP_GNU_SYMBOL_VERSIONING -@@ -368,7 +372,9 @@ omp_get_schedule_ (int32_t *kind, int32_ - omp_sched_t k; - int cs; - omp_get_schedule (&k, &cs); -- *kind = k; -+ /* For now mask off GFS_MONOTONIC, because OpenMP 4.5 code will not -+ expect to see it. */ -+ *kind = k & ~GFS_MONOTONIC; - *chunk_size = cs; - } - -@@ -378,7 +384,8 @@ omp_get_schedule_8_ (int32_t *kind, int6 - omp_sched_t k; - int cs; - omp_get_schedule (&k, &cs); -- *kind = k; -+ /* See above. */ -+ *kind = k & ~GFS_MONOTONIC; - *chunk_size = cs; - } - -@@ -576,3 +583,96 @@ omp_get_max_task_priority_ (void) - { - return omp_get_max_task_priority (); - } -+ -+void -+omp_set_affinity_format_ (const char *format, size_t format_len) -+{ -+ gomp_set_affinity_format (format, format_len); -+} -+ -+int32_t -+omp_get_affinity_format_ (char *buffer, size_t buffer_len) -+{ -+ size_t len = strlen (gomp_affinity_format_var); -+ if (buffer_len) -+ { -+ if (len < buffer_len) -+ { -+ memcpy (buffer, gomp_affinity_format_var, len); -+ memset (buffer + len, ' ', buffer_len - len); -+ } -+ else -+ memcpy (buffer, gomp_affinity_format_var, buffer_len); -+ } -+ return len; -+} -+ -+void -+omp_display_affinity_ (const char *format, size_t format_len) -+{ -+ char *fmt = NULL, fmt_buf[256]; -+ char buf[512]; -+ if (format_len) -+ { -+ fmt = format_len < 256 ? fmt_buf : gomp_malloc (format_len + 1); -+ memcpy (fmt, format, format_len); -+ fmt[format_len] = '\0'; -+ } -+ struct gomp_thread *thr = gomp_thread (); -+ size_t ret -+ = gomp_display_affinity (buf, sizeof buf, -+ format_len ? fmt : gomp_affinity_format_var, -+ gomp_thread_self (), &thr->ts, thr->place); -+ if (ret < sizeof buf) -+ { -+ buf[ret] = '\n'; -+ gomp_print_string (buf, ret + 1); -+ } -+ else -+ { -+ char *b = gomp_malloc (ret + 1); -+ gomp_display_affinity (buf, sizeof buf, -+ format_len ? fmt : gomp_affinity_format_var, -+ gomp_thread_self (), &thr->ts, thr->place); -+ b[ret] = '\n'; -+ gomp_print_string (b, ret + 1); -+ free (b); -+ } -+ if (fmt && fmt != fmt_buf) -+ free (fmt); -+} -+ -+int32_t -+omp_capture_affinity_ (char *buffer, const char *format, -+ size_t buffer_len, size_t format_len) -+{ -+ char *fmt = NULL, fmt_buf[256]; -+ if (format_len) -+ { -+ fmt = format_len < 256 ? fmt_buf : gomp_malloc (format_len + 1); -+ memcpy (fmt, format, format_len); -+ fmt[format_len] = '\0'; -+ } -+ struct gomp_thread *thr = gomp_thread (); -+ size_t ret -+ = gomp_display_affinity (buffer, buffer_len, -+ format_len ? fmt : gomp_affinity_format_var, -+ gomp_thread_self (), &thr->ts, thr->place); -+ if (fmt && fmt != fmt_buf) -+ free (fmt); -+ if (ret < buffer_len) -+ memset (buffer + ret, ' ', buffer_len - ret); -+ return ret; -+} -+ -+int32_t -+omp_pause_resource_ (const int32_t *kind, const int32_t *device_num) -+{ -+ return omp_pause_resource (*kind, *device_num); -+} -+ -+int32_t -+omp_pause_resource_all_ (const int32_t *kind) -+{ -+ return omp_pause_resource_all (*kind); -+} ---- libgomp/configure.tgt.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/configure.tgt 2019-05-07 18:46:36.479110486 +0200 -@@ -18,7 +18,7 @@ if test $gcc_cv_have_tls = yes ; then - ;; - - *-*-linux* | *-*-gnu*) -- XCFLAGS="${XCFLAGS} -ftls-model=initial-exec" -+ XCFLAGS="${XCFLAGS} -ftls-model=initial-exec -DUSING_INITIAL_EXEC_TLS" - ;; - - *-*-rtems*) ---- libgomp/icv-device.c.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/icv-device.c 2019-05-07 18:46:36.513109943 +0200 -@@ -49,20 +49,6 @@ omp_get_num_devices (void) - } - - int --omp_get_num_teams (void) --{ -- /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */ -- return 1; --} -- --int --omp_get_team_num (void) --{ -- /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */ -- return 0; --} -- --int - omp_is_initial_device (void) - { - /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */ -@@ -72,6 +58,4 @@ omp_is_initial_device (void) - ialias (omp_set_default_device) - ialias (omp_get_default_device) - ialias (omp_get_num_devices) --ialias (omp_get_num_teams) --ialias (omp_get_team_num) - ialias (omp_is_initial_device) ---- libgomp/Makefile.in.jj 2018-04-25 09:40:31.320655306 +0200 -+++ libgomp/Makefile.in 2019-05-07 20:00:01.082077522 +0200 -@@ -90,7 +90,7 @@ DIST_COMMON = $(top_srcdir)/plugin/Makef - $(srcdir)/libgomp.spec.in $(srcdir)/../depcomp - @PLUGIN_NVPTX_TRUE@am__append_1 = libgomp-plugin-nvptx.la - @PLUGIN_HSA_TRUE@am__append_2 = libgomp-plugin-hsa.la --@USE_FORTRAN_TRUE@am__append_3 = openacc.f90 -+@USE_FORTRAN_TRUE@am__append_3 = openacc2.f90 - subdir = . - ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 - am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ -@@ -172,7 +172,7 @@ libgomp_plugin_nvptx_la_LINK = $(LIBTOOL - @PLUGIN_NVPTX_TRUE@am_libgomp_plugin_nvptx_la_rpath = -rpath \ - @PLUGIN_NVPTX_TRUE@ $(toolexeclibdir) - libgomp_la_LIBADD = --@USE_FORTRAN_TRUE@am__objects_1 = openacc.lo -+@USE_FORTRAN_TRUE@am__objects_1 = openacc2.lo - am_libgomp_la_OBJECTS = alloc.lo atomic.lo barrier.lo critical.lo \ - env.lo error.lo icv.lo icv-device.lo iter.lo iter_ull.lo \ - loop.lo loop_ull.lo ordered.lo parallel.lo sections.lo \ -@@ -180,7 +180,8 @@ am_libgomp_la_OBJECTS = alloc.lo atomic. - sem.lo bar.lo ptrlock.lo time.lo fortran.lo affinity.lo \ - target.lo splay-tree.lo libgomp-plugin.lo oacc-parallel.lo \ - oacc-host.lo oacc-init.lo oacc-mem.lo oacc-async.lo \ -- oacc-plugin.lo oacc-cuda.lo priority_queue.lo $(am__objects_1) -+ oacc-plugin.lo oacc-cuda.lo priority_queue.lo affinity-fmt.lo \ -+ teams.lo $(am__objects_1) - libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS) - DEFAULT_INCLUDES = -I.@am__isrc@ - depcomp = $(SHELL) $(top_srcdir)/../depcomp -@@ -380,6 +381,7 @@ mkdir_p = @mkdir_p@ - multi_basedir = @multi_basedir@ - offload_additional_lib_paths = @offload_additional_lib_paths@ - offload_additional_options = @offload_additional_options@ -+offload_plugins = @offload_plugins@ - offload_targets = @offload_targets@ - oldincludedir = @oldincludedir@ - pdfdir = @pdfdir@ -@@ -436,7 +438,7 @@ libgomp_la_SOURCES = alloc.c atomic.c ba - affinity.c target.c splay-tree.c libgomp-plugin.c \ - oacc-parallel.c oacc-host.c oacc-init.c oacc-mem.c \ - oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \ -- $(am__append_3) -+ affinity-fmt.c teams.c $(am__append_3) - - # Nvidia PTX OpenACC plugin. - @PLUGIN_NVPTX_TRUE@libgomp_plugin_nvptx_version_info = -version-info $(libtool_VERSION) -@@ -599,6 +601,7 @@ mostlyclean-compile: - distclean-compile: - -rm -f *.tab.c - -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity-fmt.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic.Plo@am__quote@ -@@ -638,6 +641,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/team.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/teams.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work.Plo@am__quote@ - -@@ -1292,8 +1296,6 @@ omp_lib_kinds.mod: omp_lib.mod - : - openacc_kinds.mod: openacc.mod - : --openacc.mod: openacc.lo -- : - %.mod: %.f90 - $(FC) $(FCFLAGS) -fsyntax-only $< - fortran.lo: libgomp_f.h ---- libgomp/plugin/cuda/cuda.h.jj 2018-04-25 09:40:31.914655581 +0200 -+++ libgomp/plugin/cuda/cuda.h 2019-05-07 18:46:36.533109624 +0200 -@@ -44,6 +44,7 @@ typedef void *CUevent; - typedef void *CUfunction; - typedef void *CUlinkState; - typedef void *CUmodule; -+typedef size_t (*CUoccupancyB2DSize)(int); - typedef void *CUstream; - - typedef enum { -@@ -88,6 +89,7 @@ typedef enum { - CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES = 4, - CU_JIT_ERROR_LOG_BUFFER = 5, - CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES = 6, -+ CU_JIT_OPTIMIZATION_LEVEL = 7, - CU_JIT_LOG_VERBOSE = 12 - } CUjit_option; - -@@ -169,6 +171,8 @@ CUresult cuModuleGetGlobal (CUdeviceptr - CUresult cuModuleLoad (CUmodule *, const char *); - CUresult cuModuleLoadData (CUmodule *, const void *); - CUresult cuModuleUnload (CUmodule); -+CUresult cuOccupancyMaxPotentialBlockSize(int *, int *, CUfunction, -+ CUoccupancyB2DSize, size_t, int); - CUresult cuStreamCreate (CUstream *, unsigned); - #define cuStreamDestroy cuStreamDestroy_v2 - CUresult cuStreamDestroy (CUstream); ---- libgomp/plugin/cuda-lib.def.jj 2019-05-07 18:46:36.533109624 +0200 -+++ libgomp/plugin/cuda-lib.def 2019-05-07 18:46:36.533109624 +0200 -@@ -0,0 +1,49 @@ -+CUDA_ONE_CALL (cuCtxCreate) -+CUDA_ONE_CALL (cuCtxDestroy) -+CUDA_ONE_CALL (cuCtxGetCurrent) -+CUDA_ONE_CALL (cuCtxGetDevice) -+CUDA_ONE_CALL (cuCtxPopCurrent) -+CUDA_ONE_CALL (cuCtxPushCurrent) -+CUDA_ONE_CALL (cuCtxSynchronize) -+CUDA_ONE_CALL (cuDeviceGet) -+CUDA_ONE_CALL (cuDeviceGetAttribute) -+CUDA_ONE_CALL (cuDeviceGetCount) -+CUDA_ONE_CALL (cuEventCreate) -+CUDA_ONE_CALL (cuEventDestroy) -+CUDA_ONE_CALL (cuEventElapsedTime) -+CUDA_ONE_CALL (cuEventQuery) -+CUDA_ONE_CALL (cuEventRecord) -+CUDA_ONE_CALL (cuEventSynchronize) -+CUDA_ONE_CALL (cuFuncGetAttribute) -+CUDA_ONE_CALL_MAYBE_NULL (cuGetErrorString) -+CUDA_ONE_CALL (cuInit) -+CUDA_ONE_CALL (cuLaunchKernel) -+CUDA_ONE_CALL (cuLinkAddData) -+CUDA_ONE_CALL_MAYBE_NULL (cuLinkAddData_v2) -+CUDA_ONE_CALL (cuLinkComplete) -+CUDA_ONE_CALL (cuLinkCreate) -+CUDA_ONE_CALL_MAYBE_NULL (cuLinkCreate_v2) -+CUDA_ONE_CALL (cuLinkDestroy) -+CUDA_ONE_CALL (cuMemAlloc) -+CUDA_ONE_CALL (cuMemAllocHost) -+CUDA_ONE_CALL (cuMemcpy) -+CUDA_ONE_CALL (cuMemcpyDtoDAsync) -+CUDA_ONE_CALL (cuMemcpyDtoH) -+CUDA_ONE_CALL (cuMemcpyDtoHAsync) -+CUDA_ONE_CALL (cuMemcpyHtoD) -+CUDA_ONE_CALL (cuMemcpyHtoDAsync) -+CUDA_ONE_CALL (cuMemFree) -+CUDA_ONE_CALL (cuMemFreeHost) -+CUDA_ONE_CALL (cuMemGetAddressRange) -+CUDA_ONE_CALL (cuMemHostGetDevicePointer) -+CUDA_ONE_CALL (cuModuleGetFunction) -+CUDA_ONE_CALL (cuModuleGetGlobal) -+CUDA_ONE_CALL (cuModuleLoad) -+CUDA_ONE_CALL (cuModuleLoadData) -+CUDA_ONE_CALL (cuModuleUnload) -+CUDA_ONE_CALL_MAYBE_NULL (cuOccupancyMaxPotentialBlockSize) -+CUDA_ONE_CALL (cuStreamCreate) -+CUDA_ONE_CALL (cuStreamDestroy) -+CUDA_ONE_CALL (cuStreamQuery) -+CUDA_ONE_CALL (cuStreamSynchronize) -+CUDA_ONE_CALL (cuStreamWaitEvent) ---- libgomp/plugin/plugin-nvptx.c.jj 2018-04-25 09:40:31.915655582 +0200 -+++ libgomp/plugin/plugin-nvptx.c 2019-05-07 18:46:36.535109592 +0200 -@@ -31,6 +31,7 @@ - is not clear as to what that state might be. Or how one might - propagate it from one thread to another. */ - -+#define _GNU_SOURCE - #include "openacc.h" - #include "config.h" - #include "libgomp-plugin.h" -@@ -48,60 +49,41 @@ - #include - #include - -+#if CUDA_VERSION < 6000 -+extern CUresult cuGetErrorString (CUresult, const char **); -+#define CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR 82 -+#endif -+ -+#if CUDA_VERSION >= 6050 -+#undef cuLinkCreate -+#undef cuLinkAddData -+CUresult cuLinkAddData (CUlinkState, CUjitInputType, void *, size_t, -+ const char *, unsigned, CUjit_option *, void **); -+CUresult cuLinkCreate (unsigned, CUjit_option *, void **, CUlinkState *); -+#else -+typedef size_t (*CUoccupancyB2DSize)(int); -+CUresult cuLinkAddData_v2 (CUlinkState, CUjitInputType, void *, size_t, -+ const char *, unsigned, CUjit_option *, void **); -+CUresult cuLinkCreate_v2 (unsigned, CUjit_option *, void **, CUlinkState *); -+CUresult cuOccupancyMaxPotentialBlockSize(int *, int *, CUfunction, -+ CUoccupancyB2DSize, size_t, int); -+#endif -+ -+#define DO_PRAGMA(x) _Pragma (#x) -+ - #if PLUGIN_NVPTX_DYNAMIC - # include - --# define CUDA_CALLS \ --CUDA_ONE_CALL (cuCtxCreate) \ --CUDA_ONE_CALL (cuCtxDestroy) \ --CUDA_ONE_CALL (cuCtxGetCurrent) \ --CUDA_ONE_CALL (cuCtxGetDevice) \ --CUDA_ONE_CALL (cuCtxPopCurrent) \ --CUDA_ONE_CALL (cuCtxPushCurrent) \ --CUDA_ONE_CALL (cuCtxSynchronize) \ --CUDA_ONE_CALL (cuDeviceGet) \ --CUDA_ONE_CALL (cuDeviceGetAttribute) \ --CUDA_ONE_CALL (cuDeviceGetCount) \ --CUDA_ONE_CALL (cuEventCreate) \ --CUDA_ONE_CALL (cuEventDestroy) \ --CUDA_ONE_CALL (cuEventElapsedTime) \ --CUDA_ONE_CALL (cuEventQuery) \ --CUDA_ONE_CALL (cuEventRecord) \ --CUDA_ONE_CALL (cuEventSynchronize) \ --CUDA_ONE_CALL (cuFuncGetAttribute) \ --CUDA_ONE_CALL (cuGetErrorString) \ --CUDA_ONE_CALL (cuInit) \ --CUDA_ONE_CALL (cuLaunchKernel) \ --CUDA_ONE_CALL (cuLinkAddData) \ --CUDA_ONE_CALL (cuLinkComplete) \ --CUDA_ONE_CALL (cuLinkCreate) \ --CUDA_ONE_CALL (cuLinkDestroy) \ --CUDA_ONE_CALL (cuMemAlloc) \ --CUDA_ONE_CALL (cuMemAllocHost) \ --CUDA_ONE_CALL (cuMemcpy) \ --CUDA_ONE_CALL (cuMemcpyDtoDAsync) \ --CUDA_ONE_CALL (cuMemcpyDtoH) \ --CUDA_ONE_CALL (cuMemcpyDtoHAsync) \ --CUDA_ONE_CALL (cuMemcpyHtoD) \ --CUDA_ONE_CALL (cuMemcpyHtoDAsync) \ --CUDA_ONE_CALL (cuMemFree) \ --CUDA_ONE_CALL (cuMemFreeHost) \ --CUDA_ONE_CALL (cuMemGetAddressRange) \ --CUDA_ONE_CALL (cuMemHostGetDevicePointer)\ --CUDA_ONE_CALL (cuModuleGetFunction) \ --CUDA_ONE_CALL (cuModuleGetGlobal) \ --CUDA_ONE_CALL (cuModuleLoad) \ --CUDA_ONE_CALL (cuModuleLoadData) \ --CUDA_ONE_CALL (cuModuleUnload) \ --CUDA_ONE_CALL (cuStreamCreate) \ --CUDA_ONE_CALL (cuStreamDestroy) \ --CUDA_ONE_CALL (cuStreamQuery) \ --CUDA_ONE_CALL (cuStreamSynchronize) \ --CUDA_ONE_CALL (cuStreamWaitEvent) --# define CUDA_ONE_CALL(call) \ -- __typeof (call) *call; - struct cuda_lib_s { -- CUDA_CALLS -+ -+# define CUDA_ONE_CALL(call) \ -+ __typeof (call) *call; -+# define CUDA_ONE_CALL_MAYBE_NULL(call) \ -+ CUDA_ONE_CALL (call) -+#include "cuda-lib.def" -+# undef CUDA_ONE_CALL -+# undef CUDA_ONE_CALL_MAYBE_NULL -+ - } cuda_lib; - - /* -1 if init_cuda_lib has not been called yet, false -@@ -120,24 +102,41 @@ init_cuda_lib (void) - cuda_lib_inited = false; - if (h == NULL) - return false; --# undef CUDA_ONE_CALL --# define CUDA_ONE_CALL(call) CUDA_ONE_CALL_1 (call) --# define CUDA_ONE_CALL_1(call) \ -+ -+# define CUDA_ONE_CALL(call) CUDA_ONE_CALL_1 (call, false) -+# define CUDA_ONE_CALL_MAYBE_NULL(call) CUDA_ONE_CALL_1 (call, true) -+# define CUDA_ONE_CALL_1(call, allow_null) \ - cuda_lib.call = dlsym (h, #call); \ -- if (cuda_lib.call == NULL) \ -+ if (!allow_null && cuda_lib.call == NULL) \ - return false; -- CUDA_CALLS -+#include "cuda-lib.def" -+# undef CUDA_ONE_CALL -+# undef CUDA_ONE_CALL_1 -+# undef CUDA_ONE_CALL_MAYBE_NULL -+ - cuda_lib_inited = true; - return true; - } --# undef CUDA_ONE_CALL --# undef CUDA_ONE_CALL_1 - # define CUDA_CALL_PREFIX cuda_lib. - #else -+ -+# define CUDA_ONE_CALL(call) -+# define CUDA_ONE_CALL_MAYBE_NULL(call) DO_PRAGMA (weak call) -+#include "cuda-lib.def" -+#undef CUDA_ONE_CALL_MAYBE_NULL -+#undef CUDA_ONE_CALL -+ - # define CUDA_CALL_PREFIX - # define init_cuda_lib() true - #endif - -+#include "secure_getenv.h" -+ -+#undef MIN -+#undef MAX -+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) -+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) -+ - /* Convenience macros for the frequently used CUDA library call and - error handling sequence as well as CUDA library calls that - do the error checking themselves or don't do it at all. */ -@@ -171,40 +170,42 @@ init_cuda_lib (void) - #define CUDA_CALL_NOCHECK(FN, ...) \ - CUDA_CALL_PREFIX FN (__VA_ARGS__) - -+#define CUDA_CALL_EXISTS(FN) \ -+ CUDA_CALL_PREFIX FN -+ - static const char * - cuda_error (CUresult r) - { --#if CUDA_VERSION < 7000 -- /* Specified in documentation and present in library from at least -- 5.5. Not declared in header file prior to 7.0. */ -- extern CUresult cuGetErrorString (CUresult, const char **); --#endif -+ const char *fallback = "unknown cuda error"; - const char *desc; - -+ if (!CUDA_CALL_EXISTS (cuGetErrorString)) -+ return fallback; -+ - r = CUDA_CALL_NOCHECK (cuGetErrorString, r, &desc); -- if (r != CUDA_SUCCESS) -- desc = "unknown cuda error"; -+ if (r == CUDA_SUCCESS) -+ return desc; - -- return desc; -+ return fallback; - } - - static unsigned int instantiated_devices = 0; - static pthread_mutex_t ptx_dev_lock = PTHREAD_MUTEX_INITIALIZER; - -+struct cuda_map -+{ -+ CUdeviceptr d; -+ size_t size; -+ bool active; -+ struct cuda_map *next; -+}; -+ - struct ptx_stream - { - CUstream stream; - pthread_t host_thread; - bool multithreaded; -- -- CUdeviceptr d; -- void *h; -- void *h_begin; -- void *h_end; -- void *h_next; -- void *h_prev; -- void *h_tail; -- -+ struct cuda_map *map; - struct ptx_stream *next; - }; - -@@ -216,12 +217,64 @@ struct nvptx_thread - struct ptx_device *ptx_dev; - }; - --struct map -+static struct cuda_map * -+cuda_map_create (size_t size) - { -- int async; -- size_t size; -- char mappings[0]; --}; -+ struct cuda_map *map = GOMP_PLUGIN_malloc (sizeof (struct cuda_map)); -+ -+ assert (map); -+ -+ map->next = NULL; -+ map->size = size; -+ map->active = false; -+ -+ CUDA_CALL_ERET (NULL, cuMemAlloc, &map->d, size); -+ assert (map->d); -+ -+ return map; -+} -+ -+static void -+cuda_map_destroy (struct cuda_map *map) -+{ -+ if (map->active) -+ /* Possible reasons for the map to be still active: -+ - the associated async kernel might still be running. -+ - the associated async kernel might have finished, but the -+ corresponding event that should trigger the pop_map has not been -+ processed by event_gc. -+ - the associated sync kernel might have aborted -+ -+ The async cases could happen if the user specified an async region -+ without adding a corresponding wait that is guaranteed to be executed -+ (before returning from main, or in an atexit handler). -+ We do not want to deallocate a device pointer that is still being -+ used, so skip it. -+ -+ In the sync case, the device pointer is no longer used, but deallocating -+ it using cuMemFree will not succeed, so skip it. -+ -+ TODO: Handle this in a more constructive way, by f.i. waiting for streams -+ to finish before de-allocating them (PR88981), or by ensuring the CUDA -+ lib atexit handler is called before rather than after the libgomp plugin -+ atexit handler (PR83795). */ -+ ; -+ else -+ CUDA_CALL_NOCHECK (cuMemFree, map->d); -+ -+ free (map); -+} -+ -+/* The following map_* routines manage the CUDA device memory that -+ contains the data mapping arguments for cuLaunchKernel. Each -+ asynchronous PTX stream may have multiple pending kernel -+ invocations, which are launched in a FIFO order. As such, the map -+ routines maintains a queue of cuLaunchKernel arguments. -+ -+ Calls to map_push and map_pop must be guarded by ptx_event_lock. -+ Likewise, calls to map_init and map_fini are guarded by -+ ptx_dev_lock inside GOMP_OFFLOAD_init_device and -+ GOMP_OFFLOAD_fini_device, respectively. */ - - static bool - map_init (struct ptx_stream *s) -@@ -229,109 +282,83 @@ map_init (struct ptx_stream *s) - int size = getpagesize (); - - assert (s); -- assert (!s->d); -- assert (!s->h); -- -- CUDA_CALL (cuMemAllocHost, &s->h, size); -- CUDA_CALL (cuMemHostGetDevicePointer, &s->d, s->h, 0); - -- assert (s->h); -+ s->map = cuda_map_create (size); - -- s->h_begin = s->h; -- s->h_end = s->h_begin + size; -- s->h_next = s->h_prev = s->h_tail = s->h_begin; -- -- assert (s->h_next); -- assert (s->h_end); - return true; - } - - static bool - map_fini (struct ptx_stream *s) - { -- CUDA_CALL (cuMemFreeHost, s->h); -+ assert (s->map->next == NULL); -+ -+ cuda_map_destroy (s->map); -+ - return true; - } - - static void - map_pop (struct ptx_stream *s) - { -- struct map *m; -+ struct cuda_map *next; - - assert (s != NULL); -- assert (s->h_next); -- assert (s->h_prev); -- assert (s->h_tail); -- -- m = s->h_tail; -- -- s->h_tail += m->size; -- -- if (s->h_tail >= s->h_end) -- s->h_tail = s->h_begin + (int) (s->h_tail - s->h_end); -- -- if (s->h_next == s->h_tail) -- s->h_prev = s->h_next; - -- assert (s->h_next >= s->h_begin); -- assert (s->h_tail >= s->h_begin); -- assert (s->h_prev >= s->h_begin); -+ if (s->map->next == NULL) -+ { -+ s->map->active = false; -+ return; -+ } - -- assert (s->h_next <= s->h_end); -- assert (s->h_tail <= s->h_end); -- assert (s->h_prev <= s->h_end); -+ next = s->map->next; -+ cuda_map_destroy (s->map); -+ s->map = next; - } - --static void --map_push (struct ptx_stream *s, int async, size_t size, void **h, void **d) -+static CUdeviceptr -+map_push (struct ptx_stream *s, size_t size) - { -- int left; -- int offset; -- struct map *m; -+ struct cuda_map *map = NULL; -+ struct cuda_map **t; - -- assert (s != NULL); -- -- left = s->h_end - s->h_next; -- size += sizeof (struct map); -- -- assert (s->h_prev); -- assert (s->h_next); -+ assert (s); -+ assert (s->map); - -- if (size >= left) -+ /* Select an element to push. */ -+ if (s->map->active) -+ map = cuda_map_create (size); -+ else - { -- m = s->h_prev; -- m->size += left; -- s->h_next = s->h_begin; -- -- if (s->h_next + size > s->h_end) -- GOMP_PLUGIN_fatal ("unable to push map"); -- } -- -- assert (s->h_next); -- -- m = s->h_next; -- m->async = async; -- m->size = size; -+ /* Pop the inactive front element. */ -+ struct cuda_map *pop = s->map; -+ s->map = pop->next; -+ pop->next = NULL; - -- offset = (void *)&m->mappings[0] - s->h; -+ if (pop->size < size) -+ { -+ cuda_map_destroy (pop); - -- *d = (void *)(s->d + offset); -- *h = (void *)(s->h + offset); -+ map = cuda_map_create (size); -+ } -+ else -+ map = pop; -+ } - -- s->h_prev = s->h_next; -- s->h_next += size; -+ /* Check that the element is as expected. */ -+ assert (map->next == NULL); -+ assert (!map->active); - -- assert (s->h_prev); -- assert (s->h_next); -+ /* Mark the element active. */ -+ map->active = true; - -- assert (s->h_next >= s->h_begin); -- assert (s->h_tail >= s->h_begin); -- assert (s->h_prev >= s->h_begin); -- assert (s->h_next <= s->h_end); -- assert (s->h_tail <= s->h_end); -- assert (s->h_prev <= s->h_end); -+ /* Push the element to the back of the list. */ -+ for (t = &s->map; (*t) != NULL; t = &(*t)->next) -+ ; -+ assert (t != NULL && *t == NULL); -+ *t = map; - -- return; -+ return map->d; - } - - /* Target data function launch information. */ -@@ -411,6 +438,10 @@ struct ptx_device - int num_sms; - int regs_per_block; - int regs_per_sm; -+ int warp_size; -+ int max_threads_per_block; -+ int max_threads_per_multiprocessor; -+ int default_dims[GOMP_DIM_MAX]; - - struct ptx_image_data *images; /* Images loaded on device. */ - pthread_mutex_t image_lock; /* Lock for above list. */ -@@ -458,8 +489,6 @@ init_streams_for_device (struct ptx_devi - null_stream->stream = NULL; - null_stream->host_thread = pthread_self (); - null_stream->multithreaded = true; -- null_stream->d = (CUdeviceptr) NULL; -- null_stream->h = NULL; - if (!map_init (null_stream)) - return false; - -@@ -594,8 +623,6 @@ select_stream_for_async (int async, pthr - s->host_thread = thread; - s->multithreaded = false; - -- s->d = (CUdeviceptr) NULL; -- s->h = NULL; - if (!map_init (s)) - { - pthread_mutex_unlock (&ptx_dev->stream_lock); -@@ -777,9 +804,11 @@ nvptx_open_device (int n) - &pi, CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK, dev); - ptx_dev->regs_per_block = pi; - -- /* CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR = 82 is defined only -+ /* CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR is defined only - in CUDA 6.0 and newer. */ -- r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &pi, 82, dev); -+ r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &pi, -+ CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR, -+ dev); - /* Fallback: use limit of registers per block, which is usually equal. */ - if (r == CUDA_ERROR_INVALID_VALUE) - pi = ptx_dev->regs_per_block; -@@ -797,12 +826,24 @@ nvptx_open_device (int n) - GOMP_PLUGIN_error ("Only warp size 32 is supported"); - return NULL; - } -+ ptx_dev->warp_size = pi; -+ -+ CUDA_CALL_ERET (NULL, cuDeviceGetAttribute, &pi, -+ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK, dev); -+ ptx_dev->max_threads_per_block = pi; -+ -+ CUDA_CALL_ERET (NULL, cuDeviceGetAttribute, &pi, -+ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR, dev); -+ ptx_dev->max_threads_per_multiprocessor = pi; - - r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &async_engines, - CU_DEVICE_ATTRIBUTE_ASYNC_ENGINE_COUNT, dev); - if (r != CUDA_SUCCESS) - async_engines = 1; - -+ for (int i = 0; i != GOMP_DIM_MAX; i++) -+ ptx_dev->default_dims[i] = 0; -+ - ptx_dev->images = NULL; - pthread_mutex_init (&ptx_dev->image_lock, NULL); - -@@ -876,12 +917,42 @@ notify_var (const char *var_name, const - GOMP_PLUGIN_debug (0, "%s: '%s'\n", var_name, env_var); - } - -+static void -+process_GOMP_NVPTX_JIT (intptr_t *gomp_nvptx_o) -+{ -+ const char *var_name = "GOMP_NVPTX_JIT"; -+ const char *env_var = secure_getenv (var_name); -+ notify_var (var_name, env_var); -+ -+ if (env_var == NULL) -+ return; -+ -+ const char *c = env_var; -+ while (*c != '\0') -+ { -+ while (*c == ' ') -+ c++; -+ -+ if (c[0] == '-' && c[1] == 'O' -+ && '0' <= c[2] && c[2] <= '4' -+ && (c[3] == '\0' || c[3] == ' ')) -+ { -+ *gomp_nvptx_o = c[2] - '0'; -+ c += 3; -+ continue; -+ } -+ -+ GOMP_PLUGIN_error ("Error parsing %s", var_name); -+ break; -+ } -+} -+ - static bool - link_ptx (CUmodule *module, const struct targ_ptx_obj *ptx_objs, - unsigned num_objs) - { -- CUjit_option opts[6]; -- void *optvals[6]; -+ CUjit_option opts[7]; -+ void *optvals[7]; - float elapsed = 0.0; - char elog[1024]; - char ilog[16384]; -@@ -908,16 +979,41 @@ link_ptx (CUmodule *module, const struct - opts[5] = CU_JIT_LOG_VERBOSE; - optvals[5] = (void *) 1; - -- CUDA_CALL (cuLinkCreate, 6, opts, optvals, &linkstate); -+ static intptr_t gomp_nvptx_o = -1; -+ -+ static bool init_done = false; -+ if (!init_done) -+ { -+ process_GOMP_NVPTX_JIT (&gomp_nvptx_o); -+ init_done = true; -+ } -+ -+ int nopts = 6; -+ if (gomp_nvptx_o != -1) -+ { -+ opts[nopts] = CU_JIT_OPTIMIZATION_LEVEL; -+ optvals[nopts] = (void *) gomp_nvptx_o; -+ nopts++; -+ } -+ -+ if (CUDA_CALL_EXISTS (cuLinkCreate_v2)) -+ CUDA_CALL (cuLinkCreate_v2, nopts, opts, optvals, &linkstate); -+ else -+ CUDA_CALL (cuLinkCreate, nopts, opts, optvals, &linkstate); - - for (; num_objs--; ptx_objs++) - { - /* cuLinkAddData's 'data' argument erroneously omits the const - qualifier. */ - GOMP_PLUGIN_debug (0, "Loading:\n---\n%s\n---\n", ptx_objs->code); -- r = CUDA_CALL_NOCHECK (cuLinkAddData, linkstate, CU_JIT_INPUT_PTX, -- (char *) ptx_objs->code, ptx_objs->size, -- 0, 0, 0, 0); -+ if (CUDA_CALL_EXISTS (cuLinkAddData_v2)) -+ r = CUDA_CALL_NOCHECK (cuLinkAddData_v2, linkstate, CU_JIT_INPUT_PTX, -+ (char *) ptx_objs->code, ptx_objs->size, -+ 0, 0, 0, 0); -+ else -+ r = CUDA_CALL_NOCHECK (cuLinkAddData, linkstate, CU_JIT_INPUT_PTX, -+ (char *) ptx_objs->code, ptx_objs->size, -+ 0, 0, 0, 0); - if (r != CUDA_SUCCESS) - { - GOMP_PLUGIN_error ("Link error log %s\n", &elog[0]); -@@ -1067,8 +1163,10 @@ nvptx_exec (void (*fn), size_t mapnum, v - int i; - struct ptx_stream *dev_str; - void *kargs[1]; -- void *hp, *dp; -+ void *hp; -+ CUdeviceptr dp = 0; - struct nvptx_thread *nvthd = nvptx_thread (); -+ int warp_size = nvthd->ptx_dev->warp_size; - const char *maybe_abort_msg = "(perhaps abort was called)"; - - function = targ_fn->fn; -@@ -1090,68 +1188,36 @@ nvptx_exec (void (*fn), size_t mapnum, v - - if (seen_zero) - { -- /* See if the user provided GOMP_OPENACC_DIM environment -- variable to specify runtime defaults. */ -- static int default_dims[GOMP_DIM_MAX]; -- - pthread_mutex_lock (&ptx_dev_lock); -- if (!default_dims[0]) -- { -- const char *var_name = "GOMP_OPENACC_DIM"; -- /* We only read the environment variable once. You can't -- change it in the middle of execution. The syntax is -- the same as for the -fopenacc-dim compilation option. */ -- const char *env_var = getenv (var_name); -- notify_var (var_name, env_var); -- if (env_var) -- { -- const char *pos = env_var; - -- for (i = 0; *pos && i != GOMP_DIM_MAX; i++) -- { -- if (i && *pos++ != ':') -- break; -- if (*pos != ':') -- { -- const char *eptr; -- -- errno = 0; -- long val = strtol (pos, (char **)&eptr, 10); -- if (errno || val < 0 || (unsigned)val != val) -- break; -- default_dims[i] = (int)val; -- pos = eptr; -- } -- } -- } -+ static int gomp_openacc_dims[GOMP_DIM_MAX]; -+ if (!gomp_openacc_dims[0]) -+ { -+ /* See if the user provided GOMP_OPENACC_DIM environment -+ variable to specify runtime defaults. */ -+ for (int i = 0; i < GOMP_DIM_MAX; ++i) -+ gomp_openacc_dims[i] = GOMP_PLUGIN_acc_default_dim (i); -+ } - -- int warp_size, block_size, dev_size, cpu_size; -- CUdevice dev = nvptx_thread()->ptx_dev->dev; -- /* 32 is the default for known hardware. */ -- int gang = 0, worker = 32, vector = 32; -- CUdevice_attribute cu_tpb, cu_ws, cu_mpc, cu_tpm; -- -- cu_tpb = CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK; -- cu_ws = CU_DEVICE_ATTRIBUTE_WARP_SIZE; -- cu_mpc = CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT; -- cu_tpm = CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR; -- -- if (CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &block_size, cu_tpb, -- dev) == CUDA_SUCCESS -- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &warp_size, cu_ws, -- dev) == CUDA_SUCCESS -- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &dev_size, cu_mpc, -- dev) == CUDA_SUCCESS -- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &cpu_size, cu_tpm, -- dev) == CUDA_SUCCESS) -- { -- GOMP_PLUGIN_debug (0, " warp_size=%d, block_size=%d," -- " dev_size=%d, cpu_size=%d\n", -- warp_size, block_size, dev_size, cpu_size); -- gang = (cpu_size / block_size) * dev_size; -- worker = block_size / warp_size; -- vector = warp_size; -- } -+ if (!nvthd->ptx_dev->default_dims[0]) -+ { -+ int default_dims[GOMP_DIM_MAX]; -+ for (int i = 0; i < GOMP_DIM_MAX; ++i) -+ default_dims[i] = gomp_openacc_dims[i]; -+ -+ int gang, worker, vector; -+ { -+ int block_size = nvthd->ptx_dev->max_threads_per_block; -+ int cpu_size = nvthd->ptx_dev->max_threads_per_multiprocessor; -+ int dev_size = nvthd->ptx_dev->num_sms; -+ GOMP_PLUGIN_debug (0, " warp_size=%d, block_size=%d," -+ " dev_size=%d, cpu_size=%d\n", -+ warp_size, block_size, dev_size, cpu_size); -+ -+ gang = (cpu_size / block_size) * dev_size; -+ worker = block_size / warp_size; -+ vector = warp_size; -+ } - - /* There is no upper bound on the gang size. The best size - matches the hardware configuration. Logical gangs are -@@ -1172,29 +1238,150 @@ nvptx_exec (void (*fn), size_t mapnum, v - default_dims[GOMP_DIM_GANG], - default_dims[GOMP_DIM_WORKER], - default_dims[GOMP_DIM_VECTOR]); -+ -+ for (i = 0; i != GOMP_DIM_MAX; i++) -+ nvthd->ptx_dev->default_dims[i] = default_dims[i]; - } - pthread_mutex_unlock (&ptx_dev_lock); - -- for (i = 0; i != GOMP_DIM_MAX; i++) -- if (!dims[i]) -- dims[i] = default_dims[i]; -- } -- -- /* This reserves a chunk of a pre-allocated page of memory mapped on both -- the host and the device. HP is a host pointer to the new chunk, and DP is -- the corresponding device pointer. */ -- map_push (dev_str, async, mapnum * sizeof (void *), &hp, &dp); -- -- GOMP_PLUGIN_debug (0, " %s: prepare mappings\n", __FUNCTION__); -- -- /* Copy the array of arguments to the mapped page. */ -- for (i = 0; i < mapnum; i++) -- ((void **) hp)[i] = devaddrs[i]; -- -- /* Copy the (device) pointers to arguments to the device (dp and hp might in -- fact have the same value on a unified-memory system). */ -- CUDA_CALL_ASSERT (cuMemcpy, (CUdeviceptr) dp, (CUdeviceptr) hp, -- mapnum * sizeof (void *)); -+ { -+ bool default_dim_p[GOMP_DIM_MAX]; -+ for (i = 0; i != GOMP_DIM_MAX; i++) -+ default_dim_p[i] = !dims[i]; -+ -+ if (!CUDA_CALL_EXISTS (cuOccupancyMaxPotentialBlockSize)) -+ { -+ for (i = 0; i != GOMP_DIM_MAX; i++) -+ if (default_dim_p[i]) -+ dims[i] = nvthd->ptx_dev->default_dims[i]; -+ -+ if (default_dim_p[GOMP_DIM_VECTOR]) -+ dims[GOMP_DIM_VECTOR] -+ = MIN (dims[GOMP_DIM_VECTOR], -+ (targ_fn->max_threads_per_block / warp_size -+ * warp_size)); -+ -+ if (default_dim_p[GOMP_DIM_WORKER]) -+ dims[GOMP_DIM_WORKER] -+ = MIN (dims[GOMP_DIM_WORKER], -+ targ_fn->max_threads_per_block / dims[GOMP_DIM_VECTOR]); -+ } -+ else -+ { -+ /* Handle the case that the compiler allows the runtime to choose -+ the vector-length conservatively, by ignoring -+ gomp_openacc_dims[GOMP_DIM_VECTOR]. TODO: actually handle -+ it. */ -+ int vectors = 0; -+ /* TODO: limit gomp_openacc_dims[GOMP_DIM_WORKER] such that that -+ gomp_openacc_dims[GOMP_DIM_WORKER] * actual_vectors does not -+ exceed targ_fn->max_threads_per_block. */ -+ int workers = gomp_openacc_dims[GOMP_DIM_WORKER]; -+ int gangs = gomp_openacc_dims[GOMP_DIM_GANG]; -+ int grids, blocks; -+ -+ CUDA_CALL_ASSERT (cuOccupancyMaxPotentialBlockSize, &grids, -+ &blocks, function, NULL, 0, -+ dims[GOMP_DIM_WORKER] * dims[GOMP_DIM_VECTOR]); -+ GOMP_PLUGIN_debug (0, "cuOccupancyMaxPotentialBlockSize: " -+ "grid = %d, block = %d\n", grids, blocks); -+ -+ /* Keep the num_gangs proportional to the block size. In -+ the case were a block size is limited by shared-memory -+ or the register file capacity, the runtime will not -+ excessively over assign gangs to the multiprocessor -+ units if their state is going to be swapped out even -+ more than necessary. The constant factor 2 is there to -+ prevent threads from idling when there is insufficient -+ work for them. */ -+ if (gangs == 0) -+ gangs = 2 * grids * (blocks / warp_size); -+ -+ if (vectors == 0) -+ vectors = warp_size; -+ -+ if (workers == 0) -+ { -+ int actual_vectors = (default_dim_p[GOMP_DIM_VECTOR] -+ ? vectors -+ : dims[GOMP_DIM_VECTOR]); -+ workers = blocks / actual_vectors; -+ workers = MAX (workers, 1); -+ /* If we need a per-worker barrier ... . */ -+ if (actual_vectors > 32) -+ /* Don't use more barriers than available. */ -+ workers = MIN (workers, 15); -+ } -+ -+ for (i = 0; i != GOMP_DIM_MAX; i++) -+ if (default_dim_p[i]) -+ switch (i) -+ { -+ case GOMP_DIM_GANG: dims[i] = gangs; break; -+ case GOMP_DIM_WORKER: dims[i] = workers; break; -+ case GOMP_DIM_VECTOR: dims[i] = vectors; break; -+ default: GOMP_PLUGIN_fatal ("invalid dim"); -+ } -+ } -+ } -+ } -+ -+ /* Check if the accelerator has sufficient hardware resources to -+ launch the offloaded kernel. */ -+ if (dims[GOMP_DIM_WORKER] * dims[GOMP_DIM_VECTOR] -+ > targ_fn->max_threads_per_block) -+ { -+ const char *msg -+ = ("The Nvidia accelerator has insufficient resources to launch '%s'" -+ " with num_workers = %d and vector_length = %d" -+ "; " -+ "recompile the program with 'num_workers = x and vector_length = y'" -+ " on that offloaded region or '-fopenacc-dim=:x:y' where" -+ " x * y <= %d" -+ ".\n"); -+ GOMP_PLUGIN_fatal (msg, targ_fn->launch->fn, dims[GOMP_DIM_WORKER], -+ dims[GOMP_DIM_VECTOR], targ_fn->max_threads_per_block); -+ } -+ -+ /* Check if the accelerator has sufficient barrier resources to -+ launch the offloaded kernel. */ -+ if (dims[GOMP_DIM_WORKER] > 15 && dims[GOMP_DIM_VECTOR] > 32) -+ { -+ const char *msg -+ = ("The Nvidia accelerator has insufficient barrier resources to launch" -+ " '%s' with num_workers = %d and vector_length = %d" -+ "; " -+ "recompile the program with 'num_workers = x' on that offloaded" -+ " region or '-fopenacc-dim=:x:' where x <= 15" -+ "; " -+ "or, recompile the program with 'vector_length = 32' on that" -+ " offloaded region or '-fopenacc-dim=::32'" -+ ".\n"); -+ GOMP_PLUGIN_fatal (msg, targ_fn->launch->fn, dims[GOMP_DIM_WORKER], -+ dims[GOMP_DIM_VECTOR]); -+ } -+ -+ if (mapnum > 0) -+ { -+ /* This reserves a chunk of a pre-allocated page of memory mapped on both -+ the host and the device. HP is a host pointer to the new chunk, and DP is -+ the corresponding device pointer. */ -+ pthread_mutex_lock (&ptx_event_lock); -+ dp = map_push (dev_str, mapnum * sizeof (void *)); -+ pthread_mutex_unlock (&ptx_event_lock); -+ -+ GOMP_PLUGIN_debug (0, " %s: prepare mappings\n", __FUNCTION__); -+ -+ /* Copy the array of arguments to the mapped page. */ -+ hp = alloca(sizeof(void *) * mapnum); -+ for (i = 0; i < mapnum; i++) -+ ((void **) hp)[i] = devaddrs[i]; -+ -+ /* Copy the (device) pointers to arguments to the device */ -+ CUDA_CALL_ASSERT (cuMemcpyHtoD, dp, hp, -+ mapnum * sizeof (void *)); -+ } -+ - GOMP_PLUGIN_debug (0, " %s: kernel %s: launch" - " gangs=%u, workers=%u, vectors=%u\n", - __FUNCTION__, targ_fn->launch->fn, dims[GOMP_DIM_GANG], -@@ -1239,7 +1426,8 @@ nvptx_exec (void (*fn), size_t mapnum, v - - CUDA_CALL_ASSERT (cuEventRecord, *e, dev_str->stream); - -- event_add (PTX_EVT_KNL, e, (void *)dev_str, 0); -+ if (mapnum > 0) -+ event_add (PTX_EVT_KNL, e, (void *)dev_str, 0); - } - #else - r = CUDA_CALL_NOCHECK (cuCtxSynchronize, ); -@@ -1256,7 +1444,10 @@ nvptx_exec (void (*fn), size_t mapnum, v - #ifndef DISABLE_ASYNC - if (async < acc_async_noval) - #endif -- map_pop (dev_str); -+ { -+ if (mapnum > 0) -+ map_pop (dev_str); -+ } - } - - void * openacc_get_current_cuda_context (void); -@@ -1415,9 +1606,8 @@ nvptx_async_test (int async) - struct ptx_stream *s; - - s = select_stream_for_async (async, pthread_self (), false, NULL); -- - if (!s) -- GOMP_PLUGIN_fatal ("unknown async %d", async); -+ return 1; - - r = CUDA_CALL_NOCHECK (cuStreamQuery, s->stream); - if (r == CUDA_SUCCESS) -@@ -1472,7 +1662,7 @@ nvptx_wait (int async) - - s = select_stream_for_async (async, pthread_self (), false, NULL); - if (!s) -- GOMP_PLUGIN_fatal ("unknown async %d", async); -+ return; - - CUDA_CALL_ASSERT (cuStreamSynchronize, s->stream); - -@@ -1486,16 +1676,17 @@ nvptx_wait_async (int async1, int async2 - struct ptx_stream *s1, *s2; - pthread_t self = pthread_self (); - -+ s1 = select_stream_for_async (async1, self, false, NULL); -+ if (!s1) -+ return; -+ - /* The stream that is waiting (rather than being waited for) doesn't - necessarily have to exist already. */ - s2 = select_stream_for_async (async2, self, true, NULL); - -- s1 = select_stream_for_async (async1, self, false, NULL); -- if (!s1) -- GOMP_PLUGIN_fatal ("invalid async 1\n"); -- -+ /* A stream is always synchronized with itself. */ - if (s1 == s2) -- GOMP_PLUGIN_fatal ("identical parameters"); -+ return; - - e = (CUevent *) GOMP_PLUGIN_malloc (sizeof (CUevent)); - -@@ -1629,8 +1820,14 @@ nvptx_set_cuda_stream (int async, void * - pthread_t self = pthread_self (); - struct nvptx_thread *nvthd = nvptx_thread (); - -- if (async < 0) -- GOMP_PLUGIN_fatal ("bad async %d", async); -+ /* Due to the "null_stream" usage for "acc_async_sync", this cannot be used -+ to change the stream handle associated with "acc_async_sync". */ -+ if (async == acc_async_sync) -+ { -+ GOMP_PLUGIN_debug (0, "Refusing request to set CUDA stream associated" -+ " with \"acc_async_sync\"\n"); -+ return 0; -+ } - - pthread_mutex_lock (&nvthd->ptx_dev->stream_lock); - -@@ -1739,6 +1936,12 @@ GOMP_OFFLOAD_fini_device (int n) - instantiated_devices--; - } - -+ if (instantiated_devices == 0) -+ { -+ free (ptx_devices); -+ ptx_devices = NULL; -+ } -+ - pthread_mutex_unlock (&ptx_dev_lock); - return true; - } ---- libgomp/plugin/configfrag.ac.jj 2018-04-25 09:40:31.914655581 +0200 -+++ libgomp/plugin/configfrag.ac 2019-05-07 18:46:36.533109624 +0200 -@@ -26,8 +26,6 @@ - # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - # . - --offload_targets= --AC_SUBST(offload_targets) - plugin_support=yes - AC_CHECK_LIB(dl, dlsym, , [plugin_support=no]) - if test x"$plugin_support" = xyes; then -@@ -59,7 +57,11 @@ AC_ARG_WITH(cuda-driver-lib, - [AS_HELP_STRING([--with-cuda-driver-lib=PATH], - [specify directory for the installed CUDA driver library])]) - case "x$with_cuda_driver" in -- x | xno) ;; -+ x) ;; -+ xno) -+ CUDA_DRIVER_INCLUDE=no -+ CUDA_DRIVER_LIB=no -+ ;; - *) CUDA_DRIVER_INCLUDE=$with_cuda_driver/include - CUDA_DRIVER_LIB=$with_cuda_driver/lib - ;; -@@ -70,10 +72,12 @@ fi - if test "x$with_cuda_driver_lib" != x; then - CUDA_DRIVER_LIB=$with_cuda_driver_lib - fi --if test "x$CUDA_DRIVER_INCLUDE" != x; then -+if test "x$CUDA_DRIVER_INCLUDE" != x \ -+ && test "x$CUDA_DRIVER_INCLUDE" != xno; then - CUDA_DRIVER_CPPFLAGS=-I$CUDA_DRIVER_INCLUDE - fi --if test "x$CUDA_DRIVER_LIB" != x; then -+if test "x$CUDA_DRIVER_LIB" != x \ -+ && test "x$CUDA_DRIVER_LIB" != xno; then - CUDA_DRIVER_LDFLAGS=-L$CUDA_DRIVER_LIB - fi - -@@ -133,7 +137,13 @@ AC_SUBST(PLUGIN_HSA_CPPFLAGS) - AC_SUBST(PLUGIN_HSA_LDFLAGS) - AC_SUBST(PLUGIN_HSA_LIBS) - --# Get offload targets and path to install tree of offloading compiler. -+# Parse '--enable-offload-targets', figure out the corresponding libgomp -+# plugins, and configure to find the corresponding offload compilers. -+# 'offload_plugins' and 'offload_targets' will be populated in the same order. -+offload_plugins= -+offload_targets= -+AC_SUBST(offload_plugins) -+AC_SUBST(offload_targets) - offload_additional_options= - offload_additional_lib_paths= - AC_SUBST(offload_additional_options) -@@ -152,10 +152,10 @@ if test x"$enable_offload_targets" != x; - for tgt in `echo $enable_offload_targets | sed -e 's#,# #g'`; do - tgt_dir=`echo $tgt | grep '=' | sed 's/.*=//'` - tgt=`echo $tgt | sed 's/=.*//'` -- tgt_name= -+ tgt_plugin= - case $tgt in - *-intelmic-* | *-intelmicemul-*) -- tgt_name=intelmic -+ tgt_plugin=intelmic - ;; - nvptx*) - case "${target}" in -@@ -167,30 +167,35 @@ if test x"$enable_offload_targets" != x; - PLUGIN_NVPTX=0 - ;; - *) -- tgt_name=nvptx -+ tgt_plugin=nvptx - PLUGIN_NVPTX=$tgt -- PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS -- PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS -- PLUGIN_NVPTX_LIBS='-lcuda' -+ if test "x$CUDA_DRIVER_LIB" != xno \ -+ && test "x$CUDA_DRIVER_LIB" != xno; then -+ PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS -+ PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS -+ PLUGIN_NVPTX_LIBS='-lcuda' - -- PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS -- CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS" -- PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS -- LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS" -- PLUGIN_NVPTX_save_LIBS=$LIBS -- LIBS="$PLUGIN_NVPTX_LIBS $LIBS" -- AC_LINK_IFELSE( -- [AC_LANG_PROGRAM( -- [#include "cuda.h"], -- [CUresult r = cuCtxPushCurrent (NULL);])], -- [PLUGIN_NVPTX=1]) -- CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS -- LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS -- LIBS=$PLUGIN_NVPTX_save_LIBS -+ PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS -+ CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS" -+ PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS -+ LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS" -+ PLUGIN_NVPTX_save_LIBS=$LIBS -+ LIBS="$PLUGIN_NVPTX_LIBS $LIBS" -+ AC_LINK_IFELSE( -+ [AC_LANG_PROGRAM( -+ [#include "cuda.h"], -+ [CUresult r = cuCtxPushCurrent (NULL);])], -+ [PLUGIN_NVPTX=1]) -+ CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS -+ LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS -+ LIBS=$PLUGIN_NVPTX_save_LIBS -+ fi - case $PLUGIN_NVPTX in - nvptx*) -- if test "x$CUDA_DRIVER_INCLUDE" = x \ -- && test "x$CUDA_DRIVER_LIB" = x; then -+ if (test "x$CUDA_DRIVER_INCLUDE" = x \ -+ || test "x$CUDA_DRIVER_INCLUDE" = xno) \ -+ && (test "x$CUDA_DRIVER_LIB" = x \ -+ || test "x$CUDA_DRIVER_LIB" = xno); then - PLUGIN_NVPTX=1 - PLUGIN_NVPTX_CPPFLAGS='-I$(srcdir)/plugin/cuda' - PLUGIN_NVPTX_LIBS='-ldl' -@@ -191,7 +206,7 @@ if test x"$enable_offload_targets" != x; - PLUGIN_HSA=0 - ;; - *) -- tgt_name=hsa -+ tgt_plugin=hsa - PLUGIN_HSA=$tgt - PLUGIN_HSA_CPPFLAGS=$HSA_RUNTIME_CPPFLAGS - PLUGIN_HSA_LDFLAGS="$HSA_RUNTIME_LDFLAGS" -@@ -209,7 +224,7 @@ if test x"$enable_offload_targets" != x; - LDFLAGS=$PLUGIN_HSA_save_LDFLAGS - LIBS=$PLUGIN_HSA_save_LIBS - case $PLUGIN_HSA in -- hsa*) -+ hsa*) - HSA_PLUGIN=0 - AC_MSG_ERROR([HSA run-time package required for HSA support]) - ;; -@@ -226,16 +241,19 @@ if test x"$enable_offload_targets" != x; - AC_MSG_ERROR([unknown offload target specified]) - ;; - esac -- if test x"$tgt_name" = x; then -- # Don't configure libgomp for this offloading target if we don't build -- # the corresponding plugin. -+ if test x"$tgt_plugin" = x; then -+ # Not configuring libgomp for this offload target if we're not building -+ # the corresponding offload plugin. - continue -- elif test x"$offload_targets" = x; then -- offload_targets=$tgt_name -+ elif test x"$offload_plugins" = x; then -+ offload_plugins=$tgt_plugin -+ offload_targets=$tgt - else -- offload_targets=$offload_targets,$tgt_name -+ offload_plugins=$offload_plugins,$tgt_plugin -+ offload_targets=$offload_targets,$tgt - fi -- if test "$tgt_name" = hsa; then -+ # Configure additional search paths. -+ if test "$tgt_plugin" = hsa; then - # Offloading compilation is all handled by the target compiler. - : - elif test x"$tgt_dir" != x; then -@@ -247,8 +265,8 @@ if test x"$enable_offload_targets" != x; - fi - done - fi --AC_DEFINE_UNQUOTED(OFFLOAD_TARGETS, "$offload_targets", -- [Define to offload targets, separated by commas.]) -+AC_DEFINE_UNQUOTED(OFFLOAD_PLUGINS, "$offload_plugins", -+ [Define to offload plugins, separated by commas.]) - AM_CONDITIONAL([PLUGIN_NVPTX], [test $PLUGIN_NVPTX = 1]) - AC_DEFINE_UNQUOTED([PLUGIN_NVPTX], [$PLUGIN_NVPTX], - [Define to 1 if the NVIDIA plugin is built, 0 if not.]) ---- libgomp/affinity-fmt.c.jj 2019-05-07 18:46:36.285113585 +0200 -+++ libgomp/affinity-fmt.c 2019-05-07 18:46:36.285113585 +0200 -@@ -0,0 +1,495 @@ -+/* Copyright (C) 2018-2019 Free Software Foundation, Inc. -+ Contributed by Jakub Jelinek . -+ -+ This file is part of the GNU Offloading and Multi Processing Library -+ (libgomp). -+ -+ Libgomp is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+#include "libgomp.h" -+#include -+#include -+#include -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#ifdef HAVE_INTTYPES_H -+# include /* For PRIx64. */ -+#endif -+#ifdef HAVE_UNAME -+#include -+#endif -+ -+void -+gomp_print_string (const char *str, size_t len) -+{ -+ fwrite (str, 1, len, stderr); -+} -+ -+void -+gomp_set_affinity_format (const char *format, size_t len) -+{ -+ if (len < gomp_affinity_format_len) -+ memcpy (gomp_affinity_format_var, format, len); -+ else -+ { -+ char *p; -+ if (gomp_affinity_format_len) -+ p = gomp_realloc (gomp_affinity_format_var, len + 1); -+ else -+ p = gomp_malloc (len + 1); -+ memcpy (p, format, len); -+ gomp_affinity_format_var = p; -+ gomp_affinity_format_len = len + 1; -+ } -+ gomp_affinity_format_var[len] = '\0'; -+} -+ -+void -+omp_set_affinity_format (const char *format) -+{ -+ gomp_set_affinity_format (format, strlen (format)); -+} -+ -+size_t -+omp_get_affinity_format (char *buffer, size_t size) -+{ -+ size_t len = strlen (gomp_affinity_format_var); -+ if (size) -+ { -+ if (len < size) -+ memcpy (buffer, gomp_affinity_format_var, len + 1); -+ else -+ { -+ memcpy (buffer, gomp_affinity_format_var, size - 1); -+ buffer[size - 1] = '\0'; -+ } -+ } -+ return len; -+} -+ -+void -+gomp_display_string (char *buffer, size_t size, size_t *ret, -+ const char *str, size_t len) -+{ -+ size_t r = *ret; -+ if (size && r < size) -+ { -+ size_t l = len; -+ if (size - r < len) -+ l = size - r; -+ memcpy (buffer + r, str, l); -+ } -+ *ret += len; -+ if (__builtin_expect (r > *ret, 0)) -+ gomp_fatal ("overflow in omp_capture_affinity"); -+} -+ -+static void -+gomp_display_repeat (char *buffer, size_t size, size_t *ret, -+ char c, size_t len) -+{ -+ size_t r = *ret; -+ if (size && r < size) -+ { -+ size_t l = len; -+ if (size - r < len) -+ l = size - r; -+ memset (buffer + r, c, l); -+ } -+ *ret += len; -+ if (__builtin_expect (r > *ret, 0)) -+ gomp_fatal ("overflow in omp_capture_affinity"); -+} -+ -+static void -+gomp_display_num (char *buffer, size_t size, size_t *ret, -+ bool zero, bool right, size_t sz, char *buf) -+{ -+ size_t l = strlen (buf); -+ if (sz == (size_t) -1 || l >= sz) -+ { -+ gomp_display_string (buffer, size, ret, buf, l); -+ return; -+ } -+ if (zero) -+ { -+ if (buf[0] == '-') -+ gomp_display_string (buffer, size, ret, buf, 1); -+ else if (buf[0] == '0' && buf[1] == 'x') -+ gomp_display_string (buffer, size, ret, buf, 2); -+ gomp_display_repeat (buffer, size, ret, '0', sz - l); -+ if (buf[0] == '-') -+ gomp_display_string (buffer, size, ret, buf + 1, l - 1); -+ else if (buf[0] == '0' && buf[1] == 'x') -+ gomp_display_string (buffer, size, ret, buf + 2, l - 2); -+ else -+ gomp_display_string (buffer, size, ret, buf, l); -+ } -+ else if (right) -+ { -+ gomp_display_repeat (buffer, size, ret, ' ', sz - l); -+ gomp_display_string (buffer, size, ret, buf, l); -+ } -+ else -+ { -+ gomp_display_string (buffer, size, ret, buf, l); -+ gomp_display_repeat (buffer, size, ret, ' ', sz - l); -+ } -+} -+ -+static void -+gomp_display_int (char *buffer, size_t size, size_t *ret, -+ bool zero, bool right, size_t sz, int num) -+{ -+ char buf[3 * sizeof (int) + 2]; -+ sprintf (buf, "%d", num); -+ gomp_display_num (buffer, size, ret, zero, right, sz, buf); -+} -+ -+static void -+gomp_display_string_len (char *buffer, size_t size, size_t *ret, -+ bool right, size_t sz, char *str, size_t len) -+{ -+ if (sz == (size_t) -1 || len >= sz) -+ { -+ gomp_display_string (buffer, size, ret, str, len); -+ return; -+ } -+ -+ if (right) -+ { -+ gomp_display_repeat (buffer, size, ret, ' ', sz - len); -+ gomp_display_string (buffer, size, ret, str, len); -+ } -+ else -+ { -+ gomp_display_string (buffer, size, ret, str, len); -+ gomp_display_repeat (buffer, size, ret, ' ', sz - len); -+ } -+} -+ -+static void -+gomp_display_hostname (char *buffer, size_t size, size_t *ret, -+ bool right, size_t sz) -+{ -+#ifdef HAVE_GETHOSTNAME -+ { -+ char buf[256]; -+ char *b = buf; -+ size_t len = 256; -+ do -+ { -+ b[len - 1] = '\0'; -+ if (gethostname (b, len - 1) == 0) -+ { -+ size_t l = strlen (b); -+ if (l < len - 1) -+ { -+ gomp_display_string_len (buffer, size, ret, -+ right, sz, b, l); -+ if (b != buf) -+ free (b); -+ return; -+ } -+ } -+ if (len == 1048576) -+ break; -+ len = len * 2; -+ if (len == 512) -+ b = gomp_malloc (len); -+ else -+ b = gomp_realloc (b, len); -+ } -+ while (1); -+ if (b != buf) -+ free (b); -+ } -+#endif -+#ifdef HAVE_UNAME -+ { -+ struct utsname buf; -+ if (uname (&buf) == 0) -+ { -+ gomp_display_string_len (buffer, size, ret, right, sz, -+ buf.nodename, strlen (buf.nodename)); -+ return; -+ } -+ } -+#endif -+ gomp_display_string_len (buffer, size, ret, right, sz, "node", 4); -+} -+ -+struct affinity_types_struct { -+ char long_str[18]; -+ char long_len; -+ char short_c; }; -+ -+static struct affinity_types_struct affinity_types[] = -+{ -+#define AFFINITY_TYPE(l, s) \ -+ { #l, sizeof (#l) - 1, s } -+ AFFINITY_TYPE (team_num, 't'), -+ AFFINITY_TYPE (num_teams, 'T'), -+ AFFINITY_TYPE (nesting_level, 'L'), -+ AFFINITY_TYPE (thread_num, 'n'), -+ AFFINITY_TYPE (num_threads, 'N'), -+ AFFINITY_TYPE (ancestor_tnum, 'a'), -+ AFFINITY_TYPE (host, 'H'), -+ AFFINITY_TYPE (process_id, 'P'), -+ AFFINITY_TYPE (native_thread_id, 'i'), -+ AFFINITY_TYPE (thread_affinity, 'A') -+#undef AFFINITY_TYPE -+}; -+ -+size_t -+gomp_display_affinity (char *buffer, size_t size, -+ const char *format, gomp_thread_handle handle, -+ struct gomp_team_state *ts, unsigned int place) -+{ -+ size_t ret = 0; -+ do -+ { -+ const char *p = strchr (format, '%'); -+ bool zero = false; -+ bool right = false; -+ size_t sz = -1; -+ char c; -+ int val; -+ if (p == NULL) -+ p = strchr (format, '\0'); -+ if (p != format) -+ gomp_display_string (buffer, size, &ret, -+ format, p - format); -+ if (*p == '\0') -+ break; -+ p++; -+ if (*p == '%') -+ { -+ gomp_display_string (buffer, size, &ret, "%", 1); -+ format = p + 1; -+ continue; -+ } -+ if (*p == '0') -+ { -+ zero = true; -+ p++; -+ if (*p != '.') -+ gomp_fatal ("leading zero not followed by dot in affinity format"); -+ } -+ if (*p == '.') -+ { -+ right = true; -+ p++; -+ } -+ if (*p >= '1' && *p <= '9') -+ { -+ char *end; -+ sz = strtoul (p, &end, 10); -+ p = end; -+ } -+ else if (zero || right) -+ gomp_fatal ("leading zero or right justification in affinity format " -+ "requires size"); -+ c = *p; -+ if (c == '{') -+ { -+ int i; -+ for (i = 0; -+ i < sizeof (affinity_types) / sizeof (affinity_types[0]); ++i) -+ if (strncmp (p + 1, affinity_types[i].long_str, -+ affinity_types[i].long_len) == 0 -+ && p[affinity_types[i].long_len + 1] == '}') -+ { -+ c = affinity_types[i].short_c; -+ p += affinity_types[i].long_len + 1; -+ break; -+ } -+ if (c == '{') -+ { -+ char *q = strchr (p + 1, '}'); -+ if (q) -+ gomp_fatal ("unsupported long type name '%.*s' in affinity " -+ "format", (int) (q - (p + 1)), p + 1); -+ else -+ gomp_fatal ("unterminated long type name '%s' in affinity " -+ "format", p + 1); -+ } -+ } -+ switch (c) -+ { -+ case 't': -+ val = omp_get_team_num (); -+ goto do_int; -+ case 'T': -+ val = omp_get_num_teams (); -+ goto do_int; -+ case 'L': -+ val = ts->level; -+ goto do_int; -+ case 'n': -+ val = ts->team_id; -+ goto do_int; -+ case 'N': -+ val = ts->team ? ts->team->nthreads : 1; -+ goto do_int; -+ case 'a': -+ val = ts->team ? ts->team->prev_ts.team_id : -1; -+ goto do_int; -+ case 'H': -+ gomp_display_hostname (buffer, size, &ret, right, sz); -+ break; -+ case 'P': -+#ifdef HAVE_GETPID -+ val = getpid (); -+#else -+ val = 0; -+#endif -+ goto do_int; -+ case 'i': -+#if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__) -+ { -+ char buf[3 * (sizeof (handle) + sizeof (uintptr_t) + sizeof (int)) -+ + 4]; -+ /* This macro returns expr unmodified for integral or pointer -+ types and 0 for anything else (e.g. aggregates). */ -+#define gomp_nonaggregate(expr) \ -+ __builtin_choose_expr (__builtin_classify_type (expr) == 1 \ -+ || __builtin_classify_type (expr) == 5, expr, 0) -+ /* This macro returns expr unmodified for integral types, -+ (uintptr_t) (expr) for pointer types and 0 for anything else -+ (e.g. aggregates). */ -+#define gomp_integral(expr) \ -+ __builtin_choose_expr (__builtin_classify_type (expr) == 5, \ -+ (uintptr_t) gomp_nonaggregate (expr), \ -+ gomp_nonaggregate (expr)) -+ -+ if (sizeof (gomp_integral (handle)) == sizeof (unsigned long)) -+ sprintf (buf, "0x%lx", (unsigned long) gomp_integral (handle)); -+#if defined (HAVE_INTTYPES_H) && defined (PRIx64) -+ else if (sizeof (gomp_integral (handle)) == sizeof (uint64_t)) -+ sprintf (buf, "0x%" PRIx64, (uint64_t) gomp_integral (handle)); -+#else -+ else if (sizeof (gomp_integral (handle)) -+ == sizeof (unsigned long long)) -+ sprintf (buf, "0x%llx", -+ (unsigned long long) gomp_integral (handle)); -+#endif -+ else -+ sprintf (buf, "0x%x", (unsigned int) gomp_integral (handle)); -+ gomp_display_num (buffer, size, &ret, zero, right, sz, buf); -+ break; -+ } -+#else -+ val = 0; -+ goto do_int; -+#endif -+ case 'A': -+ if (sz == (size_t) -1) -+ gomp_display_affinity_place (buffer, size, &ret, -+ place - 1); -+ else if (right) -+ { -+ size_t len = 0; -+ gomp_display_affinity_place (NULL, 0, &len, place - 1); -+ if (len < sz) -+ gomp_display_repeat (buffer, size, &ret, ' ', sz - len); -+ gomp_display_affinity_place (buffer, size, &ret, place - 1); -+ } -+ else -+ { -+ size_t start = ret; -+ gomp_display_affinity_place (buffer, size, &ret, place - 1); -+ if (ret - start < sz) -+ gomp_display_repeat (buffer, size, &ret, ' ', sz - (ret - start)); -+ } -+ break; -+ do_int: -+ gomp_display_int (buffer, size, &ret, zero, right, sz, val); -+ break; -+ default: -+ gomp_fatal ("unsupported type %c in affinity format", c); -+ } -+ format = p + 1; -+ } -+ while (1); -+ return ret; -+} -+ -+size_t -+omp_capture_affinity (char *buffer, size_t size, const char *format) -+{ -+ struct gomp_thread *thr = gomp_thread (); -+ size_t ret -+ = gomp_display_affinity (buffer, size, -+ format && *format -+ ? format : gomp_affinity_format_var, -+ gomp_thread_self (), &thr->ts, thr->place); -+ if (size) -+ { -+ if (ret >= size) -+ buffer[size - 1] = '\0'; -+ else -+ buffer[ret] = '\0'; -+ } -+ return ret; -+} -+ialias (omp_capture_affinity) -+ -+void -+omp_display_affinity (const char *format) -+{ -+ char buf[512]; -+ char *b; -+ size_t ret = ialias_call (omp_capture_affinity) (buf, sizeof buf, format); -+ if (ret < sizeof buf) -+ { -+ buf[ret] = '\n'; -+ gomp_print_string (buf, ret + 1); -+ return; -+ } -+ b = gomp_malloc (ret + 1); -+ ialias_call (omp_capture_affinity) (b, ret + 1, format); -+ b[ret] = '\n'; -+ gomp_print_string (b, ret + 1); -+ free (b); -+} -+ -+void -+gomp_display_affinity_thread (gomp_thread_handle handle, -+ struct gomp_team_state *ts, unsigned int place) -+{ -+ char buf[512]; -+ char *b; -+ size_t ret = gomp_display_affinity (buf, sizeof buf, gomp_affinity_format_var, -+ handle, ts, place); -+ if (ret < sizeof buf) -+ { -+ buf[ret] = '\n'; -+ gomp_print_string (buf, ret + 1); -+ return; -+ } -+ b = gomp_malloc (ret + 1); -+ gomp_display_affinity (b, ret + 1, gomp_affinity_format_var, -+ handle, ts, place); -+ b[ret] = '\n'; -+ gomp_print_string (b, ret + 1); -+ free (b); -+} ---- libgomp/single.c.jj 2018-04-25 09:40:31.870655561 +0200 -+++ libgomp/single.c 2019-05-07 18:46:36.536109576 +0200 -@@ -47,7 +47,7 @@ GOMP_single_start (void) - return __sync_bool_compare_and_swap (&team->single_count, single_count, - single_count + 1L); - #else -- bool ret = gomp_work_share_start (false); -+ bool ret = gomp_work_share_start (0); - if (ret) - gomp_work_share_init_done (); - gomp_work_share_end_nowait (); -@@ -68,7 +68,7 @@ GOMP_single_copy_start (void) - bool first; - void *ret; - -- first = gomp_work_share_start (false); -+ first = gomp_work_share_start (0); - - if (first) - { ---- libgomp/oacc-cuda.c.jj 2018-04-25 09:40:31.321655307 +0200 -+++ libgomp/oacc-cuda.c 2019-05-07 18:46:36.528109704 +0200 -@@ -58,7 +58,7 @@ acc_get_cuda_stream (int async) - { - struct goacc_thread *thr = goacc_thread (); - -- if (async < 0) -+ if (!async_valid_p (async)) - return NULL; - - if (thr && thr->dev && thr->dev->openacc.cuda.get_stream_func) -@@ -72,7 +72,7 @@ acc_set_cuda_stream (int async, void *st - { - struct goacc_thread *thr; - -- if (async < 0 || stream == NULL) -+ if (!async_valid_p (async) || stream == NULL) - return 0; - - goacc_lazy_initialize (); ---- libgomp/work.c.jj 2018-04-25 09:40:31.925655587 +0200 -+++ libgomp/work.c 2019-05-07 18:46:36.548109384 +0200 -@@ -76,7 +76,15 @@ alloc_work_share (struct gomp_team *team - #endif - - team->work_share_chunk *= 2; -+ /* Allocating gomp_work_share structures aligned is just an -+ optimization, don't do it when using the fallback method. */ -+#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC -+ ws = gomp_aligned_alloc (__alignof (struct gomp_work_share), -+ team->work_share_chunk -+ * sizeof (struct gomp_work_share)); -+#else - ws = gomp_malloc (team->work_share_chunk * sizeof (struct gomp_work_share)); -+#endif - ws->next_alloc = team->work_shares[0].next_alloc; - team->work_shares[0].next_alloc = ws; - team->work_share_list_alloc = &ws[1]; -@@ -90,30 +98,35 @@ alloc_work_share (struct gomp_team *team - This shouldn't touch the next_alloc field. */ - - void --gomp_init_work_share (struct gomp_work_share *ws, bool ordered, -+gomp_init_work_share (struct gomp_work_share *ws, size_t ordered, - unsigned nthreads) - { - gomp_mutex_init (&ws->lock); - if (__builtin_expect (ordered, 0)) - { --#define INLINE_ORDERED_TEAM_IDS_CNT \ -- ((sizeof (struct gomp_work_share) \ -- - offsetof (struct gomp_work_share, inline_ordered_team_ids)) \ -- / sizeof (((struct gomp_work_share *) 0)->inline_ordered_team_ids[0])) -- -- if (nthreads > INLINE_ORDERED_TEAM_IDS_CNT) -- ws->ordered_team_ids -- = gomp_malloc (nthreads * sizeof (*ws->ordered_team_ids)); -+#define INLINE_ORDERED_TEAM_IDS_SIZE \ -+ (sizeof (struct gomp_work_share) \ -+ - offsetof (struct gomp_work_share, inline_ordered_team_ids)) -+ -+ if (__builtin_expect (ordered != 1, 0)) -+ { -+ ordered += nthreads * sizeof (*ws->ordered_team_ids) - 1; -+ ordered = ordered + __alignof__ (long long) - 1; -+ ordered &= ~(__alignof__ (long long) - 1); -+ } -+ else -+ ordered = nthreads * sizeof (*ws->ordered_team_ids); -+ if (ordered > INLINE_ORDERED_TEAM_IDS_SIZE) -+ ws->ordered_team_ids = gomp_malloc (ordered); - else - ws->ordered_team_ids = ws->inline_ordered_team_ids; -- memset (ws->ordered_team_ids, '\0', -- nthreads * sizeof (*ws->ordered_team_ids)); -+ memset (ws->ordered_team_ids, '\0', ordered); - ws->ordered_num_used = 0; - ws->ordered_owner = -1; - ws->ordered_cur = 0; - } - else -- ws->ordered_team_ids = NULL; -+ ws->ordered_team_ids = ws->inline_ordered_team_ids; - gomp_ptrlock_init (&ws->next_ws, NULL); - ws->threads_completed = 0; - } -@@ -166,7 +179,7 @@ free_work_share (struct gomp_team *team, - if this was the first thread to reach this point. */ - - bool --gomp_work_share_start (bool ordered) -+gomp_work_share_start (size_t ordered) - { - struct gomp_thread *thr = gomp_thread (); - struct gomp_team *team = thr->ts.team; -@@ -178,7 +191,7 @@ gomp_work_share_start (bool ordered) - ws = gomp_malloc (sizeof (*ws)); - gomp_init_work_share (ws, ordered, 1); - thr->ts.work_share = ws; -- return ws; -+ return true; - } - - ws = thr->ts.work_share; ---- include/gomp-constants.h.jj 2018-04-25 09:40:39.757659209 +0200 -+++ include/gomp-constants.h 2019-05-07 18:57:33.333627031 +0200 -@@ -189,6 +189,7 @@ enum gomp_map_kind - #define GOMP_TASK_FLAG_GRAINSIZE (1 << 9) - #define GOMP_TASK_FLAG_IF (1 << 10) - #define GOMP_TASK_FLAG_NOGROUP (1 << 11) -+#define GOMP_TASK_FLAG_REDUCTION (1 << 12) - - /* GOMP_target{_ext,update_ext,enter_exit_data} flags argument. */ - #define GOMP_TARGET_FLAG_NOWAIT (1 << 0) -@@ -196,6 +197,18 @@ enum gomp_map_kind - /* Internal to libgomp. */ - #define GOMP_TARGET_FLAG_UPDATE (1U << 31) - -+ -+/* OpenACC construct flags. */ -+ -+/* Force host fallback execution. */ -+#define GOACC_FLAG_HOST_FALLBACK (1 << 0) -+ -+/* For legacy reasons, in the ABI, the GOACC_FLAGs are encoded as an inverted -+ bitmask. */ -+#define GOACC_FLAGS_MARSHAL_OP BIT_NOT_EXPR -+#define GOACC_FLAGS_UNMARSHAL(X) (~(X)) -+ -+ - /* Versions of libgomp and device-specific plugins. GOMP_VERSION - should be incremented whenever an ABI-incompatible change is introduced - to the plugin interface defined in libgomp/libgomp.h. */ -@@ -251,6 +264,12 @@ enum gomp_map_kind - at most and shifted by this many bits. */ - #define GOMP_TARGET_ARG_VALUE_SHIFT 16 - -+/* Dependence types in omp_depend_t objects. */ -+#define GOMP_DEPEND_IN 1 -+#define GOMP_DEPEND_OUT 2 -+#define GOMP_DEPEND_INOUT 3 -+#define GOMP_DEPEND_MUTEXINOUTSET 4 -+ - /* HSA specific data structures. */ - - /* Identifiers of device-specific target arguments. */ diff --git a/SOURCES/gcc8-libgomp-testsuite.patch b/SOURCES/gcc8-libgomp-testsuite.patch deleted file mode 100644 index 502ee22..0000000 --- a/SOURCES/gcc8-libgomp-testsuite.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- libgomp/testsuite/libgomp-test-support.exp.in.jj 2018-04-25 09:40:31.323655308 +0200 -+++ libgomp/testsuite/libgomp-test-support.exp.in 2019-04-25 20:01:50.028243827 +0200 -@@ -2,4 +2,5 @@ set cuda_driver_include "@CUDA_DRIVER_IN - set cuda_driver_lib "@CUDA_DRIVER_LIB@" - set hsa_runtime_lib "@HSA_RUNTIME_LIB@" - -+set offload_plugins "@offload_plugins@" - set offload_targets "@offload_targets@" ---- libgomp/testsuite/lib/libgomp.exp.jj 2018-04-25 09:40:31.584655429 +0200 -+++ libgomp/testsuite/lib/libgomp.exp 2019-05-24 11:41:51.015822702 +0200 -@@ -40,7 +40,7 @@ load_file libgomp-test-support.exp - # Populate offload_targets_s (offloading targets separated by a space), and - # offload_targets_s_openacc (the same, but with OpenACC names; OpenACC spells - # some of them a little differently). --set offload_targets_s [split $offload_targets ","] -+set offload_targets_s [split $offload_plugins ","] - set offload_targets_s_openacc {} - foreach offload_target_openacc $offload_targets_s { - # Translate to OpenACC names, or skip if not yet supported. -@@ -137,8 +137,8 @@ proc libgomp_init { args } { - - # Add liboffloadmic build directory in LD_LIBRARY_PATH to support - # non-fallback testing for Intel MIC targets -- global offload_targets -- if { [string match "*,intelmic,*" ",$offload_targets,"] } { -+ global offload_plugins -+ if { [string match "*,intelmic,*" ",$offload_plugins,"] } { - append always_ld_library_path ":${blddir}/../liboffloadmic/.libs" - append always_ld_library_path ":${blddir}/../liboffloadmic/plugin/.libs" - # libstdc++ is required by liboffloadmic -@@ -362,8 +362,8 @@ proc check_effective_target_offload_devi - # Return 1 if configured for nvptx offloading. - - proc check_effective_target_openacc_nvidia_accel_configured { } { -- global offload_targets -- if { ![string match "*,nvptx,*" ",$offload_targets,"] } { -+ global offload_plugins -+ if { ![string match "*,nvptx,*" ",$offload_plugins,"] } { - return 0 - } - # PR libgomp/65099: Currently, we only support offloading in 64-bit diff --git a/SOURCES/gcc8-libstdc++-make_shared.patch b/SOURCES/gcc8-libstdc++-make_shared.patch deleted file mode 100644 index 59256d8..0000000 --- a/SOURCES/gcc8-libstdc++-make_shared.patch +++ /dev/null @@ -1,61 +0,0 @@ -commit 79fa567e234585dc6a71f9bd069101c993513f3e -Author: Jonathan Wakely -Date: Thu Apr 22 15:46:51 2021 +0100 - - libstdc++: Reject std::make_shared [PR 99006] - - Prior to C++20 it should be ill-formed to use std::make_shared with an - array type (and we don't support the C++20 feature to make it valid yet - anyway). - - libstdc++-v3/ChangeLog: - - PR libstdc++/99006 - * include/bits/shared_ptr.h (allocate_shared): Assert that _Tp - is not an array type. - * include/bits/shared_ptr_base.h (__allocate_shared): Likewise. - * testsuite/20_util/shared_ptr/creation/99006.cc: New test. - - (cherry picked from commit 55650236cd97d81f42f9fdb4f6bcb12babafe51f) - -diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h -index 281600b2901..4ddc52ae723 100644 ---- a/libstdc++-v3/include/bits/shared_ptr.h -+++ b/libstdc++-v3/include/bits/shared_ptr.h -@@ -698,6 +698,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - inline shared_ptr<_Tp> - allocate_shared(const _Alloc& __a, _Args&&... __args) - { -+ static_assert(!is_array<_Tp>::value, "make_shared not supported"); -+ - return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a}, - std::forward<_Args>(__args)...); - } -diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h -index 0367c2d51a5..8af6e9fb11c 100644 ---- a/libstdc++-v3/include/bits/shared_ptr_base.h -+++ b/libstdc++-v3/include/bits/shared_ptr_base.h -@@ -1822,6 +1822,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - inline __shared_ptr<_Tp, _Lp> - __allocate_shared(const _Alloc& __a, _Args&&... __args) - { -+ static_assert(!is_array<_Tp>::value, "make_shared not supported"); -+ - return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a}, - std::forward<_Args>(__args)...); - } -diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc -new file mode 100644 -index 00000000000..d5f7a5da5e9 ---- /dev/null -+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc -@@ -0,0 +1,9 @@ -+// FIXME: This should use { target { ! c++20 } } -+// { dg-do compile } -+ -+#include -+ -+auto p = std::make_shared(2); // { dg-error "here" } -+auto q = std::make_shared(1, 2); // { dg-error "here" } -+ -+// { dg-prune-output "static assertion failed" } diff --git a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-48362.patch b/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-48362.patch deleted file mode 100644 index 1f0239e..0000000 --- a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-48362.patch +++ /dev/null @@ -1,30 +0,0 @@ -The change is based on: - -commit 190c644c06369766aa2537851ddbf83b1231b65b -Author: Philipp Fent -Date: Sun Sep 4 20:47:34 2022 +0200 - - libstdc++: Fix pretty printer tests of tuple indexes - -but it is adapted to GCC8 since it does not have the tuple inheritance change, -which is: - -commit 91e6226f880b048275a7ceedef716e159c7cefd9 -Author: Jonathan Wakely -Date: Fri Aug 7 17:13:56 2020 +0100 - - libstdc++: Remove inheritance from elements in std::tuple - -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc -index cc91803e247..af335d0d3c7 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc -@@ -29,7 +29,7 @@ main() - // { dg-final { note-test t1 {empty std::tuple} } } - - std::tuple> t2{ "Johnny", 5, {} }; --// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {> = empty std::tuple, }}} } } -+// { dg-final { regexp-test t2 {std::tuple containing = {\[0\] = "Johnny", \[1\] = 5, \[2\] = {> = empty std::tuple, }}} } } - - std::cout << "\n"; - return 0; // Mark SPOT diff --git a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx11.patch b/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx11.patch deleted file mode 100644 index 9aca53b..0000000 --- a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx11.patch +++ /dev/null @@ -1,27 +0,0 @@ -NullablePointer support not available, so drop these tests. - -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc.new -index 2f75d12..6fb19c3 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc -@@ -145,20 +145,6 @@ main() - std::unique_ptr& rarrptr = arrptr; - // { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } } - -- struct Deleter -- { -- int deleter_member = -1; -- using pointer = __gnu_test::NullablePointer; -- void operator()(pointer) const noexcept { } -- }; -- static_assert( !std::is_empty(), "Deleter is not empty" ); -- static_assert( std::is_empty(), "but pointer is empty" ); -- -- std::unique_ptr empty_ptr; --// { dg-final { note-test empty_ptr {std::unique_ptr = {get() = {}}} } } -- std::unique_ptr& rempty_ptr = empty_ptr; --// { dg-final { note-test rempty_ptr {std::unique_ptr = {get() = {}}} } } -- - struct Deleter_pr103086 - { - int deleter_member = -1; diff --git a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx17.patch b/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx17.patch deleted file mode 100644 index 8928cc3..0000000 --- a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests-cxx17.patch +++ /dev/null @@ -1,44 +0,0 @@ -Revert this commit for libstdc++-prettyprinters (only cxx17, 91997 -doesn't exist in this tree) since gcc8 does not default to c++17. The -context has been adapted but the change should be exact: - -commit 0498d2d09a2364aae1e6b5e085c8ebb8fc517684 -Author: Jonathan Wakely -Date: Mon May 10 16:22:54 2021 +0100 - - libstdc++: Remove redundant -std=gnu++17 option from remaining tests - -Also remove the filesystem tests since it's not supported by RHEL8 gcc. - -diff --git b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -index 72c66d3b785..98e21e963fe 100644 ---- b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -+++ a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -@@ -1,4 +1,4 @@ --// { dg-options "-g -O0" } -+// { dg-options "-g -O0 -std=gnu++17" } - // { dg-do run { target c++17 } } - - // Copyright (C) 2014-2024 Free Software Foundation, Inc. -@@ -18,7 +18,6 @@ - // with this library; see the file COPYING3. If not see - // . - --#include - #include - #include - #include -@@ -120,13 +119,6 @@ main() - // { dg-final { regexp-test q {std::shared_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } - // { dg-final { regexp-test wq {std::weak_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } - -- std::filesystem::path path0; --// { dg-final { note-test path0 {filesystem::path ""} } } -- std::filesystem::path path1("filename"); --// { dg-final { note-test path1 {filesystem::path "filename"} } } -- std::filesystem::path path2("/dir/."); --// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } } -- - std::cout << "\n"; - return 0; // Mark SPOT - } diff --git a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests.patch b/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests.patch deleted file mode 100644 index 5ba0a5d..0000000 --- a/SOURCES/gcc8-libstdc++-prettyprinter-update-14-tests.patch +++ /dev/null @@ -1,458 +0,0 @@ - .../testsuite/libstdc++-prettyprinters/compat.cc | 11 +- - .../testsuite/libstdc++-prettyprinters/cxx11.cc | 129 +++++++++++++++------ - .../testsuite/libstdc++-prettyprinters/cxx17.cc | 50 +++++--- - .../libstdc++-prettyprinters/filesystem-ts.cc | 8 +- - .../libstdc++-prettyprinters/libfundts.cc | 26 +++-- - 5 files changed, 146 insertions(+), 78 deletions(-) - -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc -index 81e0ce7213f..604a6f6415b 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc -@@ -1,8 +1,7 @@ - // { dg-options "-g -O0" } - // { dg-do run { target c++11 } } --// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } } - --// Copyright (C) 2014-2019 Free Software Foundation, Inc. -+// Copyright (C) 2014-2024 Free Software Foundation, Inc. - // - // This file is part of the GNU ISO C++ Library. This library is free - // software; you can redistribute it and/or modify it under the -@@ -103,13 +102,13 @@ main() - using std::optional; - - optional o; --// { dg-final { note-test o {std::optional [no contained value]} } } -+// { dg-final { note-test o {std::optional [no contained value]} } } - optional ob{false}; --// { dg-final { note-test ob {std::optional = {[contained value] = false}} } } -+// { dg-final { note-test ob {std::optional = {[contained value] = false}} } } - optional oi{5}; --// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } } -+// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } } - optional op{nullptr}; --// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } } -+// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } } - - __builtin_puts(""); - return 0; // Mark SPOT -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc -index 9a90d8d91db..2f75d12703c 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc -@@ -1,8 +1,7 @@ - // { dg-do run { target c++11 } } - // { dg-options "-g -O0" } --// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } } - --// Copyright (C) 2011-2018 Free Software Foundation, Inc. -+// Copyright (C) 2011-2024 Free Software Foundation, Inc. - // - // This file is part of the GNU ISO C++ Library. This library is free - // software; you can redistribute it and/or modify it under the -@@ -25,6 +24,10 @@ - #include - #include - #include -+#include -+#include -+#include -+#include "../util/testsuite_allocator.h" // NullablePointer - - typedef std::tuple ExTuple; - -@@ -60,84 +63,74 @@ struct datum - - std::unique_ptr global; - --struct Deleter --{ -- // Deleter is not an empty class: -- int deleter_member = -1; -- // But pointer is an empty class: -- struct pointer -- { -- pointer(const void* = nullptr) { } -- explicit operator bool() const noexcept { return false; } -- friend bool operator==(pointer, pointer) noexcept { return true; } -- friend bool operator!=(pointer, pointer) noexcept { return false; } -- }; -- void operator()(pointer) const noexcept { } -+struct custom_cat : std::error_category { -+ const char* name() const noexcept { return "miaow"; } -+ std::string message(int) const { return ""; } - }; - - int - main() - { - std::forward_list efl; --// { dg-final { note-test efl "empty std::forward_list" } } -+// { dg-final { regexp-test efl "empty std::(__debug::)?forward_list" } } - - std::forward_list &refl = efl; --// { dg-final { note-test refl "empty std::forward_list" } } -+// { dg-final { regexp-test refl "empty std::(__debug::)?forward_list" } } - - std::forward_list fl; - fl.push_front(2); - fl.push_front(1); --// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } } -+// { dg-final { regexp-test fl {std::(__debug::)?forward_list = {\[0\] = 1, \[1\] = 2}} } } - - std::forward_list &rfl = fl; --// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } } -+// { dg-final { regexp-test rfl {std::(__debug::)?forward_list = {\[0\] = 1, \[1\] = 2}} } } - - std::unordered_map eum; --// { dg-final { note-test eum "std::unordered_map with 0 elements" } } -+// { dg-final { regexp-test eum "std::(__debug::)?unordered_map with 0 elements" } } - std::unordered_map &reum = eum; --// { dg-final { note-test reum "std::unordered_map with 0 elements" } } -+// { dg-final { regexp-test reum "std::(__debug::)?unordered_map with 0 elements" } } - - std::unordered_multimap eumm; --// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } } -+// { dg-final { regexp-test eumm "std::(__debug::)?unordered_multimap with 0 elements" } } - std::unordered_multimap &reumm = eumm; --// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } } -+// { dg-final { regexp-test reumm "std::(__debug::)?unordered_multimap with 0 elements" } } - - std::unordered_set eus; --// { dg-final { note-test eus "std::unordered_set with 0 elements" } } -+// { dg-final { regexp-test eus "std::(__debug::)?unordered_set with 0 elements" } } - std::unordered_set &reus = eus; --// { dg-final { note-test reus "std::unordered_set with 0 elements" } } -+// { dg-final { regexp-test reus "std::(__debug::)?unordered_set with 0 elements" } } - - std::unordered_multiset eums; --// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } } -+// { dg-final { regexp-test eums "std::(__debug::)?unordered_multiset with 0 elements" } } - std::unordered_multiset &reums = eums; --// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } } -+// { dg-final { regexp-test reums "std::(__debug::)?unordered_multiset with 0 elements" } } - - std::unordered_map uom; - uom[5] = "three"; - uom[3] = "seven"; --// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } } -+// { dg-final { regexp-test uom {std::(__debug::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } } - - std::unordered_map &ruom = uom; --// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } } -+// { dg-final { regexp-test ruom {std::(__debug::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } } - - std::unordered_multimap uomm; - uomm.insert(std::pair (5, "three")); - uomm.insert(std::pair (5, "seven")); --// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } } -+// { dg-final { regexp-test uomm {std::(__debug::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } } - std::unordered_multimap &ruomm = uomm; --// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } } -+// { dg-final { regexp-test ruomm {std::(__debug::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } } - - std::unordered_set uos; - uos.insert(5); --// { dg-final { note-test uos {std::unordered_set with 1 element = {[0] = 5}} } } -+// { dg-final { regexp-test uos {std::(__debug::)?unordered_set with 1 element = {\[0\] = 5}} } } - std::unordered_set &ruos = uos; --// { dg-final { note-test ruos {std::unordered_set with 1 element = {[0] = 5}} } } -+// { dg-final { regexp-test ruos {std::(__debug::)?unordered_set with 1 element = {\[0\] = 5}} } } - - std::unordered_multiset uoms; - uoms.insert(5); --// { dg-final { note-test uoms {std::unordered_multiset with 1 element = {[0] = 5}} } } -+// { dg-final { regexp-test uoms {std::(__debug::)?unordered_multiset with 1 element = {\[0\] = 5}} } } - std::unordered_multiset &ruoms = uoms; --// { dg-final { note-test ruoms {std::unordered_multiset with 1 element = {[0] = 5}} } } -+// { dg-final { regexp-test ruoms {std::(__debug::)?unordered_multiset with 1 element = {\[0\] = 5}} } } - - std::unique_ptr uptr (new datum); - uptr->s = "hi bob"; -@@ -152,15 +145,77 @@ main() - std::unique_ptr& rarrptr = arrptr; - // { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } } - -+ struct Deleter -+ { -+ int deleter_member = -1; -+ using pointer = __gnu_test::NullablePointer; -+ void operator()(pointer) const noexcept { } -+ }; -+ static_assert( !std::is_empty(), "Deleter is not empty" ); -+ static_assert( std::is_empty(), "but pointer is empty" ); -+ - std::unique_ptr empty_ptr; - // { dg-final { note-test empty_ptr {std::unique_ptr = {get() = {}}} } } - std::unique_ptr& rempty_ptr = empty_ptr; - // { dg-final { note-test rempty_ptr {std::unique_ptr = {get() = {}}} } } - -+ struct Deleter_pr103086 -+ { -+ int deleter_member = -1; -+ void operator()(int*) const noexcept { } -+ }; -+ -+ std::unique_ptr uniq_ptr; -+// { dg-final { note-test uniq_ptr {std::unique_ptr = {get() = 0x0}} } } -+ std::unique_ptr& runiq_ptr = uniq_ptr; -+// { dg-final { note-test runiq_ptr {std::unique_ptr = {get() = 0x0}} } } -+ - ExTuple tpl(6,7); --// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } } -+// { dg-final { note-test tpl {std::tuple containing = {[0] = 6, [1] = 7}} } } - ExTuple &rtpl = tpl; --// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } } -+// { dg-final { note-test rtpl {std::tuple containing = {[0] = 6, [1] = 7}} } } -+ -+ std::error_code e0; -+ // { dg-final { note-test e0 {std::error_code = { }} } } -+ std::error_condition ec0; -+ // { dg-final { note-test ec0 {std::error_condition = { }} } } -+ std::error_code einval = std::make_error_code(std::errc::invalid_argument); -+ // { dg-final { note-test einval {std::error_code = {"generic": EINVAL}} } } -+ std::error_condition ecinval = std::make_error_condition(std::errc::invalid_argument); -+ // { dg-final { note-test ecinval {std::error_condition = {"generic": EINVAL}} } } -+ -+ custom_cat cat; -+ std::error_code emiaow(42, cat); -+ // { dg-final { note-test emiaow {std::error_code = {custom_cat: 42}} } } -+ std::error_condition ecmiaow(42, cat); -+ // { dg-final { note-test ecmiaow {std::error_condition = {custom_cat: 42}} } } -+ -+ std::error_code ecio = std::make_error_code(std::io_errc::stream); -+ // { dg-final { note-test ecio {std::error_code = {"io": stream}} } } -+ std::error_code ecfut0 = std::make_error_code(std::future_errc{}); -+ // { dg-final { note-test ecfut0 {std::error_code = {"future": 0}} } } -+ -+ std::initializer_list emptyIl = {}; -+ // { dg-final { note-test emptyIl {std::initializer_list of length 0} } } -+ std::initializer_list il = {3, 4}; -+ // { dg-final { note-test il {std::initializer_list of length 2 = {3, 4}} } } -+ -+ std::atomic ai{100}; -+ // { dg-final { note-test ai {std::atomic = { 100 }} } } -+ long l{}; -+ std::atomic ap{&l}; -+ // { dg-final { regexp-test ap {std::atomic.long \*. = { 0x.* }} } } -+ struct Value { int i, j; }; -+ std::atomic av{{8, 9}}; -+ // { dg-final { note-test av {std::atomic = { {i = 8, j = 9} }} } } -+ -+ std::integral_constant one; -+ // { dg-final { note-test one {std::integral_constant} } } -+ std::integral_constant truth; -+ // { dg-final { note-test truth {std::true_type} } } -+ std::integral_constant lies; -+ // { dg-final { note-test lies {std::false_type} } } -+ - placeholder(""); // Mark SPOT - use(efl); - use(fl); -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -index 0c7cb4c9bb6..c8b70622bef 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc -@@ -1,8 +1,7 @@ --// { dg-options "-g -O0 -std=gnu++17" } -+// { dg-options "-g -O0" } - // { dg-do run { target c++17 } } --// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } } - --// Copyright (C) 2014-2018 Free Software Foundation, Inc. -+// Copyright (C) 2014-2024 Free Software Foundation, Inc. - // - // This file is part of the GNU ISO C++ Library. This library is free - // software; you can redistribute it and/or modify it under the -@@ -19,9 +18,7 @@ - // with this library; see the file COPYING3. If not see - // . - --// Type printers only recognize the old std::string for now. --#define _GLIBCXX_USE_CXX11_ABI 0 -- -+#include - #include - #include - #include -@@ -41,6 +38,11 @@ using std::unordered_set; - using std::shared_ptr; - using std::weak_ptr; - -+struct X { -+ X(int) { } -+ X(const X&) { } // not trivially-copyable -+}; -+ - int - main() - { -@@ -48,18 +50,18 @@ main() - // { dg-final { note-test str "\"string\"" } } - - optional o; --// { dg-final { note-test o {std::optional [no contained value]} } } -+// { dg-final { note-test o {std::optional [no contained value]} } } - optional ob{false}; --// { dg-final { note-test ob {std::optional = {[contained value] = false}} } } -+// { dg-final { note-test ob {std::optional = {[contained value] = false}} } } - optional oi{5}; --// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } } -+// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } } - optional op{nullptr}; --// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } } -+// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } } - optional> om; - om = std::map{ {1, 2.}, {3, 4.}, {5, 6.} }; --// { dg-final { note-test om {std::optional> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } -+// { dg-final { regexp-test om {std::optional containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } } - optional os{ "stringy" }; --// { dg-final { note-test os {std::optional = {[contained value] = "stringy"}} } } -+// { dg-final { note-test os {std::optional = {[contained value] = "stringy"}} } } - - any a; - // { dg-final { note-test a {std::any [no contained value]} } } -@@ -74,22 +76,25 @@ main() - any as2("stringiest"); - // { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } } - any am = *om; --// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } -+// { dg-final { regexp-test am {std::any containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } } -+ struct local_type { int i = 99; }; -+ any al = local_type{}; -+// { dg-final { note-test al {std::any containing local_type = {[contained value] = {i = 99}}} } } - - struct S { operator int() { throw 42; }}; - variant v0; --// { dg-final { note-test v0 {std::variant [index 0] = {0}} } } -+// { dg-final { note-test v0 {std::variant [index 0] = {0}} } } - variant v1{ 0.5f }; --// { dg-final { note-test v1 {std::variant [index 0] = {0.5}} } } -- variant v2; -+// { dg-final { note-test v1 {std::variant [index 0] = {0.5}} } } -+ variant v2; - try { - v2.emplace<1>(S()); - } catch (int) { } --// { dg-final { note-test v2 {std::variant [no contained value]} } } -+// { dg-final { note-test v2 {std::variant [no contained value]} } } - variant v3{ 3 }; --// { dg-final { note-test v3 {std::variant [index 1] = {3}} } } -+// { dg-final { note-test v3 {std::variant [index 1] = {3}} } } - variant v4{ str }; --// { dg-final { note-test v4 {std::variant [index 2] = {"string"}} } } -+// { dg-final { note-test v4 {std::variant [index 2] = {"string"}} } } - - map m{ {1, "one"} }; - map::node_type n0; -@@ -115,6 +120,13 @@ main() - // { dg-final { regexp-test q {std::shared_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } - // { dg-final { regexp-test wq {std::weak_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } - -+ std::filesystem::path path0; -+// { dg-final { note-test path0 {filesystem::path ""} } } -+ std::filesystem::path path1("filename"); -+// { dg-final { note-test path1 {filesystem::path "filename"} } } -+ std::filesystem::path path2("/dir/."); -+// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } } -+ - std::cout << "\n"; - return 0; // Mark SPOT - } -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc -index 8a1398f6c85..9faeed02852 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc -@@ -2,7 +2,7 @@ - // { dg-do run { target c++11 } } - // { dg-require-filesystem-ts "" } - --// Copyright (C) 2020 Free Software Foundation, Inc. -+// Copyright (C) 2020-2024 Free Software Foundation, Inc. - // - // This file is part of the GNU ISO C++ Library. This library is free - // software; you can redistribute it and/or modify it under the -@@ -26,11 +26,11 @@ int - main() - { - std::experimental::filesystem::path path0; --// { dg-final { note-test path0 {filesystem::path ""} } } -+// { dg-final { note-test path0 {experimental::filesystem::path ""} } } - std::experimental::filesystem::path path1("filename"); --// { dg-final { note-test path1 {filesystem::path "filename"} } } -+// { dg-final { note-test path1 {experimental::filesystem::path "filename"} } } - std::experimental::filesystem::path path2("/dir/."); --// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } } -+// { dg-final { note-test path2 {experimental::filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } } - - std::cout << "\n"; - return 0; // Mark SPOT -diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc -index ea13ebe71ee..7a6ee8d281e 100644 ---- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc -+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc -@@ -1,8 +1,7 @@ - // { dg-do run { target c++14 } } - // { dg-options "-g -O0" } --// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } } - --// Copyright (C) 2014-2018 Free Software Foundation, Inc. -+// Copyright (C) 2014-2024 Free Software Foundation, Inc. - // - // This file is part of the GNU ISO C++ Library. This library is free - // software; you can redistribute it and/or modify it under the -@@ -19,9 +18,6 @@ - // with this library; see the file COPYING3. If not see - // . - --// Type printers only recognize the old std::string for now. --#define _GLIBCXX_USE_CXX11_ABI 0 -- - #include - #include - #include -@@ -36,22 +32,28 @@ using std::experimental::string_view; - int - main() - { -+ // Ensure debug info for std::string is issued in the local -+ // translation unit, so that GDB won't pick up any alternate -+ // std::string notion that might be present in libstdc++.so. -+ std::string bah = "hi"; -+ (void)bah; -+ - string_view str = "string"; - // { dg-final { note-test str "\"string\"" } } - - optional o; --// { dg-final { note-test o {std::experimental::optional [no contained value]} } } -+// { dg-final { note-test o {std::experimental::optional [no contained value]} } } - optional ob{false}; --// { dg-final { note-test ob {std::experimental::optional = {[contained value] = false}} } } -+// { dg-final { note-test ob {std::experimental::optional = {[contained value] = false}} } } - optional oi{5}; --// { dg-final { note-test oi {std::experimental::optional = {[contained value] = 5}} } } -+// { dg-final { note-test oi {std::experimental::optional = {[contained value] = 5}} } } - optional op{nullptr}; --// { dg-final { note-test op {std::experimental::optional = {[contained value] = 0x0}} } } -+// { dg-final { note-test op {std::experimental::optional = {[contained value] = 0x0}} } } - optional> om; - om = std::map{ {1, 2.}, {3, 4.}, {5, 6.} }; --// { dg-final { note-test om {std::experimental::optional> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } -+// { dg-final { regexp-test om {std::experimental::optional containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } } - optional os{ "stringy" }; --// { dg-final { note-test os {std::experimental::optional = {[contained value] = "stringy"}} } } -+// { dg-final { note-test os {std::experimental::optional = {[contained value] = "stringy"}} } } - - any a; - // { dg-final { note-test a {std::experimental::any [no contained value]} } } -@@ -66,7 +68,7 @@ main() - any as2("stringiest"); - // { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } } - any am = *om; --// { dg-final { note-test am {std::experimental::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } -+// { dg-final { regexp-test am {std::experimental::any containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } } - - std::cout << "\n"; - return 0; // Mark SPOT diff --git a/SOURCES/gcc8-libstdc++-prettyprinter-update-14.patch b/SOURCES/gcc8-libstdc++-prettyprinter-update-14.patch deleted file mode 100644 index f477ae1..0000000 --- a/SOURCES/gcc8-libstdc++-prettyprinter-update-14.patch +++ /dev/null @@ -1,4166 +0,0 @@ - libstdc++-v3/python/libstdcxx/v6/__init__.py | 4 +- - libstdc++-v3/python/libstdcxx/v6/printers.py | 2593 +++++++++++++++++++------- - libstdc++-v3/python/libstdcxx/v6/xmethods.py | 170 +- - 3 files changed, 2017 insertions(+), 750 deletions(-) - -diff --git a/libstdc++-v3/python/libstdcxx/v6/__init__.py b/libstdc++-v3/python/libstdcxx/v6/__init__.py -index b001c8520b6..f40acd922af 100644 ---- a/libstdc++-v3/python/libstdcxx/v6/__init__.py -+++ b/libstdc++-v3/python/libstdcxx/v6/__init__.py -@@ -1,4 +1,4 @@ --# Copyright (C) 2014-2018 Free Software Foundation, Inc. -+# Copyright (C) 2014-2024 Free Software Foundation, Inc. - - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -13,8 +13,6 @@ - # You should have received a copy of the GNU General Public License - # along with this program. If not, see . - --import gdb -- - # Load the xmethods if GDB supports them. - def gdb_has_xmethods(): - try: -diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py -index ba9bbc096a0..3026de35bbd 100644 ---- a/libstdc++-v3/python/libstdcxx/v6/printers.py -+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py -@@ -1,6 +1,6 @@ - # Pretty-printers for libstdc++. - --# Copyright (C) 2008-2018 Free Software Foundation, Inc. -+# Copyright (C) 2008-2024 Free Software Foundation, Inc. - - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -19,8 +19,10 @@ import gdb - import itertools - import re - import sys -+import errno -+import datetime - --### Python 2 + Python 3 compatibility code -+# Python 2 + Python 3 compatibility code - - # Resources about compatibility: - # -@@ -37,15 +39,16 @@ import sys - # - - if sys.version_info[0] > 2: -- ### Python 3 stuff -+ # Python 3 stuff - Iterator = object - # Python 3 folds these into the normal functions. - imap = map - izip = zip - # Also, int subsumes long - long = int -+ _utc_timezone = datetime.timezone.utc - else: -- ### Python 2 stuff -+ # Python 2 stuff - class Iterator: - """Compatibility mixin for iterators - -@@ -63,6 +66,20 @@ else: - # In Python 2, we still need these from itertools - from itertools import imap, izip - -+ # Python 2 does not provide the datetime.UTC singleton. -+ class UTC(datetime.tzinfo): -+ """Concrete tzinfo class representing the UTC time zone.""" -+ -+ def utcoffset(self, dt): -+ return datetime.timedelta(0) -+ -+ def tzname(self, dt): -+ return "UTC" -+ -+ def dst(self, dt): -+ return datetime.timedelta(0) -+ _utc_timezone = UTC() -+ - # Try to use the new-style pretty-printing if available. - _use_gdb_pp = True - try: -@@ -79,14 +96,22 @@ try: - except ImportError: - pass - -+# Use the base class if available. -+if hasattr(gdb, 'ValuePrinter'): -+ printer_base = gdb.ValuePrinter -+else: -+ printer_base = object -+ - # Starting with the type ORIG, search for the member type NAME. This - # handles searching upward through superclasses. This is needed to - # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615. -+ -+ - def find_type(orig, name): - typ = orig.strip_typedefs() - while True: -- # Strip cv-qualifiers. PR 67440. -- search = '%s::%s' % (typ.unqualified(), name) -+ # Use Type.tag to ignore cv-qualifiers. PR 67440. -+ search = '%s::%s' % (typ.tag, name) - try: - return gdb.lookup_type(search) - except RuntimeError: -@@ -94,39 +119,131 @@ def find_type(orig, name): - # The type was not found, so try the superclass. We only need - # to check the first superclass, so we don't bother with - # anything fancier here. -- field = typ.fields()[0] -- if not field.is_base_class: -+ fields = typ.fields() -+ if len(fields) and fields[0].is_base_class: -+ typ = fields[0].type -+ else: - raise ValueError("Cannot find type %s::%s" % (str(orig), name)) -- typ = field.type -+ - - _versioned_namespace = '__8::' - --def is_specialization_of(type, template_name): -- "Test if a type is a given template instantiation." -+ -+def lookup_templ_spec(templ, *args): -+ """ -+ Lookup template specialization templ. -+ """ -+ t = '{}<{}>'.format(templ, ', '.join([str(a) for a in args])) -+ try: -+ return gdb.lookup_type(t) -+ except gdb.error as e: -+ # Type not found, try again in versioned namespace. -+ global _versioned_namespace -+ if _versioned_namespace not in templ: -+ t = t.replace('::', '::' + _versioned_namespace, 1) -+ try: -+ return gdb.lookup_type(t) -+ except gdb.error: -+ # If that also fails, rethrow the original exception -+ pass -+ raise e -+ -+# Use this to find container node types instead of find_type, -+# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91997 for details. -+def lookup_node_type(nodename, containertype): -+ """ -+ Lookup specialization of template nodename corresponding to containertype. -+ -+ nodename - The name of a class template, as a String -+ containertype - The container, as a gdb.Type -+ -+ Return a gdb.Type for the corresponding specialization of nodename, -+ or None if the type cannot be found. -+ -+ e.g. lookup_node_type('_List_node', gdb.lookup_type('std::list')) -+ will return a gdb.Type for the type std::_List_node. -+ """ -+ # If nodename is unqualified, assume it's in namespace std. -+ if '::' not in nodename: -+ nodename = 'std::' + nodename -+ # Use either containertype's value_type or its first template argument. -+ try: -+ valtype = find_type(containertype, 'value_type') -+ except: -+ valtype = containertype.template_argument(0) -+ valtype = valtype.strip_typedefs() -+ try: -+ return lookup_templ_spec(nodename, valtype) -+ except gdb.error: -+ # For debug mode containers the node is in std::__cxx1998. -+ if is_member_of_namespace(nodename, 'std'): -+ if is_member_of_namespace(containertype, 'std::__cxx1998', -+ 'std::__debug', '__gnu_debug'): -+ nodename = nodename.replace('::', '::__cxx1998::', 1) -+ try: -+ return lookup_templ_spec(nodename, valtype) -+ except gdb.error: -+ pass -+ return None -+ -+ -+def is_member_of_namespace(typ, *namespaces): -+ """ -+ Test whether a type is a member of one of the specified namespaces. -+ The type can be specified as a string or a gdb.Type object. -+ """ -+ if isinstance(typ, gdb.Type): -+ typ = str(typ) -+ typ = strip_versioned_namespace(typ) -+ for namespace in namespaces: -+ if typ.startswith(namespace + '::'): -+ return True -+ return False -+ -+ -+def is_specialization_of(x, template_name): -+ """ -+ Test whether a type is a specialization of the named class template. -+ The type can be specified as a string or a gdb.Type object. -+ The template should be the name of a class template as a string, -+ without any 'std' qualification. -+ """ - global _versioned_namespace -- if _versioned_namespace: -- return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None -- return re.match('^std::%s<.*>$' % template_name, type) is not None -+ if isinstance(x, gdb.Type): -+ x = x.tag -+ template_name = '(%s)?%s' % (_versioned_namespace, template_name) -+ return re.match('^std::%s<.*>$' % template_name, x) is not None -+ - - def strip_versioned_namespace(typename): - global _versioned_namespace -- if _versioned_namespace: -- return typename.replace(_versioned_namespace, '') -- return typename -+ return typename.replace(_versioned_namespace, '') -+ -+ -+def strip_fundts_namespace(typ): -+ """Remove "fundamentals_vN" inline namespace from qualified type name.""" -+ pattern = r'^std::experimental::fundamentals_v\d::' -+ repl = 'std::experimental::' -+ if sys.version_info[0] == 2: -+ return re.sub(pattern, repl, typ, 1) -+ else: # Technically this needs Python 3.1 but nobody should be using 3.0 -+ return re.sub(pattern, repl, typ, count=1) -+ - - def strip_inline_namespaces(type_str): -- "Remove known inline namespaces from the canonical name of a type." -+ """Remove known inline namespaces from the canonical name of a type.""" - type_str = strip_versioned_namespace(type_str) - type_str = type_str.replace('std::__cxx11::', 'std::') - expt_ns = 'std::experimental::' - for lfts_ns in ('fundamentals_v1', 'fundamentals_v2'): -- type_str = type_str.replace(expt_ns+lfts_ns+'::', expt_ns) -+ type_str = type_str.replace(expt_ns + lfts_ns + '::', expt_ns) - fs_ns = expt_ns + 'filesystem::' -- type_str = type_str.replace(fs_ns+'v1::', fs_ns) -+ type_str = type_str.replace(fs_ns + 'v1::', fs_ns) - return type_str - -+ - def get_template_arg_list(type_obj): -- "Return a type's template arguments as a list" -+ """Return a type's template arguments as a list.""" - n = 0 - template_args = [] - while True: -@@ -136,78 +253,140 @@ def get_template_arg_list(type_obj): - return template_args - n += 1 - -+ - class SmartPtrIterator(Iterator): -- "An iterator for smart pointer types with a single 'child' value" -+ """An iterator for smart pointer types with a single 'child' value.""" - - def __init__(self, val): -- self.val = val -+ self._val = val - - def __iter__(self): - return self - - def __next__(self): -- if self.val is None: -+ if self._val is None: - raise StopIteration -- self.val, val = None, self.val -+ self._val, val = None, self._val - return ('get()', val) - --class SharedPointerPrinter: -- "Print a shared_ptr or weak_ptr" - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -- self.pointer = val['_M_ptr'] -+class SharedPointerPrinter(printer_base): -+ """ -+ Print a shared_ptr, weak_ptr, atomic, or atomic. -+ """ -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ self._pointer = val['_M_ptr'] - -- def children (self): -- return SmartPtrIterator(self.pointer) -+ def children(self): -+ return SmartPtrIterator(self._pointer) -+ -+ # Return the _Sp_counted_base<>* that holds the refcounts. -+ def _get_refcounts(self): -+ if self._typename == 'std::atomic': -+ # A tagged pointer is stored as uintptr_t. -+ ptr_val = self._val['_M_refcount']['_M_val']['_M_i'] -+ ptr_val = ptr_val - (ptr_val % 2) # clear lock bit -+ ptr_type = find_type(self._val['_M_refcount'].type, 'pointer') -+ return ptr_val.cast(ptr_type) -+ return self._val['_M_refcount']['_M_pi'] - -- def to_string (self): -+ def to_string(self): - state = 'empty' -- refcounts = self.val['_M_refcount']['_M_pi'] -+ refcounts = self._get_refcounts() -+ targ = self._val.type.template_argument(0) -+ targ = strip_versioned_namespace(str(targ)) -+ - if refcounts != 0: - usecount = refcounts['_M_use_count'] - weakcount = refcounts['_M_weak_count'] - if usecount == 0: - state = 'expired, weak count %d' % weakcount - else: -- state = 'use count %d, weak count %d' % (usecount, weakcount - 1) -- return '%s<%s> (%s)' % (self.typename, str(self.val.type.template_argument(0)), state) -- --class UniquePointerPrinter: -- "Print a unique_ptr" -- -- def __init__ (self, typename, val): -- self.val = val -- impl_type = val.type.fields()[0].type.strip_typedefs() -- if is_specialization_of(str(impl_type), '__uniq_ptr_impl'): # New implementation -- tuple_member = val['_M_t']['_M_t'] -- elif is_specialization_of(str(impl_type), 'tuple'): -- tuple_member = val['_M_t'] -- else: -- raise ValueError("Unsupported implementation for unique_ptr: %s" % str(impl_type)) -- tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl -- tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base -- head_field = tuple_head_type.fields()[0] -- if head_field.name == '_M_head_impl': -- self.pointer = tuple_member['_M_head_impl'] -- elif head_field.is_base_class: -- self.pointer = tuple_member.cast(head_field.type) -- else: -- raise ValueError("Unsupported implementation for tuple in unique_ptr: %s" % str(impl_type)) -+ state = 'use count %d, weak count %d' % ( -+ usecount, weakcount - 1) -+ return '%s<%s> (%s)' % (self._typename, targ, state) -+ -+ -+def _tuple_impl_get(val): -+ """Return the tuple element stored in a _Tuple_impl base class.""" -+ bases = val.type.fields() -+ if not bases[-1].is_base_class: -+ raise ValueError( -+ "Unsupported implementation for std::tuple: %s" % str(val.type)) -+ # Get the _Head_base base class: -+ head_base = val.cast(bases[-1].type) -+ fields = head_base.type.fields() -+ if len(fields) == 0: -+ raise ValueError( -+ "Unsupported implementation for std::tuple: %s" % str(val.type)) -+ if fields[0].name == '_M_head_impl': -+ # The tuple element is the _Head_base::_M_head_impl data member. -+ return head_base['_M_head_impl'] -+ elif fields[0].is_base_class: -+ # The tuple element is an empty base class of _Head_base. -+ # Cast to that empty base class. -+ return head_base.cast(fields[0].type) -+ else: -+ raise ValueError( -+ "Unsupported implementation for std::tuple: %s" % str(val.type)) -+ -+ -+def tuple_get(n, val): -+ """Return the result of std::get(val) on a std::tuple.""" -+ tuple_size = len(get_template_arg_list(val.type)) -+ if n > tuple_size: -+ raise ValueError("Out of range index for std::get on std::tuple") -+ # Get the first _Tuple_impl<0, T...> base class: -+ node = val.cast(val.type.fields()[0].type) -+ while n > 0: -+ # Descend through the base classes until the Nth one. -+ node = node.cast(node.type.fields()[0].type) -+ n -= 1 -+ return _tuple_impl_get(node) -+ -+ -+def unique_ptr_get(val): -+ """Return the result of val.get() on a std::unique_ptr.""" -+ # std::unique_ptr contains a std::tuple, -+ # either as a direct data member _M_t (the old implementation) -+ # or within a data member of type __uniq_ptr_data. -+ impl_type = val.type.fields()[0].type.strip_typedefs() -+ # Check for new implementations first: -+ if is_specialization_of(impl_type, '__uniq_ptr_data') \ -+ or is_specialization_of(impl_type, '__uniq_ptr_impl'): -+ tuple_member = val['_M_t']['_M_t'] -+ elif is_specialization_of(impl_type, 'tuple'): -+ tuple_member = val['_M_t'] -+ else: -+ raise ValueError( -+ "Unsupported implementation for unique_ptr: %s" % str(impl_type)) -+ return tuple_get(0, tuple_member) -+ - -- def children (self): -- return SmartPtrIterator(self.pointer) -+class UniquePointerPrinter(printer_base): -+ """Print a unique_ptr.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ -+ def children(self): -+ return SmartPtrIterator(unique_ptr_get(self._val)) -+ -+ def to_string(self): -+ t = self._val.type.template_argument(0) -+ return 'std::unique_ptr<{}>'.format(str(t)) - -- def to_string (self): -- return ('std::unique_ptr<%s>' % (str(self.val.type.template_argument(0)))) - - def get_value_from_aligned_membuf(buf, valtype): -- """Returns the value held in a __gnu_cxx::__aligned_membuf.""" -+ """Return the value held in a __gnu_cxx::__aligned_membuf.""" - return buf['_M_storage'].address.cast(valtype.pointer()).dereference() - -+ - def get_value_from_list_node(node): -- """Returns the value held in an _List_node<_Val>""" -+ """Return the value held in an _List_node<_Val>.""" - try: - member = node.type.fields()[1].name - if member == '_M_data': -@@ -221,240 +400,281 @@ def get_value_from_list_node(node): - pass - raise ValueError("Unsupported implementation for %s" % str(node.type)) - --class StdListPrinter: -- "Print a std::list" -+ -+class StdListPrinter(printer_base): -+ """Print a std::list.""" - - class _iterator(Iterator): - def __init__(self, nodetype, head): -- self.nodetype = nodetype -- self.base = head['_M_next'] -- self.head = head.address -- self.count = 0 -+ self._nodetype = nodetype -+ self._base = head['_M_next'] -+ self._head = head.address -+ self._count = 0 - - def __iter__(self): - return self - - def __next__(self): -- if self.base == self.head: -+ if self._base == self._head: - raise StopIteration -- elt = self.base.cast(self.nodetype).dereference() -- self.base = elt['_M_next'] -- count = self.count -- self.count = self.count + 1 -+ elt = self._base.cast(self._nodetype).dereference() -+ self._base = elt['_M_next'] -+ count = self._count -+ self._count = self._count + 1 - val = get_value_from_list_node(elt) - return ('[%d]' % count, val) - - def __init__(self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - - def children(self): -- nodetype = find_type(self.val.type, '_Node') -- nodetype = nodetype.strip_typedefs().pointer() -- return self._iterator(nodetype, self.val['_M_impl']['_M_node']) -+ nodetype = lookup_node_type('_List_node', self._val.type).pointer() -+ return self._iterator(nodetype, self._val['_M_impl']['_M_node']) - - def to_string(self): -- if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: -- return 'empty %s' % (self.typename) -- return '%s' % (self.typename) -+ headnode = self._val['_M_impl']['_M_node'] -+ if headnode['_M_next'] == headnode.address: -+ return 'empty %s' % (self._typename) -+ return '%s' % (self._typename) - --class NodeIteratorPrinter: -- def __init__(self, typename, val, contname): -- self.val = val -- self.typename = typename -- self.contname = contname -+ -+class NodeIteratorPrinter(printer_base): -+ def __init__(self, typename, val, contname, nodename): -+ self._val = val -+ self._typename = typename -+ self._contname = contname -+ self._nodetype = lookup_node_type(nodename, val.type) - - def to_string(self): -- if not self.val['_M_node']: -- return 'non-dereferenceable iterator for std::%s' % (self.contname) -- nodetype = find_type(self.val.type, '_Node') -- nodetype = nodetype.strip_typedefs().pointer() -- node = self.val['_M_node'].cast(nodetype).dereference() -+ if not self._val['_M_node']: -+ return 'non-dereferenceable iterator for std::%s' % (self._contname) -+ node = self._val['_M_node'].cast( -+ self._nodetype.pointer()).dereference() - return str(get_value_from_list_node(node)) - -+ - class StdListIteratorPrinter(NodeIteratorPrinter): -- "Print std::list::iterator" -+ """Print std::list::iterator.""" - - def __init__(self, typename, val): -- NodeIteratorPrinter.__init__(self, typename, val, 'list') -+ NodeIteratorPrinter.__init__(self, typename, val, 'list', '_List_node') -+ - - class StdFwdListIteratorPrinter(NodeIteratorPrinter): -- "Print std::forward_list::iterator" -+ """Print std::forward_list::iterator.""" - - def __init__(self, typename, val): -- NodeIteratorPrinter.__init__(self, typename, val, 'forward_list') -+ NodeIteratorPrinter.__init__(self, typename, val, 'forward_list', -+ '_Fwd_list_node') - --class StdSlistPrinter: -- "Print a __gnu_cxx::slist" -+ -+class StdSlistPrinter(printer_base): -+ """Print a __gnu_cxx::slist.""" - - class _iterator(Iterator): - def __init__(self, nodetype, head): -- self.nodetype = nodetype -- self.base = head['_M_head']['_M_next'] -- self.count = 0 -+ self._nodetype = nodetype -+ self._base = head['_M_head']['_M_next'] -+ self._count = 0 - - def __iter__(self): - return self - - def __next__(self): -- if self.base == 0: -+ if self._base == 0: - raise StopIteration -- elt = self.base.cast(self.nodetype).dereference() -- self.base = elt['_M_next'] -- count = self.count -- self.count = self.count + 1 -+ elt = self._base.cast(self._nodetype).dereference() -+ self._base = elt['_M_next'] -+ count = self._count -+ self._count = self._count + 1 - return ('[%d]' % count, elt['_M_data']) - - def __init__(self, typename, val): -- self.val = val -+ self._val = val - - def children(self): -- nodetype = find_type(self.val.type, '_Node') -- nodetype = nodetype.strip_typedefs().pointer() -- return self._iterator(nodetype, self.val) -+ nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self._val.type) -+ return self._iterator(nodetype.pointer(), self._val) - - def to_string(self): -- if self.val['_M_head']['_M_next'] == 0: -+ if self._val['_M_head']['_M_next'] == 0: - return 'empty __gnu_cxx::slist' - return '__gnu_cxx::slist' - --class StdSlistIteratorPrinter: -- "Print __gnu_cxx::slist::iterator" -+ -+class StdSlistIteratorPrinter(printer_base): -+ """Print __gnu_cxx::slist::iterator.""" - - def __init__(self, typename, val): -- self.val = val -+ self._val = val - - def to_string(self): -- if not self.val['_M_node']: -+ if not self._val['_M_node']: - return 'non-dereferenceable iterator for __gnu_cxx::slist' -- nodetype = find_type(self.val.type, '_Node') -- nodetype = nodetype.strip_typedefs().pointer() -- return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data']) -+ nodetype = lookup_node_type( -+ '__gnu_cxx::_Slist_node', self._val.type).pointer() -+ return str(self._val['_M_node'].cast(nodetype).dereference()['_M_data']) -+ - --class StdVectorPrinter: -- "Print a std::vector" -+class StdVectorPrinter(printer_base): -+ """Print a std::vector.""" - - class _iterator(Iterator): -- def __init__ (self, start, finish, bitvec): -- self.bitvec = bitvec -+ def __init__(self, start, finish, bitvec): -+ self._bitvec = bitvec - if bitvec: -- self.item = start['_M_p'] -- self.so = start['_M_offset'] -- self.finish = finish['_M_p'] -- self.fo = finish['_M_offset'] -- itype = self.item.dereference().type -- self.isize = 8 * itype.sizeof -+ self._item = start['_M_p'] -+ self._so = 0 -+ self._finish = finish['_M_p'] -+ self._fo = finish['_M_offset'] -+ itype = self._item.dereference().type -+ self._isize = 8 * itype.sizeof - else: -- self.item = start -- self.finish = finish -- self.count = 0 -+ self._item = start -+ self._finish = finish -+ self._count = 0 - - def __iter__(self): - return self - - def __next__(self): -- count = self.count -- self.count = self.count + 1 -- if self.bitvec: -- if self.item == self.finish and self.so >= self.fo: -+ count = self._count -+ self._count = self._count + 1 -+ if self._bitvec: -+ if self._item == self._finish and self._so >= self._fo: - raise StopIteration -- elt = self.item.dereference() -- if elt & (1 << self.so): -- obit = 1 -- else: -- obit = 0 -- self.so = self.so + 1 -- if self.so >= self.isize: -- self.item = self.item + 1 -- self.so = 0 -- return ('[%d]' % count, obit) -+ elt = bool(self._item.dereference() & (1 << self._so)) -+ self._so = self._so + 1 -+ if self._so >= self._isize: -+ self._item = self._item + 1 -+ self._so = 0 -+ return ('[%d]' % count, elt) - else: -- if self.item == self.finish: -+ if self._item == self._finish: - raise StopIteration -- elt = self.item.dereference() -- self.item = self.item + 1 -+ elt = self._item.dereference() -+ self._item = self._item + 1 - return ('[%d]' % count, elt) - - def __init__(self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -- self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ self._is_bool = val.type.template_argument( -+ 0).code == gdb.TYPE_CODE_BOOL - - def children(self): -- return self._iterator(self.val['_M_impl']['_M_start'], -- self.val['_M_impl']['_M_finish'], -- self.is_bool) -+ return self._iterator(self._val['_M_impl']['_M_start'], -+ self._val['_M_impl']['_M_finish'], -+ self._is_bool) - - def to_string(self): -- start = self.val['_M_impl']['_M_start'] -- finish = self.val['_M_impl']['_M_finish'] -- end = self.val['_M_impl']['_M_end_of_storage'] -- if self.is_bool: -- start = self.val['_M_impl']['_M_start']['_M_p'] -- so = self.val['_M_impl']['_M_start']['_M_offset'] -- finish = self.val['_M_impl']['_M_finish']['_M_p'] -- fo = self.val['_M_impl']['_M_finish']['_M_offset'] -+ start = self._val['_M_impl']['_M_start'] -+ finish = self._val['_M_impl']['_M_finish'] -+ end = self._val['_M_impl']['_M_end_of_storage'] -+ if self._is_bool: -+ start = self._val['_M_impl']['_M_start']['_M_p'] -+ finish = self._val['_M_impl']['_M_finish']['_M_p'] -+ fo = self._val['_M_impl']['_M_finish']['_M_offset'] - itype = start.dereference().type - bl = 8 * itype.sizeof -- length = (bl - so) + bl * ((finish - start) - 1) + fo -+ length = bl * (finish - start) + fo - capacity = bl * (end - start) - return ('%s of length %d, capacity %d' -- % (self.typename, int (length), int (capacity))) -+ % (self._typename, int(length), int(capacity))) - else: - return ('%s of length %d, capacity %d' -- % (self.typename, int (finish - start), int (end - start))) -+ % (self._typename, int(finish - start), int(end - start))) - - def display_hint(self): - return 'array' - --class StdVectorIteratorPrinter: -- "Print std::vector::iterator" -+ -+class StdVectorIteratorPrinter(printer_base): -+ """Print std::vector::iterator.""" - - def __init__(self, typename, val): -- self.val = val -+ self._val = val - - def to_string(self): -- if not self.val['_M_current']: -+ if not self._val['_M_current']: - return 'non-dereferenceable iterator for std::vector' -- return str(self.val['_M_current'].dereference()) -+ return str(self._val['_M_current'].dereference()) -+ -+ -+class StdBitIteratorPrinter(printer_base): -+ """Print std::vector's _Bit_iterator and _Bit_const_iterator.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ -+ def to_string(self): -+ if not self._val['_M_p']: -+ return 'non-dereferenceable iterator for std::vector' -+ return bool(self._val['_M_p'].dereference() -+ & (1 << self._val['_M_offset'])) - --class StdTuplePrinter: -- "Print a std::tuple" -+ -+class StdBitReferencePrinter(printer_base): -+ """Print std::vector::reference.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ -+ def to_string(self): -+ if not self._val['_M_p']: -+ return 'invalid std::vector::reference' -+ return bool(self._val['_M_p'].dereference() & (self._val['_M_mask'])) -+ -+ -+class StdTuplePrinter(printer_base): -+ """Print a std::tuple.""" - - class _iterator(Iterator): -- def __init__ (self, head): -- self.head = head -+ @staticmethod -+ def _is_nonempty_tuple(nodes): -+ if len(nodes) == 2: -+ if is_specialization_of(nodes[1].type, '__tuple_base'): -+ return True -+ elif len(nodes) == 1: -+ return True -+ elif len(nodes) == 0: -+ return False -+ raise ValueError( -+ "Top of tuple tree does not consist of a single node.") -+ -+ def __init__(self, head): -+ self._head = head - - # Set the base class as the initial head of the - # tuple. -- nodes = self.head.type.fields () -- if len (nodes) == 1: -+ nodes = self._head.type.fields() -+ if self._is_nonempty_tuple(nodes): - # Set the actual head to the first pair. -- self.head = self.head.cast (nodes[0].type) -- elif len (nodes) != 0: -- raise ValueError("Top of tuple tree does not consist of a single node.") -- self.count = 0 -+ self._head = self._head.cast(nodes[0].type) -+ self._count = 0 - -- def __iter__ (self): -+ def __iter__(self): - return self - -- def __next__ (self): -+ def __next__(self): - # Check for further recursions in the inheritance tree. -- # For a GCC 5+ tuple self.head is None after visiting all nodes: -- if not self.head: -+ # For a GCC 5+ tuple self._head is None after visiting all nodes: -+ if not self._head: - raise StopIteration -- nodes = self.head.type.fields () -+ nodes = self._head.type.fields() - # For a GCC 4.x tuple there is a final node with no fields: -- if len (nodes) == 0: -+ if len(nodes) == 0: - raise StopIteration - # Check that this iteration has an expected structure. -- if len (nodes) > 2: -- raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") -+ if len(nodes) > 2: -+ raise ValueError( -+ "Cannot parse more than 2 nodes in a tuple tree.") - -- if len (nodes) == 1: -+ if len(nodes) == 1: - # This is the last node of a GCC 5+ std::tuple. -- impl = self.head.cast (nodes[0].type) -- self.head = None -+ impl = self._head.cast(nodes[0].type) -+ self._head = None - else: - # Either a node before the last node, or the last node of - # a GCC 4.x tuple (which has an empty parent). -@@ -463,53 +683,55 @@ class StdTuplePrinter: - # - Right node is the actual class contained in the tuple. - - # Process right node. -- impl = self.head.cast (nodes[1].type) -+ impl = self._head.cast(nodes[1].type) - - # Process left node and set it as head. -- self.head = self.head.cast (nodes[0].type) -+ self._head = self._head.cast(nodes[0].type) - -- self.count = self.count + 1 -+ self._count = self._count + 1 - - # Finally, check the implementation. If it is - # wrapped in _M_head_impl return that, otherwise return - # the value "as is". -- fields = impl.type.fields () -- if len (fields) < 1 or fields[0].name != "_M_head_impl": -- return ('[%d]' % self.count, impl) -+ fields = impl.type.fields() -+ if len(fields) < 1 or fields[0].name != "_M_head_impl": -+ return ('[%d]' % (self._count - 1), impl) - else: -- return ('[%d]' % self.count, impl['_M_head_impl']) -+ return ('[%d]' % (self._count - 1), impl['_M_head_impl']) - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val; -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - -- def children (self): -- return self._iterator (self.val) -+ def children(self): -+ return self._iterator(self._val) - -- def to_string (self): -- if len (self.val.type.fields ()) == 0: -- return 'empty %s' % (self.typename) -- return '%s containing' % (self.typename) -+ def to_string(self): -+ if len(self._val.type.fields()) == 0: -+ return 'empty %s' % (self._typename) -+ return '%s containing' % (self._typename) - --class StdStackOrQueuePrinter: -- "Print a std::stack or std::queue" - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.visualizer = gdb.default_visualizer(val['c']) -+class StdStackOrQueuePrinter(printer_base): -+ """Print a std::stack or std::queue.""" - -- def children (self): -- return self.visualizer.children() -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._visualizer = gdb.default_visualizer(val['c']) - -- def to_string (self): -- return '%s wrapping: %s' % (self.typename, -- self.visualizer.to_string()) -+ def children(self): -+ return self._visualizer.children() -+ -+ def to_string(self): -+ return '%s wrapping: %s' % (self._typename, -+ self._visualizer.to_string()) - -- def display_hint (self): -- if hasattr (self.visualizer, 'display_hint'): -- return self.visualizer.display_hint () -+ def display_hint(self): -+ if hasattr(self._visualizer, 'display_hint'): -+ return self._visualizer.display_hint() - return None - -+ - class RbtreeIterator(Iterator): - """ - Turn an RB-tree-based container (std::map, std::set etc.) into -@@ -517,24 +739,24 @@ class RbtreeIterator(Iterator): - """ - - def __init__(self, rbtree): -- self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] -- self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] -- self.count = 0 -+ self._size = rbtree['_M_t']['_M_impl']['_M_node_count'] -+ self._node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] -+ self._count = 0 - - def __iter__(self): - return self - - def __len__(self): -- return int (self.size) -+ return int(self._size) - - def __next__(self): -- if self.count == self.size: -+ if self._count == self._size: - raise StopIteration -- result = self.node -- self.count = self.count + 1 -- if self.count < self.size: -+ result = self._node -+ self._count = self._count + 1 -+ if self._count < self._size: - # Compute the next node. -- node = self.node -+ node = self._node - if node.dereference()['_M_right']: - node = node.dereference()['_M_right'] - while node.dereference()['_M_left']: -@@ -546,11 +768,12 @@ class RbtreeIterator(Iterator): - parent = parent.dereference()['_M_parent'] - if node.dereference()['_M_right'] != parent: - node = parent -- self.node = node -+ self._node = node - return result - -+ - def get_value_from_Rb_tree_node(node): -- """Returns the value held in an _Rb_tree_node<_Val>""" -+ """Return the value held in an _Rb_tree_node<_Val>.""" - try: - member = node.type.fields()[1].name - if member == '_M_value_field': -@@ -567,143 +790,142 @@ def get_value_from_Rb_tree_node(node): - # This is a pretty printer for std::_Rb_tree_iterator (which is - # std::map::iterator), and has nothing to do with the RbtreeIterator - # class above. --class StdRbtreeIteratorPrinter: -- "Print std::map::iterator, std::set::iterator, etc." -- -- def __init__ (self, typename, val): -- self.val = val -- valtype = self.val.type.template_argument(0).strip_typedefs() -- nodetype = '_Rb_tree_node<' + str(valtype) + '>' -- if _versioned_namespace and typename.startswith('std::' + _versioned_namespace): -- nodetype = _versioned_namespace + nodetype -- nodetype = gdb.lookup_type('std::' + nodetype) -- self.link_type = nodetype.strip_typedefs().pointer() -- -- def to_string (self): -- if not self.val['_M_node']: -+ -+ -+class StdRbtreeIteratorPrinter(printer_base): -+ """Print std::map::iterator, std::set::iterator, etc.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ nodetype = lookup_node_type('_Rb_tree_node', self._val.type) -+ self._link_type = nodetype.pointer() -+ -+ def to_string(self): -+ if not self._val['_M_node']: - return 'non-dereferenceable iterator for associative container' -- node = self.val['_M_node'].cast(self.link_type).dereference() -+ node = self._val['_M_node'].cast(self._link_type).dereference() - return str(get_value_from_Rb_tree_node(node)) - --class StdDebugIteratorPrinter: -- "Print a debug enabled version of an iterator" - -- def __init__ (self, typename, val): -- self.val = val -+class StdDebugIteratorPrinter(printer_base): -+ """Print a debug enabled version of an iterator.""" -+ -+ def __init__(self, typename, val): -+ self._val = val - - # Just strip away the encapsulating __gnu_debug::_Safe_iterator - # and return the wrapped iterator value. -- def to_string (self): -+ def to_string(self): - base_type = gdb.lookup_type('__gnu_debug::_Safe_iterator_base') -- itype = self.val.type.template_argument(0) -- safe_seq = self.val.cast(base_type)['_M_sequence'] -+ itype = self._val.type.template_argument(0) -+ safe_seq = self._val.cast(base_type)['_M_sequence'] - if not safe_seq: -- return str(self.val.cast(itype)) -- if self.val['_M_version'] != safe_seq['_M_version']: -+ return str(self._val.cast(itype)) -+ if self._val['_M_version'] != safe_seq['_M_version']: - return "invalid iterator" -- return str(self.val.cast(itype)) -+ return str(self._val.cast(itype)) -+ - - def num_elements(num): - """Return either "1 element" or "N elements" depending on the argument.""" - return '1 element' if num == 1 else '%d elements' % num - --class StdMapPrinter: -- "Print a std::map or std::multimap" -+ -+class StdMapPrinter(printer_base): -+ """Print a std::map or std::multimap.""" - - # Turn an RbtreeIterator into a pretty-print iterator. - class _iter(Iterator): - def __init__(self, rbiter, type): -- self.rbiter = rbiter -- self.count = 0 -- self.type = type -+ self._rbiter = rbiter -+ self._count = 0 -+ self._type = type - - def __iter__(self): - return self - - def __next__(self): -- if self.count % 2 == 0: -- n = next(self.rbiter) -- n = n.cast(self.type).dereference() -+ if self._count % 2 == 0: -+ n = next(self._rbiter) -+ n = n.cast(self._type).dereference() - n = get_value_from_Rb_tree_node(n) -- self.pair = n -+ self._pair = n - item = n['first'] - else: -- item = self.pair['second'] -- result = ('[%d]' % self.count, item) -- self.count = self.count + 1 -+ item = self._pair['second'] -+ result = ('[%d]' % self._count, item) -+ self._count = self._count + 1 - return result - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - -- def to_string (self): -- return '%s with %s' % (self.typename, -- num_elements(len(RbtreeIterator (self.val)))) -+ def to_string(self): -+ return '%s with %s' % (self._typename, -+ num_elements(len(RbtreeIterator(self._val)))) - -- def children (self): -- rep_type = find_type(self.val.type, '_Rep_type') -- node = find_type(rep_type, '_Link_type') -- node = node.strip_typedefs() -- return self._iter (RbtreeIterator (self.val), node) -+ def children(self): -+ node = lookup_node_type('_Rb_tree_node', self._val.type).pointer() -+ return self._iter(RbtreeIterator(self._val), node) - -- def display_hint (self): -+ def display_hint(self): - return 'map' - --class StdSetPrinter: -- "Print a std::set or std::multiset" -+ -+class StdSetPrinter(printer_base): -+ """Print a std::set or std::multiset.""" - - # Turn an RbtreeIterator into a pretty-print iterator. - class _iter(Iterator): - def __init__(self, rbiter, type): -- self.rbiter = rbiter -- self.count = 0 -- self.type = type -+ self._rbiter = rbiter -+ self._count = 0 -+ self._type = type - - def __iter__(self): - return self - - def __next__(self): -- item = next(self.rbiter) -- item = item.cast(self.type).dereference() -+ item = next(self._rbiter) -+ item = item.cast(self._type).dereference() - item = get_value_from_Rb_tree_node(item) - # FIXME: this is weird ... what to do? - # Maybe a 'set' display hint? -- result = ('[%d]' % self.count, item) -- self.count = self.count + 1 -+ result = ('[%d]' % self._count, item) -+ self._count = self._count + 1 - return result - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - -- def to_string (self): -- return '%s with %s' % (self.typename, -- num_elements(len(RbtreeIterator (self.val)))) -+ def to_string(self): -+ return '%s with %s' % (self._typename, -+ num_elements(len(RbtreeIterator(self._val)))) - -- def children (self): -- rep_type = find_type(self.val.type, '_Rep_type') -- node = find_type(rep_type, '_Link_type') -- node = node.strip_typedefs() -- return self._iter (RbtreeIterator (self.val), node) -+ def children(self): -+ node = lookup_node_type('_Rb_tree_node', self._val.type).pointer() -+ return self._iter(RbtreeIterator(self._val), node) - --class StdBitsetPrinter: -- "Print a std::bitset" -+ -+class StdBitsetPrinter(printer_base): -+ """Print a std::bitset.""" - - def __init__(self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - -- def to_string (self): -+ def to_string(self): - # If template_argument handled values, we could print the - # size. Or we could use a regexp on the type. -- return '%s' % (self.typename) -+ return '%s' % (self._typename) - -- def children (self): -+ def children(self): - try: - # An empty bitset may not have any members which will - # result in an exception being thrown. -- words = self.val['_M_w'] -+ words = self._val['_M_w'] - except: - return [] - -@@ -713,7 +935,7 @@ class StdBitsetPrinter: - # array. This depends on the template specialization used. - # If it is a single long, convert to a single element list. - if wtype.code == gdb.TYPE_CODE_ARRAY: -- tsize = wtype.target ().sizeof -+ tsize = wtype.target().sizeof - else: - words = [words] - tsize = wtype.sizeof -@@ -733,279 +955,349 @@ class StdBitsetPrinter: - byte = byte + 1 - return result - --class StdDequePrinter: -- "Print a std::deque" -+ -+class StdDequePrinter(printer_base): -+ """Print a std::deque.""" - - class _iter(Iterator): - def __init__(self, node, start, end, last, buffer_size): -- self.node = node -- self.p = start -- self.end = end -- self.last = last -- self.buffer_size = buffer_size -- self.count = 0 -+ self._node = node -+ self._p = start -+ self._end = end -+ self._last = last -+ self._buffer_size = buffer_size -+ self._count = 0 - - def __iter__(self): - return self - - def __next__(self): -- if self.p == self.last: -+ if self._p == self._last: - raise StopIteration - -- result = ('[%d]' % self.count, self.p.dereference()) -- self.count = self.count + 1 -+ result = ('[%d]' % self._count, self._p.dereference()) -+ self._count = self._count + 1 - - # Advance the 'cur' pointer. -- self.p = self.p + 1 -- if self.p == self.end: -+ self._p = self._p + 1 -+ if self._p == self._end: - # If we got to the end of this bucket, move to the - # next bucket. -- self.node = self.node + 1 -- self.p = self.node[0] -- self.end = self.p + self.buffer_size -+ self._node = self._node + 1 -+ self._p = self._node[0] -+ self._end = self._p + self._buffer_size - - return result - - def __init__(self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -- self.elttype = val.type.template_argument(0) -- size = self.elttype.sizeof -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ self._elttype = val.type.template_argument(0) -+ size = self._elttype.sizeof - if size < 512: -- self.buffer_size = int (512 / size) -+ self._buffer_size = int(512 / size) - else: -- self.buffer_size = 1 -+ self._buffer_size = 1 - - def to_string(self): -- start = self.val['_M_impl']['_M_start'] -- end = self.val['_M_impl']['_M_finish'] -+ start = self._val['_M_impl']['_M_start'] -+ end = self._val['_M_impl']['_M_finish'] - - delta_n = end['_M_node'] - start['_M_node'] - 1 - delta_s = start['_M_last'] - start['_M_cur'] - delta_e = end['_M_cur'] - end['_M_first'] - -- size = self.buffer_size * delta_n + delta_s + delta_e -+ size = self._buffer_size * delta_n + delta_s + delta_e - -- return '%s with %s' % (self.typename, num_elements(long(size))) -+ return '%s with %s' % (self._typename, num_elements(long(size))) - - def children(self): -- start = self.val['_M_impl']['_M_start'] -- end = self.val['_M_impl']['_M_finish'] -+ start = self._val['_M_impl']['_M_start'] -+ end = self._val['_M_impl']['_M_finish'] - return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], -- end['_M_cur'], self.buffer_size) -+ end['_M_cur'], self._buffer_size) - -- def display_hint (self): -+ def display_hint(self): - return 'array' - --class StdDequeIteratorPrinter: -- "Print std::deque::iterator" -+ -+class StdDequeIteratorPrinter(printer_base): -+ """Print std::deque::iterator.""" - - def __init__(self, typename, val): -- self.val = val -+ self._val = val - - def to_string(self): -- if not self.val['_M_cur']: -+ if not self._val['_M_cur']: - return 'non-dereferenceable iterator for std::deque' -- return str(self.val['_M_cur'].dereference()) -+ return str(self._val['_M_cur'].dereference()) - --class StdStringPrinter: -- "Print a std::basic_string of some kind" -+ -+class StdStringPrinter(printer_base): -+ """Print a std::basic_string of some kind.""" - - def __init__(self, typename, val): -- self.val = val -- self.new_string = typename.find("::__cxx11::basic_string") != -1 -+ self._val = val -+ self._new_string = typename.find("::__cxx11::basic_string") != -1 - - def to_string(self): - # Make sure &string works, too. -- type = self.val.type -+ type = self._val.type - if type.code == gdb.TYPE_CODE_REF: -- type = type.target () -+ type = type.target() - - # Calculate the length of the string so that to_string returns - # the string according to length, not according to first null - # encountered. -- ptr = self.val ['_M_dataplus']['_M_p'] -- if self.new_string: -- length = self.val['_M_string_length'] -+ ptr = self._val['_M_dataplus']['_M_p'] -+ if self._new_string: -+ length = self._val['_M_string_length'] - # https://sourceware.org/bugzilla/show_bug.cgi?id=17728 - ptr = ptr.cast(ptr.type.strip_typedefs()) - else: -- realtype = type.unqualified ().strip_typedefs () -- reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () -+ realtype = type.unqualified().strip_typedefs() -+ reptype = gdb.lookup_type(str(realtype) + '::_Rep').pointer() - header = ptr.cast(reptype) - 1 -- length = header.dereference ()['_M_length'] -+ length = header.dereference()['_M_length'] - if hasattr(ptr, "lazy_string"): -- return ptr.lazy_string (length = length) -- return ptr.string (length = length) -+ return ptr.lazy_string(length=length) -+ return ptr.string(length=length) -+ -+ def display_hint(self): -+ return 'string' -+ -+ -+def access_streambuf_ptrs(streambuf): -+ """Access the streambuf put area pointers.""" -+ pbase = streambuf['_M_out_beg'] -+ pptr = streambuf['_M_out_cur'] -+ egptr = streambuf['_M_in_end'] -+ return pbase, pptr, egptr - -- def display_hint (self): -+ -+class StdStringBufPrinter(printer_base): -+ """Print a std::basic_stringbuf.""" -+ -+ def __init__(self, _, val): -+ self._val = val -+ -+ def to_string(self): -+ (pbase, pptr, egptr) = access_streambuf_ptrs(self._val) -+ # Logic from basic_stringbuf::_M_high_mark() -+ if pptr: -+ if not egptr or pptr > egptr: -+ return pbase.string(length=pptr - pbase) -+ else: -+ return pbase.string(length=egptr - pbase) -+ return self._val['_M_string'] -+ -+ def display_hint(self): - return 'string' - -+ -+class StdStringStreamPrinter(printer_base): -+ """Print a std::basic_stringstream.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ -+ # Check if the stream was redirected. This is essentially: -+ # val['_M_streambuf'] != val['_M_stringbuf'].address -+ # However, GDB can't resolve the virtual inheritance, so we do that -+ # manually. -+ basetype = [f.type for f in val.type.fields() if f.is_base_class][0] -+ gdb.set_convenience_variable('__stream', val.cast(basetype).address) -+ self._streambuf = gdb.parse_and_eval('$__stream->rdbuf()') -+ self._was_redirected = self._streambuf != val['_M_stringbuf'].address -+ -+ def to_string(self): -+ if self._was_redirected: -+ return "%s redirected to %s" % ( -+ self._typename, self._streambuf.dereference()) -+ return self._val['_M_stringbuf'] -+ -+ def display_hint(self): -+ if self._was_redirected: -+ return None -+ return 'string' -+ -+ - class Tr1HashtableIterator(Iterator): -- def __init__ (self, hash): -- self.buckets = hash['_M_buckets'] -- self.bucket = 0 -- self.bucket_count = hash['_M_bucket_count'] -- self.node_type = find_type(hash.type, '_Node').pointer() -- self.node = 0 -- while self.bucket != self.bucket_count: -- self.node = self.buckets[self.bucket] -- if self.node: -+ def __init__(self, hashtable): -+ self._buckets = hashtable['_M_buckets'] -+ self._bucket = 0 -+ self._bucket_count = hashtable['_M_bucket_count'] -+ self._node_type = find_type(hashtable.type, '_Node').pointer() -+ self._node = 0 -+ while self._bucket != self._bucket_count: -+ self._node = self._buckets[self._bucket] -+ if self._node: - break -- self.bucket = self.bucket + 1 -+ self._bucket = self._bucket + 1 - -- def __iter__ (self): -+ def __iter__(self): - return self - -- def __next__ (self): -- if self.node == 0: -+ def __next__(self): -+ if self._node == 0: - raise StopIteration -- node = self.node.cast(self.node_type) -+ node = self._node.cast(self._node_type) - result = node.dereference()['_M_v'] -- self.node = node.dereference()['_M_next']; -- if self.node == 0: -- self.bucket = self.bucket + 1 -- while self.bucket != self.bucket_count: -- self.node = self.buckets[self.bucket] -- if self.node: -+ self._node = node.dereference()['_M_next'] -+ if self._node == 0: -+ self._bucket = self._bucket + 1 -+ while self._bucket != self._bucket_count: -+ self._node = self._buckets[self._bucket] -+ if self._node: - break -- self.bucket = self.bucket + 1 -+ self._bucket = self._bucket + 1 - return result - -+ - class StdHashtableIterator(Iterator): -- def __init__(self, hash): -- self.node = hash['_M_before_begin']['_M_nxt'] -- self.node_type = find_type(hash.type, '__node_type').pointer() -+ def __init__(self, hashtable): -+ self._node = hashtable['_M_before_begin']['_M_nxt'] -+ valtype = hashtable.type.template_argument(1) -+ cached = hashtable.type.template_argument(9).template_argument(0) -+ node_type = lookup_templ_spec('std::__detail::_Hash_node', str(valtype), -+ 'true' if cached else 'false') -+ self._node_type = node_type.pointer() - - def __iter__(self): - return self - - def __next__(self): -- if self.node == 0: -+ if self._node == 0: - raise StopIteration -- elt = self.node.cast(self.node_type).dereference() -- self.node = elt['_M_nxt'] -+ elt = self._node.cast(self._node_type).dereference() -+ self._node = elt['_M_nxt'] - valptr = elt['_M_storage'].address - valptr = valptr.cast(elt.type.template_argument(0).pointer()) - return valptr.dereference() - --class Tr1UnorderedSetPrinter: -- "Print a tr1::unordered_set" - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+class Tr1UnorderedSetPrinter(printer_base): -+ """Print a std::unordered_set or tr1::unordered_set.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val - -- def hashtable (self): -- if self.typename.startswith('std::tr1'): -- return self.val -- return self.val['_M_h'] -+ def _hashtable(self): -+ if self._typename.startswith('std::tr1'): -+ return self._val -+ return self._val['_M_h'] - -- def to_string (self): -- count = self.hashtable()['_M_element_count'] -- return '%s with %s' % (self.typename, num_elements(count)) -+ def to_string(self): -+ count = self._hashtable()['_M_element_count'] -+ return '%s with %s' % (self._typename, num_elements(count)) - - @staticmethod -- def format_count (i): -+ def _format_count(i): - return '[%d]' % i - -- def children (self): -- counter = imap (self.format_count, itertools.count()) -- if self.typename.startswith('std::tr1'): -- return izip (counter, Tr1HashtableIterator (self.hashtable())) -- return izip (counter, StdHashtableIterator (self.hashtable())) -+ def children(self): -+ counter = imap(self._format_count, itertools.count()) -+ if self._typename.startswith('std::tr1'): -+ return izip(counter, Tr1HashtableIterator(self._hashtable())) -+ return izip(counter, StdHashtableIterator(self._hashtable())) - --class Tr1UnorderedMapPrinter: -- "Print a tr1::unordered_map" - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.val = val -+class Tr1UnorderedMapPrinter(printer_base): -+ """Print a std::unordered_map or tr1::unordered_map.""" - -- def hashtable (self): -- if self.typename.startswith('std::tr1'): -- return self.val -- return self.val['_M_h'] -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def _hashtable(self): -+ if self._typename.startswith('std::tr1'): -+ return self._val -+ return self._val['_M_h'] - -- def to_string (self): -- count = self.hashtable()['_M_element_count'] -- return '%s with %s' % (self.typename, num_elements(count)) -+ def to_string(self): -+ count = self._hashtable()['_M_element_count'] -+ return '%s with %s' % (self._typename, num_elements(count)) - - @staticmethod -- def flatten (list): -+ def _flatten(list): - for elt in list: - for i in elt: - yield i - - @staticmethod -- def format_one (elt): -+ def _format_one(elt): - return (elt['first'], elt['second']) - - @staticmethod -- def format_count (i): -+ def _format_count(i): - return '[%d]' % i - -- def children (self): -- counter = imap (self.format_count, itertools.count()) -+ def children(self): -+ counter = imap(self._format_count, itertools.count()) - # Map over the hash table and flatten the result. -- if self.typename.startswith('std::tr1'): -- data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) -+ if self._typename.startswith('std::tr1'): -+ data = self._flatten( -+ imap(self._format_one, Tr1HashtableIterator(self._hashtable()))) - # Zip the two iterators together. -- return izip (counter, data) -- data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable()))) -+ return izip(counter, data) -+ data = self._flatten( -+ imap(self._format_one, StdHashtableIterator(self._hashtable()))) - # Zip the two iterators together. -- return izip (counter, data) -+ return izip(counter, data) - -- def display_hint (self): -+ def display_hint(self): - return 'map' - --class StdForwardListPrinter: -- "Print a std::forward_list" -+ -+class StdForwardListPrinter(printer_base): -+ """Print a std::forward_list.""" - - class _iterator(Iterator): - def __init__(self, nodetype, head): -- self.nodetype = nodetype -- self.base = head['_M_next'] -- self.count = 0 -+ self._nodetype = nodetype -+ self._base = head['_M_next'] -+ self._count = 0 - - def __iter__(self): - return self - - def __next__(self): -- if self.base == 0: -+ if self._base == 0: - raise StopIteration -- elt = self.base.cast(self.nodetype).dereference() -- self.base = elt['_M_next'] -- count = self.count -- self.count = self.count + 1 -+ elt = self._base.cast(self._nodetype).dereference() -+ self._base = elt['_M_next'] -+ count = self._count -+ self._count = self._count + 1 - valptr = elt['_M_storage'].address - valptr = valptr.cast(elt.type.template_argument(0).pointer()) - return ('[%d]' % count, valptr.dereference()) - - def __init__(self, typename, val): -- self.val = val -- self.typename = strip_versioned_namespace(typename) -+ self._val = val -+ self._typename = strip_versioned_namespace(typename) - - def children(self): -- nodetype = find_type(self.val.type, '_Node') -- nodetype = nodetype.strip_typedefs().pointer() -- return self._iterator(nodetype, self.val['_M_impl']['_M_head']) -+ nodetype = lookup_node_type('_Fwd_list_node', self._val.type).pointer() -+ return self._iterator(nodetype, self._val['_M_impl']['_M_head']) - - def to_string(self): -- if self.val['_M_impl']['_M_head']['_M_next'] == 0: -- return 'empty %s' % self.typename -- return '%s' % self.typename -+ if self._val['_M_impl']['_M_head']['_M_next'] == 0: -+ return 'empty %s' % self._typename -+ return '%s' % self._typename -+ - --class SingleObjContainerPrinter(object): -- "Base class for printers of containers of single objects" -+class SingleObjContainerPrinter(printer_base): -+ """Base class for printers of containers of single objects.""" - -- def __init__ (self, val, viz, hint = None): -- self.contained_value = val -- self.visualizer = viz -- self.hint = hint -+ def __init__(self, val, viz, hint=None): -+ self._contained_value = val -+ self._visualizer = viz -+ self._hint = hint - - def _recognize(self, type): -- """Return TYPE as a string after applying type printers""" -+ """Return type as a string after applying type printers.""" - global _use_type_printing - if not _use_type_printing: - return str(type) -@@ -1013,35 +1305,37 @@ class SingleObjContainerPrinter(object): - type) or str(type) - - class _contained(Iterator): -- def __init__ (self, val): -- self.val = val -+ def __init__(self, val): -+ self._val = val - -- def __iter__ (self): -+ def __iter__(self): - return self - - def __next__(self): -- if self.val is None: -+ if self._val is None: - raise StopIteration -- retval = self.val -- self.val = None -+ retval = self._val -+ self._val = None - return ('[contained value]', retval) - -- def children (self): -- if self.contained_value is None: -- return self._contained (None) -- if hasattr (self.visualizer, 'children'): -- return self.visualizer.children () -- return self._contained (self.contained_value) -+ def children(self): -+ if self._contained_value is None: -+ return self._contained(None) -+ if hasattr(self._visualizer, 'children'): -+ return self._visualizer.children() -+ return self._contained(self._contained_value) -+ -+ def display_hint(self): -+ if (hasattr(self._visualizer, 'children') -+ and hasattr(self._visualizer, 'display_hint')): -+ # If contained value is a map we want to display in the same way. -+ return self._visualizer.display_hint() -+ return self._hint - -- def display_hint (self): -- # if contained value is a map we want to display in the same way -- if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'): -- return self.visualizer.display_hint () -- return self.hint - - def function_pointer_to_name(f): -- "Find the name of the function referred to by the gdb.Value f, " -- " which should contain a function pointer from the program." -+ """Find the name of the function referred to by the gdb.Value f, -+ which should contain a function pointer from the program.""" - - # Turn the function pointer into an actual address. - # This is needed to unpack ppc64 function descriptors. -@@ -1062,252 +1356,1003 @@ def function_pointer_to_name(f): - except: - return None - -+ - class StdExpAnyPrinter(SingleObjContainerPrinter): -- "Print a std::any or std::experimental::any" -+ """Print a std::any or std::experimental::any.""" - -- def __init__ (self, typename, val): -- self.typename = strip_versioned_namespace(typename) -- self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', self.typename, 1) -- self.val = val -- self.contained_type = None -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._typename = strip_fundts_namespace(self._typename) -+ self._val = val -+ self._contained_type = None - contained_value = None - visualizer = None -- mgr = self.val['_M_manager'] -+ mgr = self._val['_M_manager'] - if mgr != 0: - func = function_pointer_to_name(mgr) - if not func: -- raise ValueError("Invalid function pointer in %s" % (self.typename)) -- rx = r"""({0}::_Manager_\w+<.*>)::_S_manage""".format(typename) -+ raise ValueError( -+ "Invalid function pointer in %s" % (self._typename)) -+ # We want to use this regular expression: -+ # T::_Manager_xxx<.*>::_S_manage\(T::_Op, const T\*, T::_Arg\*\) -+ # where T is std::any or std::experimental::any. -+ # But we need to account for variances in demangled names -+ # between GDB versions, e.g. 'enum T::_Op' instead of 'T::_Op'. -+ rx = ( -+ r"({0}::_Manager_\w+<.*>)::_S_manage\(" -+ r"(enum )?{0}::_Op, (const {0}|{0} const) ?\*, " -+ r"(union )?{0}::_Arg ?\*\)" -+ ).format(typename) - m = re.match(rx, func) - if not m: -- raise ValueError("Unknown manager function in %s" % self.typename) -+ raise ValueError( -+ "Unknown manager function in %s" % self._typename) - - mgrname = m.group(1) - # FIXME need to expand 'std::string' so that gdb.lookup_type works - if 'std::string' in mgrname: -- mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1)) -- -- mgrtype = gdb.lookup_type(mgrname) -- self.contained_type = mgrtype.template_argument(0) -+ mgrtypes = [] -+ for s in StdExpAnyPrinter._string_types(): -+ try: -+ x = re.sub(r"std::string(?!\w)", s, m.group(1)) -+ # The following lookup might raise gdb.error if the -+ # manager function was never instantiated for 's' in -+ # the program, because there will be no such type. -+ mgrtypes.append(gdb.lookup_type(x)) -+ except gdb.error: -+ pass -+ if len(mgrtypes) != 1: -+ # FIXME: this is unlikely in practice, but possible for -+ # programs that use both old and new string types with -+ # std::any in a single program. Can we do better? -+ # Maybe find the address of each type's _S_manage and -+ # compare to the address stored in _M_manager? -+ raise ValueError( -+ 'Cannot uniquely determine std::string type ' -+ 'used in std::any' -+ ) -+ mgrtype = mgrtypes[0] -+ else: -+ mgrtype = gdb.lookup_type(mgrname) -+ self._contained_type = mgrtype.template_argument(0) - valptr = None - if '::_Manager_internal' in mgrname: -- valptr = self.val['_M_storage']['_M_buffer'].address -+ valptr = self._val['_M_storage']['_M_buffer'].address - elif '::_Manager_external' in mgrname: -- valptr = self.val['_M_storage']['_M_ptr'] -+ valptr = self._val['_M_storage']['_M_ptr'] - else: -- raise ValueError("Unknown manager function in %s" % self.typename) -- contained_value = valptr.cast(self.contained_type.pointer()).dereference() -+ raise ValueError( -+ "Unknown manager function in %s" % self._typename) -+ contained_value = valptr.cast( -+ self._contained_type.pointer()).dereference() - visualizer = gdb.default_visualizer(contained_value) -- super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer) -- -- def to_string (self): -- if self.contained_type is None: -- return '%s [no contained value]' % self.typename -- desc = "%s containing " % self.typename -- if hasattr (self.visualizer, 'children'): -- return desc + self.visualizer.to_string () -- valtype = self._recognize (self.contained_type) -+ super(StdExpAnyPrinter, self).__init__(contained_value, visualizer) -+ -+ def to_string(self): -+ if self._contained_type is None: -+ return '%s [no contained value]' % self._typename -+ desc = "%s containing " % self._typename -+ if hasattr(self._visualizer, 'children'): -+ return desc + self._visualizer.to_string() -+ valtype = self._recognize(self._contained_type) - return desc + strip_versioned_namespace(str(valtype)) - -+ @staticmethod -+ def _string_types(): -+ # This lookup for std::string might return the __cxx11 version, -+ # but that's not necessarily the one used by the std::any -+ # manager function we're trying to find. -+ strings = {str(gdb.lookup_type('std::string').strip_typedefs())} -+ # So also consider all the other possible std::string types! -+ s = 'basic_string, std::allocator >' -+ quals = ['std::', 'std::__cxx11::', -+ 'std::' + _versioned_namespace] -+ strings |= {q + s for q in quals} # set of unique strings -+ return strings -+ -+ - class StdExpOptionalPrinter(SingleObjContainerPrinter): -- "Print a std::optional or std::experimental::optional" -- -- def __init__ (self, typename, val): -- valtype = self._recognize (val.type.template_argument(0)) -- self.typename = strip_versioned_namespace(typename) -- self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, self.typename, 1) -- if not self.typename.startswith('std::experimental'): -- val = val['_M_payload'] -- self.val = val -- contained_value = val['_M_payload'] if self.val['_M_engaged'] else None -- visualizer = gdb.default_visualizer (val['_M_payload']) -- super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer) -- -- def to_string (self): -- if self.contained_value is None: -- return "%s [no contained value]" % self.typename -- if hasattr (self.visualizer, 'children'): -- return "%s containing %s" % (self.typename, -- self.visualizer.to_string()) -- return self.typename -+ """Print a std::optional or std::experimental::optional.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._typename = strip_fundts_namespace(self._typename) -+ payload = val['_M_payload'] -+ if self._typename.startswith('std::experimental'): -+ engaged = val['_M_engaged'] -+ contained_value = payload -+ else: -+ engaged = payload['_M_engaged'] -+ contained_value = payload['_M_payload'] -+ try: -+ # Since GCC 9 -+ contained_value = contained_value['_M_value'] -+ except: -+ pass -+ visualizer = gdb.default_visualizer(contained_value) -+ if not engaged: -+ contained_value = None -+ super(StdExpOptionalPrinter, self).__init__( -+ contained_value, visualizer) -+ -+ def to_string(self): -+ if self._contained_value is None: -+ return "%s [no contained value]" % self._typename -+ if hasattr(self._visualizer, 'children'): -+ return "%s containing %s" % (self._typename, -+ self._visualizer.to_string()) -+ return self._typename -+ - - class StdVariantPrinter(SingleObjContainerPrinter): -- "Print a std::variant" -+ """Print a std::variant.""" - - def __init__(self, typename, val): - alternatives = get_template_arg_list(val.type) -- self.typename = strip_versioned_namespace(typename) -- self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives])) -- self.index = val['_M_index'] -- if self.index >= len(alternatives): -- self.contained_type = None -+ self._typename = strip_versioned_namespace(typename) -+ self._index = val['_M_index'] -+ if self._index >= len(alternatives): -+ self._contained_type = None - contained_value = None - visualizer = None - else: -- self.contained_type = alternatives[int(self.index)] -+ self._contained_type = alternatives[int(self._index)] - addr = val['_M_u']['_M_first']['_M_storage'].address -- contained_value = addr.cast(self.contained_type.pointer()).dereference() -+ contained_value = addr.cast( -+ self._contained_type.pointer()).dereference() - visualizer = gdb.default_visualizer(contained_value) -- super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array') -+ super(StdVariantPrinter, self).__init__( -+ contained_value, visualizer, 'array') - - def to_string(self): -- if self.contained_value is None: -- return "%s [no contained value]" % self.typename -- if hasattr(self.visualizer, 'children'): -- return "%s [index %d] containing %s" % (self.typename, self.index, -- self.visualizer.to_string()) -- return "%s [index %d]" % (self.typename, self.index) -+ if self._contained_value is None: -+ return "%s [no contained value]" % self._typename -+ if hasattr(self._visualizer, 'children'): -+ return "%s [index %d] containing %s" % (self._typename, self._index, -+ self._visualizer.to_string()) -+ return "%s [index %d]" % (self._typename, self._index) -+ - - class StdNodeHandlePrinter(SingleObjContainerPrinter): -- "Print a container node handle" -+ """Print a container node handle.""" - - def __init__(self, typename, val): -- self.value_type = val.type.template_argument(1) -+ self._value_type = val.type.template_argument(1) - nodetype = val.type.template_argument(2).template_argument(0) -- self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node') -- self.is_map_node = val.type.template_argument(0) != self.value_type -+ self._is_rb_tree_node = is_specialization_of( -+ nodetype.name, '_Rb_tree_node') -+ self._is_map_node = val.type.template_argument(0) != self._value_type - nodeptr = val['_M_ptr'] - if nodeptr: -- if self.is_rb_tree_node: -- contained_value = get_value_from_Rb_tree_node(nodeptr.dereference()) -+ if self._is_rb_tree_node: -+ contained_value = get_value_from_Rb_tree_node( -+ nodeptr.dereference()) - else: - contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'], -- self.value_type) -+ self._value_type) - visualizer = gdb.default_visualizer(contained_value) - else: - contained_value = None - visualizer = None - optalloc = val['_M_alloc'] -- self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None -+ self._alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None - super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer, - 'array') - - def to_string(self): - desc = 'node handle for ' -- if not self.is_rb_tree_node: -+ if not self._is_rb_tree_node: - desc += 'unordered ' -- if self.is_map_node: -- desc += 'map'; -+ if self._is_map_node: -+ desc += 'map' - else: -- desc += 'set'; -+ desc += 'set' - -- if self.contained_value: -+ if self._contained_value: - desc += ' with element' -- if hasattr(self.visualizer, 'children'): -- return "%s = %s" % (desc, self.visualizer.to_string()) -+ if hasattr(self._visualizer, 'children'): -+ return "%s = %s" % (desc, self._visualizer.to_string()) - return desc - else: - return 'empty %s' % desc - --class StdExpStringViewPrinter: -- "Print a std::basic_string_view or std::experimental::basic_string_view" - -- def __init__ (self, typename, val): -- self.val = val -+class StdExpStringViewPrinter(printer_base): -+ """ -+ Print a std::basic_string_view or std::experimental::basic_string_view -+ """ -+ -+ def __init__(self, typename, val): -+ self._val = val - -- def to_string (self): -- ptr = self.val['_M_str'] -- len = self.val['_M_len'] -- if hasattr (ptr, "lazy_string"): -- return ptr.lazy_string (length = len) -- return ptr.string (length = len) -+ def to_string(self): -+ ptr = self._val['_M_str'] -+ len = self._val['_M_len'] -+ if hasattr(ptr, "lazy_string"): -+ return ptr.lazy_string(length=len) -+ return ptr.string(length=len) - -- def display_hint (self): -+ def display_hint(self): - return 'string' - --class StdExpPathPrinter: -- "Print a std::experimental::filesystem::path or std::filesystem::path" - -- def __init__ (self, typename, val): -- self.val = val -- self.typename = typename -- start = self.val['_M_cmpts']['_M_impl']['_M_start'] -- finish = self.val['_M_cmpts']['_M_impl']['_M_finish'] -- self.num_cmpts = int (finish - start) -+class StdExpPathPrinter(printer_base): -+ """Print a std::experimental::filesystem::path.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ start = self._val['_M_cmpts']['_M_impl']['_M_start'] -+ finish = self._val['_M_cmpts']['_M_impl']['_M_finish'] -+ self._num_cmpts = int(finish - start) - - def _path_type(self): -- t = str(self.val['_M_type']) -+ t = str(self._val['_M_type']) - if t[-9:] == '_Root_dir': - return "root-directory" - if t[-10:] == '_Root_name': - return "root-name" - return None - -- def to_string (self): -- path = "%s" % self.val ['_M_pathname'] -- if self.num_cmpts == 0: -+ def to_string(self): -+ path = "%s" % self._val['_M_pathname'] -+ if self._num_cmpts == 0: - t = self._path_type() - if t: - path = '%s [%s]' % (path, t) -- return "filesystem::path %s" % path -+ return "experimental::filesystem::path %s" % path - - class _iterator(Iterator): - def __init__(self, cmpts, pathtype): -- self.pathtype = pathtype -- self.item = cmpts['_M_impl']['_M_start'] -- self.finish = cmpts['_M_impl']['_M_finish'] -- self.count = 0 -+ self._pathtype = pathtype -+ self._item = cmpts['_M_impl']['_M_start'] -+ self._finish = cmpts['_M_impl']['_M_finish'] -+ self._count = 0 -+ -+ def __iter__(self): -+ return self -+ -+ def __next__(self): -+ if self._item == self._finish: -+ raise StopIteration -+ item = self._item.dereference() -+ count = self._count -+ self._count = self._count + 1 -+ self._item = self._item + 1 -+ path = item['_M_pathname'] -+ t = StdExpPathPrinter(self._pathtype, item)._path_type() -+ if not t: -+ t = count -+ return ('[%s]' % t, path) -+ -+ def children(self): -+ return self._iterator(self._val['_M_cmpts'], self._typename) -+ -+ -+class StdPathPrinter(printer_base): -+ """Print a std::filesystem::path.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ impl = unique_ptr_get(self._val['_M_cmpts']['_M_impl']) -+ self._type = impl.cast(gdb.lookup_type('uintptr_t')) & 3 -+ if self._type == 0: -+ self._impl = impl -+ else: -+ self._impl = None -+ -+ def _path_type(self): -+ t = str(self._type.cast(gdb.lookup_type(self._typename + '::_Type'))) -+ if t[-9:] == '_Root_dir': -+ return "root-directory" -+ if t[-10:] == '_Root_name': -+ return "root-name" -+ return None -+ -+ def to_string(self): -+ path = "%s" % self._val['_M_pathname'] -+ if self._type != 0: -+ t = self._path_type() -+ if t: -+ path = '%s [%s]' % (path, t) -+ return "filesystem::path %s" % path -+ -+ class _iterator(Iterator): -+ def __init__(self, impl, pathtype): -+ self._pathtype = pathtype -+ if impl: -+ # We can't access _Impl::_M_size because _Impl is incomplete -+ # so cast to int* to access the _M_size member at offset zero, -+ int_type = gdb.lookup_type('int') -+ cmpt_type = gdb.lookup_type(pathtype + '::_Cmpt') -+ char_type = gdb.lookup_type('char') -+ impl = impl.cast(int_type.pointer()) -+ size = impl.dereference() -+ #self._capacity = (impl + 1).dereference() -+ if hasattr(gdb.Type, 'alignof'): -+ sizeof_Impl = max(2 * int_type.sizeof, cmpt_type.alignof) -+ else: -+ sizeof_Impl = 2 * int_type.sizeof -+ begin = impl.cast(char_type.pointer()) + sizeof_Impl -+ self._item = begin.cast(cmpt_type.pointer()) -+ self._finish = self._item + size -+ self._count = 0 -+ else: -+ self._item = None -+ self._finish = None - - def __iter__(self): - return self - - def __next__(self): -- if self.item == self.finish: -+ if self._item == self._finish: - raise StopIteration -- item = self.item.dereference() -- count = self.count -- self.count = self.count + 1 -- self.item = self.item + 1 -+ item = self._item.dereference() -+ count = self._count -+ self._count = self._count + 1 -+ self._item = self._item + 1 - path = item['_M_pathname'] -- t = StdExpPathPrinter(self.pathtype, item)._path_type() -+ t = StdPathPrinter(self._pathtype, item)._path_type() - if not t: - t = count - return ('[%s]' % t, path) - - def children(self): -- return self._iterator(self.val['_M_cmpts'], self.typename) -+ return self._iterator(self._impl, self._typename) - - --class StdPairPrinter: -- "Print a std::pair object, with 'first' and 'second' as children" -+class StdPairPrinter(printer_base): -+ """Print a std::pair object, with 'first' and 'second' as children.""" - - def __init__(self, typename, val): -- self.val = val -+ self._val = val - - class _iter(Iterator): -- "An iterator for std::pair types. Returns 'first' then 'second'." -+ """An iterator for std::pair types. Returns 'first' then 'second'.""" - - def __init__(self, val): -- self.val = val -- self.which = 'first' -+ self._val = val -+ self._which = 'first' - - def __iter__(self): - return self - - def __next__(self): -- if self.which is None: -+ if self._which is None: - raise StopIteration -- which = self.which -+ which = self._which - if which == 'first': -- self.which = 'second' -+ self._which = 'second' - else: -- self.which = None -- return (which, self.val[which]) -+ self._which = None -+ return (which, self._val[which]) - - def children(self): -- return self._iter(self.val) -+ return self._iter(self._val) - - def to_string(self): - return None - - -+class StdCmpCatPrinter(printer_base): -+ """Print a comparison category object.""" -+ -+ def __init__(self, typename, val): -+ self._typename = typename[typename.rfind(':') + 1:] -+ self._val = val['_M_value'] -+ -+ def to_string(self): -+ if self._typename == 'strong_ordering' and self._val == 0: -+ name = 'equal' -+ else: -+ names = {2: 'unordered', -1: 'less', 0: 'equivalent', 1: 'greater'} -+ name = names[int(self._val)] -+ return 'std::{}::{}'.format(self._typename, name) -+ -+ -+class StdErrorCodePrinter(printer_base): -+ """Print a std::error_code or std::error_condition.""" -+ -+ _system_is_posix = None # Whether std::system_category() use errno values. -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = strip_versioned_namespace(typename) -+ # Do this only once ... -+ if StdErrorCodePrinter._system_is_posix is None: -+ try: -+ import posix -+ StdErrorCodePrinter._system_is_posix = True -+ except ImportError: -+ StdErrorCodePrinter._system_is_posix = False -+ -+ @staticmethod -+ def _find_errc_enum(name): -+ typ = gdb.lookup_type(name) -+ if typ is not None and typ.code == gdb.TYPE_CODE_ENUM: -+ return typ -+ return None -+ -+ @classmethod -+ def _find_standard_errc_enum(cls, name): -+ for ns in ['', _versioned_namespace]: -+ try: -+ qname = 'std::{}{}'.format(ns, name) -+ return cls._find_errc_enum(qname) -+ except RuntimeError: -+ pass -+ -+ @classmethod -+ def _match_net_ts_category(cls, cat): -+ net_cats = ['stream', 'socket', 'ip::resolver'] -+ for c in net_cats: -+ func = c + '_category()' -+ for ns in ['', _versioned_namespace]: -+ ns = 'std::{}experimental::net::v1'.format(ns) -+ sym = gdb.lookup_symbol('{}::{}::__c'.format(ns, func))[0] -+ if sym is not None: -+ if cat == sym.value().address: -+ name = 'net::' + func -+ enum = cls._find_errc_enum('{}::{}_errc'.format(ns, c)) -+ return (name, enum) -+ return (None, None) -+ -+ @classmethod -+ def _category_info(cls, cat): -+ """Return details of a std::error_category.""" -+ -+ name = None -+ enum = None -+ is_errno = False -+ -+ # Try these first, or we get "warning: RTTI symbol not found" when -+ # using cat.dynamic_type on the local class types for Net TS -+ # categories. -+ func, enum = cls._match_net_ts_category(cat) -+ if func is not None: -+ return (None, func, enum, is_errno) -+ -+ # This might give a warning for a program-defined category defined as -+ # a local class, but there doesn't seem to be any way to avoid that. -+ typ = cat.dynamic_type.target() -+ # Shortcuts for the known categories defined by libstdc++. -+ if typ.tag.endswith('::generic_error_category'): -+ name = 'generic' -+ is_errno = True -+ if typ.tag.endswith('::system_error_category'): -+ name = 'system' -+ is_errno = cls._system_is_posix -+ if typ.tag.endswith('::future_error_category'): -+ name = 'future' -+ enum = cls._find_standard_errc_enum('future_errc') -+ if typ.tag.endswith('::io_error_category'): -+ name = 'io' -+ enum = cls._find_standard_errc_enum('io_errc') -+ -+ if name is None: -+ try: -+ # Want to call std::error_category::name() override, but it's -+ # unsafe: https://sourceware.org/bugzilla/show_bug.cgi?id=28856 -+ # gdb.set_convenience_variable('__cat', cat) -+ # return '"%s"' % gdb.parse_and_eval('$__cat->name()').string() -+ pass -+ except: -+ pass -+ return (name, typ.tag, enum, is_errno) -+ -+ @staticmethod -+ def _unqualified_name(name): -+ """ -+ Strip any nested-name-specifier from name to give an unqualified name. -+ """ -+ return name.split('::')[-1] -+ -+ def to_string(self): -+ value = self._val['_M_value'] -+ cat = self._val['_M_cat'] -+ name, alt_name, enum, is_errno = self._category_info(cat) -+ if value == 0: -+ default_cats = {'error_code': 'system', -+ 'error_condition': 'generic'} -+ if name == default_cats[self._unqualified_name(self._typename)]: -+ return self._typename + ' = { }' # default-constructed value -+ -+ strval = str(value) -+ if is_errno and value != 0: -+ try: -+ strval = errno.errorcode[int(value)] -+ except: -+ pass -+ elif enum is not None: -+ strval = self._unqualified_name(str(value.cast(enum))) -+ -+ if name is not None: -+ name = '"%s"' % name -+ else: -+ name = alt_name -+ return '%s = {%s: %s}' % (self._typename, name, strval) -+ -+ -+class StdRegexStatePrinter(printer_base): -+ """Print a state node in the NFA for a std::regex.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ -+ def to_string(self): -+ opcode = str(self._val['_M_opcode']) -+ if opcode: -+ opcode = opcode[25:] -+ next_id = self._val['_M_next'] -+ -+ variants = {'repeat': 'alt', 'alternative': 'alt', -+ 'subexpr_begin': 'subexpr', 'subexpr_end': 'subexpr', -+ 'line_begin_assertion': None, 'line_end_assertion': None, -+ 'word_boundary': 'neg', 'subexpr_lookahead': 'neg', -+ 'backref': 'backref_index', -+ 'match': None, 'accept': None, -+ 'dummy': None, 'unknown': None -+ } -+ v = variants[opcode] -+ -+ s = "opcode={}, next={}".format(opcode, next_id) -+ if v is not None and self._val['_M_' + v] is not None: -+ s = "{}, {}={}".format(s, v, self._val['_M_' + v]) -+ return "{%s}" % (s) -+ -+ -+class StdSpanPrinter(printer_base): -+ """Print a std::span.""" -+ -+ class _iterator(Iterator): -+ def __init__(self, begin, size): -+ self._count = 0 -+ self._begin = begin -+ self._size = size -+ -+ def __iter__(self): -+ return self -+ -+ def __next__(self): -+ if self._count == self._size: -+ raise StopIteration -+ -+ count = self._count -+ self._count = self._count + 1 -+ return '[%d]' % count, (self._begin + count).dereference() -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ size_max = gdb.parse_and_eval('static_cast(-1)') -+ if val.type.template_argument(1) == size_max: -+ self._size = val['_M_extent']['_M_extent_value'] -+ else: -+ self._size = val.type.template_argument(1) -+ -+ def to_string(self): -+ return '%s of length %d' % (self._typename, self._size) -+ -+ def children(self): -+ return self._iterator(self._val['_M_ptr'], self._size) -+ -+ def display_hint(self): -+ return 'array' -+ -+ -+class StdInitializerListPrinter(printer_base): -+ """Print a std::initializer_list.""" -+ -+ def __init__(self, typename, val): -+ self._typename = typename -+ self._val = val -+ self._size = val['_M_len'] -+ -+ def to_string(self): -+ return '%s of length %d' % (self._typename, self._size) -+ -+ def children(self): -+ return StdSpanPrinter._iterator(self._val['_M_array'], self._size) -+ -+ def display_hint(self): -+ return 'array' -+ -+ -+class StdAtomicPrinter(printer_base): -+ """Print a std:atomic.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ self._shptr_printer = None -+ self._value_type = self._val.type.template_argument(0) -+ if self._value_type.tag is not None: -+ typ = strip_versioned_namespace(self._value_type.tag) -+ if (typ.startswith('std::shared_ptr<') -+ or typ.startswith('std::weak_ptr<')): -+ impl = val['_M_impl'] -+ self._shptr_printer = SharedPointerPrinter(typename, impl) -+ self.children = self._shptr_children -+ -+ def _shptr_children(self): -+ return SmartPtrIterator(self._shptr_printer._pointer) -+ -+ def to_string(self): -+ if self._shptr_printer is not None: -+ return self._shptr_printer.to_string() -+ -+ if self._value_type.code == gdb.TYPE_CODE_INT: -+ val = self._val['_M_i'] -+ elif self._value_type.code == gdb.TYPE_CODE_FLT: -+ val = self._val['_M_fp'] -+ elif self._value_type.code == gdb.TYPE_CODE_PTR: -+ val = self._val['_M_b']['_M_p'] -+ elif self._value_type.code == gdb.TYPE_CODE_BOOL: -+ val = self._val['_M_base']['_M_i'] -+ else: -+ val = self._val['_M_i'] -+ return '%s<%s> = { %s }' % (self._typename, str(self._value_type), val) -+ -+ -+class StdFormatArgsPrinter(printer_base): -+ """Print a std::basic_format_args.""" -+ # TODO: add printer for basic_format_arg and print out children. -+ # TODO: add printer for __format::_ArgStore. -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ targs = get_template_arg_list(self._val.type) -+ char_type = get_template_arg_list(targs[0])[1] -+ if char_type == gdb.lookup_type('char'): -+ typ = 'std::format_args' -+ elif char_type == gdb.lookup_type('wchar_t'): -+ typ = 'std::wformat_args' -+ else: -+ typ = 'std::basic_format_args' -+ -+ size = self._val['_M_packed_size'] -+ if size == 1: -+ return "%s with 1 argument" % (typ) -+ if size == 0: -+ size = self._val['_M_unpacked_size'] -+ return "%s with %d arguments" % (typ, size) -+ -+ -+class StdChronoDurationPrinter(printer_base): -+ """Print a std::chrono::duration.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def _ratio(self): -+ # TODO use reduced period i.e. duration::period -+ period = self._val.type.template_argument(1) -+ num = period.template_argument(0) -+ den = period.template_argument(1) -+ return (num, den) -+ -+ def _suffix(self): -+ num, den = self._ratio() -+ if num == 1: -+ if den == 1: -+ return 's' -+ if den == 1000: -+ return 'ms' -+ if den == 1000000: -+ return 'us' -+ if den == 1000000000: -+ return 'ns' -+ elif den == 1: -+ if num == 60: -+ return 'min' -+ if num == 3600: -+ return 'h' -+ if num == 86400: -+ return 'd' -+ return '[{}]s'.format(num) -+ return "[{}/{}]s".format(num, den) -+ -+ def to_string(self): -+ r = self._val['__r'] -+ if r.type.strip_typedefs().code == gdb.TYPE_CODE_FLT: -+ r = "%g" % r -+ return "std::chrono::duration = {{ {}{} }}".format(r, self._suffix()) -+ -+ -+class StdChronoTimePointPrinter(printer_base): -+ """Print a std::chrono::time_point.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def _clock(self): -+ clock = self._val.type.template_argument(0) -+ name = strip_versioned_namespace(clock.name) -+ if name == 'std::chrono::_V2::system_clock' \ -+ or name == 'std::chrono::system_clock': -+ return ('std::chrono::sys_time', 0) -+ # XXX need to remove leap seconds from utc, gps, and tai -+ if name == 'std::chrono::utc_clock': -+ return ('std::chrono::utc_time', None) # XXX -+ if name == 'std::chrono::gps_clock': -+ return ('std::chrono::gps_time', None) # XXX 315964809 -+ if name == 'std::chrono::tai_clock': -+ return ('std::chrono::tai_time', None) # XXX -378691210 -+ if name == 'std::filesystem::__file_clock': -+ return ('std::chrono::file_time', 6437664000) -+ if name == 'std::chrono::local_t': -+ return ('std::chrono::local_time', 0) -+ return ('{} time_point'.format(name), None) -+ -+ def to_string(self, abbrev=False): -+ clock, offset = self._clock() -+ d = self._val['__d'] -+ r = d['__r'] -+ printer = StdChronoDurationPrinter(d.type.name, d) -+ suffix = printer._suffix() -+ time = '' -+ if offset is not None: -+ num, den = printer._ratio() -+ secs = (r * num / den) + offset -+ try: -+ dt = datetime.datetime.fromtimestamp(secs, _utc_timezone) -+ time = ' [{:%Y-%m-%d %H:%M:%S}]'.format(dt) -+ except: -+ pass -+ s = '%d%s%s' % (r, suffix, time) -+ if abbrev: -+ return s -+ return '%s = { %s }' % (clock, s) -+ -+ -+class StdChronoZonedTimePrinter(printer_base): -+ """Print a std::chrono::zoned_time.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ zone = self._val['_M_zone'].dereference()['_M_name'] -+ time = self._val['_M_tp'] -+ printer = StdChronoTimePointPrinter(time.type.name, time) -+ time = printer.to_string(True) -+ return 'std::chrono::zoned_time = {{ {} {} }}'.format(zone, time) -+ -+ -+months = [None, 'January', 'February', 'March', 'April', 'May', 'June', -+ 'July', 'August', 'September', 'October', 'November', 'December'] -+ -+weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', -+ 'Saturday', 'Sunday'] -+ -+ -+class StdChronoCalendarPrinter(printer_base): -+ """Print a std::chrono::day, std::chrono::month, std::chrono::year etc.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ val = self._val -+ typ = self._typename -+ if 'month' in typ and typ != 'std::chrono::year_month_day_last': -+ m = val['_M_m'] -+ if typ.startswith('std::chrono::year'): -+ y = val['_M_y'] -+ -+ if typ == 'std::chrono::day': -+ return '{}'.format(int(val['_M_d'])) -+ if typ == 'std::chrono::month': -+ if m < 1 or m >= len(months): -+ return "%d is not a valid month" % m -+ return months[m] -+ if typ == 'std::chrono::year': -+ return '{}y'.format(y) -+ if typ == 'std::chrono::weekday': -+ wd = val['_M_wd'] -+ if wd < 0 or wd >= len(weekdays): -+ return "%d is not a valid weekday" % wd -+ return '{}'.format(weekdays[wd]) -+ if typ == 'std::chrono::weekday_indexed': -+ return '{}[{}]'.format(val['_M_wd'], int(val['_M_index'])) -+ if typ == 'std::chrono::weekday_last': -+ return '{}[last]'.format(val['_M_wd']) -+ if typ == 'std::chrono::month_day': -+ return '{}/{}'.format(m, val['_M_d']) -+ if typ == 'std::chrono::month_day_last': -+ return '{}/last'.format(m) -+ if typ == 'std::chrono::month_weekday': -+ return '{}/{}'.format(m, val['_M_wdi']) -+ if typ == 'std::chrono::month_weekday_last': -+ return '{}/{}'.format(m, val['_M_wdl']) -+ if typ == 'std::chrono::year_month': -+ return '{}/{}'.format(y, m) -+ if typ == 'std::chrono::year_month_day': -+ return '{}/{}/{}'.format(y, m, val['_M_d']) -+ if typ == 'std::chrono::year_month_day_last': -+ return '{}/{}'.format(y, val['_M_mdl']) -+ if typ == 'std::chrono::year_month_weekday': -+ return '{}/{}/{}'.format(y, m, val['_M_wdi']) -+ if typ == 'std::chrono::year_month_weekday_last': -+ return '{}/{}/{}'.format(y, m, val['_M_wdl']) -+ if typ.startswith('std::chrono::hh_mm_ss'): -+ fract = '' -+ if val['fractional_width'] != 0: -+ fract = '.{:0{}d}'.format(int(val['_M_ss']['_M_r']), -+ int(val['fractional_width'])) -+ h = int(val['_M_h']['__r']) -+ m = int(val['_M_m']['__r']) -+ s = int(val['_M_s']['__r']) -+ if val['_M_is_neg']: -+ h = -h -+ return '{:02}:{:02}:{:02}{}'.format(h, m, s, fract) -+ -+ -+class StdChronoTimeZonePrinter(printer_base): -+ """Print a chrono::time_zone or chrono::time_zone_link.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ str = '%s = %s' % (self._typename, self._val['_M_name']) -+ if self._typename.endswith("_link"): -+ str += ' -> %s' % (self._val['_M_target']) -+ return str -+ -+ -+class StdChronoLeapSecondPrinter(printer_base): -+ """Print a chrono::leap_second.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ date = self._val['_M_s']['__r'] -+ neg = '+-'[date < 0] -+ return '%s %d (%c)' % (self._typename, abs(date), neg) -+ -+ -+class StdChronoTzdbPrinter(printer_base): -+ """Print a chrono::tzdb.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ return '%s %s' % (self._typename, self._val['version']) -+ -+ -+class StdChronoTimeZoneRulePrinter(printer_base): -+ """Print a chrono::time_zone rule.""" -+ -+ def __init__(self, typename, val): -+ self._typename = strip_versioned_namespace(typename) -+ self._val = val -+ -+ def to_string(self): -+ on = self._val['on'] -+ kind = on['kind'] -+ month = months[on['month']] -+ suffixes = {1: 'st', 2: 'nd', 3: 'rd', -+ 21: 'st', 22: 'nd', 23: 'rd', 31: 'st'} -+ day = on['day_of_month'] -+ ordinal_day = '{}{}'.format(day, suffixes.get(day, 'th')) -+ if kind == 0: # DayOfMonth -+ start = '{} {}'.format(month, ordinal_day) -+ else: -+ weekday = weekdays[on['day_of_week']] -+ if kind == 1: # LastWeekDay -+ start = 'last {} in {}'.format(weekday, month) -+ else: -+ if kind == 2: # LessEq -+ direction = ('last', '<=') -+ else: -+ direction = ('first', '>=') -+ day = on['day_of_month'] -+ start = '{} {} {} {} {}'.format(direction[0], weekday, -+ direction[1], month, -+ ordinal_day) -+ return 'time_zone rule {} from {} to {} starting on {}'.format( -+ self._val['name'], self._val['from'], self._val['to'], start) -+ -+ -+class StdLocalePrinter(printer_base): -+ """Print a std::locale.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ -+ def to_string(self): -+ names = self._val['_M_impl']['_M_names'] -+ mod = '' -+ if names[0] == 0: -+ name = '*' -+ else: -+ cats = gdb.parse_and_eval(self._typename + '::_S_categories') -+ ncat = gdb.parse_and_eval(self._typename + '::_S_categories_size') -+ n = names[0].string() -+ cat = cats[0].string() -+ name = '{}={}'.format(cat, n) -+ cat_names = {cat: n} -+ i = 1 -+ while i < ncat and names[i] != 0: -+ n = names[i].string() -+ cat = cats[i].string() -+ name = '{};{}={}'.format(name, cat, n) -+ cat_names[cat] = n -+ i = i + 1 -+ uniq_names = set(cat_names.values()) -+ if len(uniq_names) == 1: -+ name = n -+ elif len(uniq_names) == 2: -+ n1, n2 = (uniq_names) -+ name_list = list(cat_names.values()) -+ other = None -+ if name_list.count(n1) == 1: -+ name = n2 -+ other = n1 -+ elif name_list.count(n2) == 1: -+ name = n1 -+ other = n2 -+ if other is not None: -+ cat = next(c for c, n in cat_names.items() if n == other) -+ mod = ' with "{}={}"'.format(cat, other) -+ return 'std::locale = "{}"{}'.format(name, mod) -+ -+class StdIntegralConstantPrinter(printer_base): -+ """Print a std::true_type or std::false_type.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ -+ def to_string(self): -+ value_type = self._val.type.template_argument(0) -+ value = self._val.type.template_argument(1) -+ if value_type.code == gdb.TYPE_CODE_BOOL: -+ if value: -+ return "std::true_type" -+ else: -+ return "std::false_type" -+ typename = strip_versioned_namespace(self._typename) -+ return "{}<{}, {}>".format(typename, value_type, value) -+ -+class StdTextEncodingPrinter(printer_base): -+ """Print a std::text_encoding.""" -+ -+ def __init__(self, typename, val): -+ self._val = val -+ self._typename = typename -+ -+ def to_string(self): -+ rep = self._val['_M_rep'].dereference() -+ if rep['_M_id'] == 1: -+ return self._val['_M_name'] -+ if rep['_M_id'] == 2: -+ return 'unknown' -+ return rep['_M_name'] -+ - # A "regular expression" printer which conforms to the - # "SubPrettyPrinter" protocol from gdb.printing. - class RxPrinter(object): - def __init__(self, name, function): - super(RxPrinter, self).__init__() - self.name = name -- self.function = function -+ self._function = function - self.enabled = True - - def invoke(self, value): -@@ -1315,36 +2360,40 @@ class RxPrinter(object): - return None - - if value.type.code == gdb.TYPE_CODE_REF: -- if hasattr(gdb.Value,"referenced_value"): -+ if hasattr(gdb.Value, "referenced_value"): - value = value.referenced_value() - -- return self.function(self.name, value) -+ return self._function(self.name, value) - - # A pretty-printer that conforms to the "PrettyPrinter" protocol from - # gdb.printing. It can also be used directly as an old-style printer. -+ -+ - class Printer(object): - def __init__(self, name): - super(Printer, self).__init__() - self.name = name -- self.subprinters = [] -- self.lookup = {} -+ self._subprinters = [] -+ self._lookup = {} - self.enabled = True -- self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') -+ self._compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') - - def add(self, name, function): - # A small sanity check. - # FIXME -- if not self.compiled_rx.match(name): -- raise ValueError('libstdc++ programming error: "%s" does not match' % name) -+ if not self._compiled_rx.match(name): -+ raise ValueError( -+ 'libstdc++ programming error: "%s" does not match' % name) - printer = RxPrinter(name, function) -- self.subprinters.append(printer) -- self.lookup[name] = printer -+ self._subprinters.append(printer) -+ self._lookup[name] = printer - - # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. - def add_version(self, base, name, function): - self.add(base + name, function) -- if _versioned_namespace: -- vbase = re.sub('^(std|__gnu_cxx)::', r'\g<0>%s' % _versioned_namespace, base) -+ if '__cxx11' not in base: -+ vbase = re.sub('^(std|__gnu_cxx)::', r'\g<0>%s' % -+ _versioned_namespace, base) - self.add(vbase + name, function) - - # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. -@@ -1356,10 +2405,10 @@ class Printer(object): - def get_basic_type(type): - # If it points to a reference, get the reference. - if type.code == gdb.TYPE_CODE_REF: -- type = type.target () -+ type = type.target() - - # Get the unqualified type, stripped of typedefs. -- type = type.unqualified ().strip_typedefs () -+ type = type.unqualified().strip_typedefs() - - return type.tag - -@@ -1370,47 +2419,49 @@ class Printer(object): - - # All the types we match are template types, so we can use a - # dictionary. -- match = self.compiled_rx.match(typename) -+ match = self._compiled_rx.match(typename) - if not match: - return None - - basename = match.group(1) - - if val.type.code == gdb.TYPE_CODE_REF: -- if hasattr(gdb.Value,"referenced_value"): -+ if hasattr(gdb.Value, "referenced_value"): - val = val.referenced_value() - -- if basename in self.lookup: -- return self.lookup[basename].invoke(val) -+ if basename in self._lookup: -+ return self._lookup[basename].invoke(val) - - # Cannot find a pretty printer. Return None. - return None - -+ - libstdcxx_printer = None - -+ - class TemplateTypePrinter(object): -- r""" -+ """ - A type printer for class templates with default template arguments. - - Recognizes specializations of class templates and prints them without - any template arguments that use a default template argument. - Type printers are recursively applied to the template arguments. - -- e.g. replace "std::vector >" with "std::vector". -+ e.g. replace 'std::vector >' with 'std::vector'. - """ - - def __init__(self, name, defargs): - self.name = name -- self.defargs = defargs -+ self._defargs = defargs - self.enabled = True - - class _recognizer(object): -- "The recognizer class for TemplateTypePrinter." -+ """The recognizer class for TemplateTypePrinter.""" - - def __init__(self, name, defargs): - self.name = name -- self.defargs = defargs -- # self.type_obj = None -+ self._defargs = defargs -+ # self._type_obj = None - - def recognize(self, type_obj): - """ -@@ -1433,7 +2484,7 @@ class TemplateTypePrinter(object): - # The actual template argument in the type: - targ = template_args[n] - # The default template argument for the class template: -- defarg = self.defargs.get(n) -+ defarg = self._defargs.get(n) - if defarg is not None: - # Substitute other template arguments into the default: - defarg = defarg.format(*template_args) -@@ -1470,7 +2521,7 @@ class TemplateTypePrinter(object): - if type_obj.code == gdb.TYPE_CODE_ARRAY: - type_str = self._recognize_subtype(type_obj.target()) - if str(type_obj.strip_typedefs()).endswith('[]'): -- return type_str + '[]' # array of unknown bound -+ return type_str + '[]' # array of unknown bound - return "%s[%d]" % (type_str, type_obj.range()[1] + 1) - if type_obj.code == gdb.TYPE_CODE_REF: - return self._recognize_subtype(type_obj.target()) + '&' -@@ -1479,17 +2530,18 @@ class TemplateTypePrinter(object): - return self._recognize_subtype(type_obj.target()) + '&&' - - type_str = gdb.types.apply_type_recognizers( -- gdb.types.get_type_recognizers(), type_obj) -+ gdb.types.get_type_recognizers(), type_obj) - if type_str: - return type_str - return str(type_obj) - - def instantiate(self): -- "Return a recognizer object for this type printer." -- return self._recognizer(self.name, self.defargs) -+ """Return a recognizer object for this type printer.""" -+ return self._recognizer(self.name, self._defargs) -+ - - def add_one_template_type_printer(obj, name, defargs): -- r""" -+ """ - Add a type printer for a class template with default template arguments. - - Args: -@@ -1503,78 +2555,121 @@ def add_one_template_type_printer(obj, name, defargs): - { 2: 'std::hash<{0}>', - 3: 'std::equal_to<{0}>', - 4: 'std::allocator >' } -- - """ -- printer = TemplateTypePrinter('std::'+name, defargs) -+ printer = TemplateTypePrinter('std::' + name, defargs) -+ gdb.types.register_type_printer(obj, printer) -+ -+ # Add type printer for same type in debug namespace: -+ printer = TemplateTypePrinter('std::__debug::' + name, defargs) - gdb.types.register_type_printer(obj, printer) -- if _versioned_namespace: -+ -+ if '__cxx11' not in name: - # Add second type printer for same type in versioned namespace: - ns = 'std::' + _versioned_namespace - # PR 86112 Cannot use dict comprehension here: -- defargs = dict((n, d.replace('std::', ns)) for (n,d) in defargs.items()) -- printer = TemplateTypePrinter(ns+name, defargs) -+ defargs = dict((n, d.replace('std::', ns)) -+ for (n, d) in defargs.items()) -+ printer = TemplateTypePrinter(ns + name, defargs) -+ gdb.types.register_type_printer(obj, printer) -+ -+ # Add type printer for same type in debug namespace: -+ printer = TemplateTypePrinter('std::__debug::' + name, defargs) - gdb.types.register_type_printer(obj, printer) - -+ - class FilteringTypePrinter(object): -- r""" -+ """ - A type printer that uses typedef names for common template specializations. - - Args: -- match (str): The class template to recognize. -+ template (str): The class template to recognize. - name (str): The typedef-name that will be used instead. -+ targ1 (str, optional): The first template argument. Defaults to None. - -- Checks if a specialization of the class template 'match' is the same type -+ Checks if a specialization of the class template 'template' is the same type - as the typedef 'name', and prints it as 'name' instead. - - e.g. if an instantiation of std::basic_istream is the same type as - std::istream then print it as std::istream. -+ -+ If targ1 is provided (not None), match only template specializations with -+ this type as the first template argument, e.g. if template='basic_string' -+ and targ1='char' then only match 'basic_string' and not -+ 'basic_string'. This rejects non-matching specializations -+ more quickly, without needing to do GDB type lookups. - """ - -- def __init__(self, match, name): -- self.match = match -+ def __init__(self, template, name, targ1=None): -+ self._template = template - self.name = name -+ self._targ1 = targ1 - self.enabled = True - - class _recognizer(object): -- "The recognizer class for TemplateTypePrinter." -+ """The recognizer class for FilteringTypePrinter.""" - -- def __init__(self, match, name): -- self.match = match -+ def __init__(self, template, name, targ1): -+ self._template = template - self.name = name -- self.type_obj = None -+ self._targ1 = targ1 -+ self._type_obj = None - - def recognize(self, type_obj): - """ -- If type_obj starts with self.match and is the same type as -+ If type_obj starts with self._template and is the same type as - self.name then return self.name, otherwise None. - """ - if type_obj.tag is None: - return None - -- if self.type_obj is None: -- if not type_obj.tag.startswith(self.match): -+ if self._type_obj is None: -+ if self._targ1 is not None: -+ s = '{}<{}'.format(self._template, self._targ1) -+ if not type_obj.tag.startswith(s): -+ # Filter didn't match. -+ return None -+ elif not type_obj.tag.startswith(self._template): - # Filter didn't match. - return None -+ - try: -- self.type_obj = gdb.lookup_type(self.name).strip_typedefs() -+ self._type_obj = gdb.lookup_type( -+ self.name).strip_typedefs() - except: - pass -- if self.type_obj == type_obj: -+ -+ if self._type_obj is None: -+ return None -+ -+ t1 = gdb.types.get_basic_type(self._type_obj) -+ t2 = gdb.types.get_basic_type(type_obj) -+ if t1 == t2: - return strip_inline_namespaces(self.name) -+ -+ # Workaround ambiguous typedefs matching both std:: and -+ # std::__cxx11:: symbols. -+ if self._template.split('::')[-1] == 'basic_string': -+ s1 = self._type_obj.tag.replace('__cxx11::', '') -+ s2 = type_obj.tag.replace('__cxx11::', '') -+ if s1 == s2: -+ return strip_inline_namespaces(self.name) -+ - return None - - def instantiate(self): -- "Return a recognizer object for this type printer." -- return self._recognizer(self.match, self.name) -+ """Return a recognizer object for this type printer.""" -+ return self._recognizer(self._template, self.name, self._targ1) - --def add_one_type_printer(obj, match, name): -- printer = FilteringTypePrinter('std::' + match, 'std::' + name) -+ -+def add_one_type_printer(obj, template, name, targ1=None): -+ printer = FilteringTypePrinter('std::' + template, 'std::' + name, targ1) - gdb.types.register_type_printer(obj, printer) -- if _versioned_namespace: -+ if '__cxx11' not in template: - ns = 'std::' + _versioned_namespace -- printer = FilteringTypePrinter(ns + match, ns + name) -+ printer = FilteringTypePrinter(ns + template, ns + name, targ1) - gdb.types.register_type_printer(obj, printer) - -+ - def register_type_printers(obj): - global _use_type_printing - -@@ -1582,29 +2677,39 @@ def register_type_printers(obj): - return - - # Add type printers for typedefs std::string, std::wstring etc. -- for ch in ('', 'w', 'u16', 'u32'): -- add_one_type_printer(obj, 'basic_string', ch + 'string') -+ for ch in (('', 'char'), -+ ('w', 'wchar_t'), -+ ('u8', 'char8_t'), -+ ('u16', 'char16_t'), -+ ('u32', 'char32_t')): -+ add_one_type_printer(obj, 'basic_string', ch[0] + 'string', ch[1]) -+ add_one_type_printer(obj, '__cxx11::basic_string', -+ ch[0] + 'string', ch[1]) -+ # Typedefs for __cxx11::basic_string used to be in namespace __cxx11: - add_one_type_printer(obj, '__cxx11::basic_string', -- '__cxx11::' + ch + 'string') -- add_one_type_printer(obj, 'basic_string_view', ch + 'string_view') -+ '__cxx11::' + ch[0] + 'string', ch[1]) -+ add_one_type_printer(obj, 'basic_string_view', -+ ch[0] + 'string_view', ch[1]) - - # Add type printers for typedefs std::istream, std::wistream etc. -- for ch in ('', 'w'): -+ for ch in (('', 'char'), ('w', 'wchar_t')): - for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream', - 'filebuf', 'ifstream', 'ofstream', 'fstream'): -- add_one_type_printer(obj, 'basic_' + x, ch + x) -+ add_one_type_printer(obj, 'basic_' + x, ch[0] + x, ch[1]) - for x in ('stringbuf', 'istringstream', 'ostringstream', - 'stringstream'): -- add_one_type_printer(obj, 'basic_' + x, ch + x) -- # types are in __cxx11 namespace, but typedefs aren'x: -- add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x) -+ add_one_type_printer(obj, 'basic_' + x, ch[0] + x, ch[1]) -+ # types are in __cxx11 namespace, but typedefs aren't: -+ add_one_type_printer(obj, '__cxx11::basic_' + x, ch[0] + x, ch[1]) - - # Add type printers for typedefs regex, wregex, cmatch, wcmatch etc. - for abi in ('', '__cxx11::'): -- for ch in ('', 'w'): -- add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex') -+ for ch in (('', 'char'), ('w', 'wchar_t')): -+ add_one_type_printer(obj, abi + 'basic_regex', -+ abi + ch[0] + 'regex', ch[1]) - for ch in ('c', 's', 'wc', 'ws'): -- add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match') -+ add_one_type_printer( -+ obj, abi + 'match_results', abi + ch + 'match') - for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'): - add_one_type_printer(obj, abi + x, abi + ch + x) - -@@ -1613,9 +2718,9 @@ def register_type_printers(obj): - add_one_type_printer(obj, 'fpos', 'streampos') - - # Add type printers for typedefs. -- for dur in ('nanoseconds', 'microseconds', 'milliseconds', -- 'seconds', 'minutes', 'hours'): -- add_one_type_printer(obj, 'duration', dur) -+ for dur in ('nanoseconds', 'microseconds', 'milliseconds', 'seconds', -+ 'minutes', 'hours', 'days', 'weeks', 'years', 'months'): -+ add_one_type_printer(obj, 'chrono::duration', 'chrono::' + dur) - - # Add type printers for typedefs. - add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') -@@ -1630,47 +2735,54 @@ def register_type_printers(obj): - - # Add type printers for experimental::basic_string_view typedefs. - ns = 'experimental::fundamentals_v1::' -- for ch in ('', 'w', 'u16', 'u32'): -+ for ch in (('', 'char'), -+ ('w', 'wchar_t'), -+ ('u8', 'char8_t'), -+ ('u16', 'char16_t'), -+ ('u32', 'char32_t')): - add_one_type_printer(obj, ns + 'basic_string_view', -- ns + ch + 'string_view') -+ ns + ch[0] + 'string_view', ch[1]) - - # Do not show defaulted template arguments in class templates. - add_one_template_type_printer(obj, 'unique_ptr', -- { 1: 'std::default_delete<{0}>' }) -- add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'}) -- add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'}) -- add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'}) -- add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'}) -- add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'}) -+ {1: 'std::default_delete<{0}>'}) -+ add_one_template_type_printer(obj, 'deque', {1: 'std::allocator<{0}>'}) -+ add_one_template_type_printer( -+ obj, 'forward_list', {1: 'std::allocator<{0}>'}) -+ add_one_template_type_printer(obj, 'list', {1: 'std::allocator<{0}>'}) -+ add_one_template_type_printer( -+ obj, '__cxx11::list', {1: 'std::allocator<{0}>'}) -+ add_one_template_type_printer(obj, 'vector', {1: 'std::allocator<{0}>'}) - add_one_template_type_printer(obj, 'map', -- { 2: 'std::less<{0}>', -- 3: 'std::allocator>' }) -+ {2: 'std::less<{0}>', -+ 3: 'std::allocator>'}) - add_one_template_type_printer(obj, 'multimap', -- { 2: 'std::less<{0}>', -- 3: 'std::allocator>' }) -+ {2: 'std::less<{0}>', -+ 3: 'std::allocator>'}) - add_one_template_type_printer(obj, 'set', -- { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' }) -+ {1: 'std::less<{0}>', 2: 'std::allocator<{0}>'}) - add_one_template_type_printer(obj, 'multiset', -- { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' }) -+ {1: 'std::less<{0}>', 2: 'std::allocator<{0}>'}) - add_one_template_type_printer(obj, 'unordered_map', -- { 2: 'std::hash<{0}>', -- 3: 'std::equal_to<{0}>', -- 4: 'std::allocator>'}) -+ {2: 'std::hash<{0}>', -+ 3: 'std::equal_to<{0}>', -+ 4: 'std::allocator>'}) - add_one_template_type_printer(obj, 'unordered_multimap', -- { 2: 'std::hash<{0}>', -- 3: 'std::equal_to<{0}>', -- 4: 'std::allocator>'}) -+ {2: 'std::hash<{0}>', -+ 3: 'std::equal_to<{0}>', -+ 4: 'std::allocator>'}) - add_one_template_type_printer(obj, 'unordered_set', -- { 1: 'std::hash<{0}>', -- 2: 'std::equal_to<{0}>', -- 3: 'std::allocator<{0}>'}) -+ {1: 'std::hash<{0}>', -+ 2: 'std::equal_to<{0}>', -+ 3: 'std::allocator<{0}>'}) - add_one_template_type_printer(obj, 'unordered_multiset', -- { 1: 'std::hash<{0}>', -- 2: 'std::equal_to<{0}>', -- 3: 'std::allocator<{0}>'}) -+ {1: 'std::hash<{0}>', -+ 2: 'std::equal_to<{0}>', -+ 3: 'std::allocator<{0}>'}) - --def register_libstdcxx_printers (obj): -- "Register libstdc++ pretty-printers with objfile Obj." -+ -+def register_libstdcxx_printers(obj): -+ """Register libstdc++ pretty-printers with objfile Obj.""" - - global _use_gdb_pp - global libstdcxx_printer -@@ -1684,7 +2796,8 @@ def register_libstdcxx_printers (obj): - - register_type_printers(obj) - --def build_libstdcxx_dictionary (): -+ -+def build_libstdcxx_dictionary(): - global libstdcxx_printer - - libstdcxx_printer = Printer("libstdc++-v6") -@@ -1693,7 +2806,8 @@ def build_libstdcxx_dictionary (): - # In order from: - # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html - libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) -- libstdcxx_printer.add_version('std::__cxx11::', 'basic_string', StdStringPrinter) -+ libstdcxx_printer.add_version( -+ 'std::__cxx11::', 'basic_string', StdStringPrinter) - libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) - libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) - libstdcxx_printer.add_container('std::', 'list', StdListPrinter) -@@ -1711,6 +2825,18 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) - libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) - # vector -+ libstdcxx_printer.add_version('std::', 'locale', StdLocalePrinter) -+ -+ libstdcxx_printer.add_version('std::', 'integral_constant', -+ StdIntegralConstantPrinter) -+ libstdcxx_printer.add_version('std::', 'text_encoding', -+ StdTextEncodingPrinter) -+ -+ if hasattr(gdb.Value, 'dynamic_type'): -+ libstdcxx_printer.add_version('std::', 'error_code', -+ StdErrorCodePrinter) -+ libstdcxx_printer.add_version('std::', 'error_condition', -+ StdErrorCodePrinter) - - # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. - libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) -@@ -1719,12 +2845,7 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add('std::__debug::map', StdMapPrinter) - libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) - libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) -- libstdcxx_printer.add('std::__debug::priority_queue', -- StdStackOrQueuePrinter) -- libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) - libstdcxx_printer.add('std::__debug::set', StdSetPrinter) -- libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) -- libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) - libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) - - # These are the TR1 and C++11 printers. -@@ -1742,8 +2863,10 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add_container('std::', 'forward_list', - StdForwardListPrinter) - -- libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) -- libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) -+ libstdcxx_printer.add_version( -+ 'std::tr1::', 'shared_ptr', SharedPointerPrinter) -+ libstdcxx_printer.add_version( -+ 'std::tr1::', 'weak_ptr', SharedPointerPrinter) - libstdcxx_printer.add_version('std::tr1::', 'unordered_map', - Tr1UnorderedMapPrinter) - libstdcxx_printer.add_version('std::tr1::', 'unordered_set', -@@ -1753,6 +2876,28 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', - Tr1UnorderedSetPrinter) - -+ libstdcxx_printer.add_version('std::', 'initializer_list', -+ StdInitializerListPrinter) -+ libstdcxx_printer.add_version('std::', 'atomic', StdAtomicPrinter) -+ libstdcxx_printer.add_version( -+ 'std::', 'basic_stringbuf', StdStringBufPrinter) -+ libstdcxx_printer.add_version( -+ 'std::__cxx11::', 'basic_stringbuf', StdStringBufPrinter) -+ for sstream in ('istringstream', 'ostringstream', 'stringstream'): -+ libstdcxx_printer.add_version( -+ 'std::', 'basic_' + sstream, StdStringStreamPrinter) -+ libstdcxx_printer.add_version( -+ 'std::__cxx11::', 'basic_' + sstream, StdStringStreamPrinter) -+ -+ libstdcxx_printer.add_version('std::chrono::', 'duration', -+ StdChronoDurationPrinter) -+ libstdcxx_printer.add_version('std::chrono::', 'time_point', -+ StdChronoTimePointPrinter) -+ -+ # std::regex components -+ libstdcxx_printer.add_version('std::__detail::', '_State', -+ StdRegexStatePrinter) -+ - # These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases. - # The tr1 namespace containers do not have any debug equivalents, - # so do not register printers for them. -@@ -1780,9 +2925,9 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::', - 'path', StdExpPathPrinter) - libstdcxx_printer.add_version('std::filesystem::', -- 'path', StdExpPathPrinter) -+ 'path', StdPathPrinter) - libstdcxx_printer.add_version('std::filesystem::__cxx11::', -- 'path', StdExpPathPrinter) -+ 'path', StdPathPrinter) - - # C++17 components - libstdcxx_printer.add_version('std::', -@@ -1796,6 +2941,33 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add_version('std::', - '_Node_handle', StdNodeHandlePrinter) - -+ # C++20 components -+ libstdcxx_printer.add_version( -+ 'std::', 'partial_ordering', StdCmpCatPrinter) -+ libstdcxx_printer.add_version('std::', 'weak_ordering', StdCmpCatPrinter) -+ libstdcxx_printer.add_version('std::', 'strong_ordering', StdCmpCatPrinter) -+ libstdcxx_printer.add_version('std::', 'span', StdSpanPrinter) -+ libstdcxx_printer.add_version('std::', 'basic_format_args', -+ StdFormatArgsPrinter) -+ for c in ['day', 'month', 'year', 'weekday', 'weekday_indexed', 'weekday_last', -+ 'month_day', 'month_day_last', 'month_weekday', 'month_weekday_last', -+ 'year_month', 'year_month_day', 'year_month_day_last', -+ 'year_month_weekday', 'year_month_weekday_last', 'hh_mm_ss']: -+ libstdcxx_printer.add_version('std::chrono::', c, -+ StdChronoCalendarPrinter) -+ libstdcxx_printer.add_version('std::chrono::', 'time_zone', -+ StdChronoTimeZonePrinter) -+ libstdcxx_printer.add_version('std::chrono::', 'time_zone_link', -+ StdChronoTimeZonePrinter) -+ libstdcxx_printer.add_version('std::chrono::', 'zoned_time', -+ StdChronoZonedTimePrinter) -+ libstdcxx_printer.add_version('std::chrono::', 'leap_second', -+ StdChronoLeapSecondPrinter) -+ libstdcxx_printer.add_version( -+ 'std::chrono::', 'tzdb', StdChronoTzdbPrinter) -+ # libstdcxx_printer.add_version('std::chrono::(anonymous namespace)', 'Rule', -+ # StdChronoTimeZoneRulePrinter) -+ - # Extensions. - libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) - -@@ -1816,6 +2988,12 @@ def build_libstdcxx_dictionary (): - StdDequeIteratorPrinter) - libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', - StdVectorIteratorPrinter) -+ libstdcxx_printer.add_container('std::', '_Bit_iterator', -+ StdBitIteratorPrinter) -+ libstdcxx_printer.add_container('std::', '_Bit_const_iterator', -+ StdBitIteratorPrinter) -+ libstdcxx_printer.add_container('std::', '_Bit_reference', -+ StdBitReferencePrinter) - libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', - StdSlistIteratorPrinter) - libstdcxx_printer.add_container('std::', '_Fwd_list_iterator', -@@ -1828,4 +3006,5 @@ def build_libstdcxx_dictionary (): - libstdcxx_printer.add('__gnu_debug::_Safe_iterator', - StdDebugIteratorPrinter) - --build_libstdcxx_dictionary () -+ -+build_libstdcxx_dictionary() -diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py -index 12fefdb041c..436c866e001 100644 ---- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py -+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py -@@ -1,6 +1,6 @@ - # Xmethods for libstdc++. - --# Copyright (C) 2014-2018 Free Software Foundation, Inc. -+# Copyright (C) 2014-2024 Free Software Foundation, Inc. - - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -21,12 +21,27 @@ import re - - matcher_name_prefix = 'libstdc++::' - -+ - def get_bool_type(): - return gdb.lookup_type('bool') - - def get_std_size_type(): - return gdb.lookup_type('std::size_t') - -+_versioned_namespace = '__8::' -+ -+def is_specialization_of(x, template_name): -+ """ -+ Test whether a type is a specialization of the named class template. -+ The type can be specified as a string or a gdb.Type object. -+ The template should be the name of a class template as a string, -+ without any 'std' qualification. -+ """ -+ if isinstance(x, gdb.Type): -+ x = x.tag -+ template_name = '(%s)?%s' % (_versioned_namespace, template_name) -+ return re.match(r'^std::(__\d::)?%s<.*>$' % template_name, x) is not None -+ - class LibStdCxxXMethod(gdb.xmethod.XMethod): - def __init__(self, name, worker_class): - gdb.xmethod.XMethod.__init__(self, name) -@@ -34,6 +49,7 @@ class LibStdCxxXMethod(gdb.xmethod.XMethod): - - # Xmethods for std::array - -+ - class ArrayWorkerBase(gdb.xmethod.XMethodWorker): - def __init__(self, val_type, size): - self._val_type = val_type -@@ -43,6 +59,7 @@ class ArrayWorkerBase(gdb.xmethod.XMethodWorker): - nullptr = gdb.parse_and_eval('(void *) 0') - return nullptr.cast(self._val_type.pointer()).dereference() - -+ - class ArraySizeWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -56,6 +73,7 @@ class ArraySizeWorker(ArrayWorkerBase): - def __call__(self, obj): - return self._size - -+ - class ArrayEmptyWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -69,6 +87,7 @@ class ArrayEmptyWorker(ArrayWorkerBase): - def __call__(self, obj): - return (int(self._size) == 0) - -+ - class ArrayFrontWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -85,6 +104,7 @@ class ArrayFrontWorker(ArrayWorkerBase): - else: - return self.null_value() - -+ - class ArrayBackWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -101,6 +121,7 @@ class ArrayBackWorker(ArrayWorkerBase): - else: - return self.null_value() - -+ - class ArrayAtWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -117,6 +138,7 @@ class ArrayAtWorker(ArrayWorkerBase): - ((int(index), self._size))) - return obj['_M_elems'][index] - -+ - class ArraySubscriptWorker(ArrayWorkerBase): - def __init__(self, val_type, size): - ArrayWorkerBase.__init__(self, val_type, size) -@@ -133,6 +155,7 @@ class ArraySubscriptWorker(ArrayWorkerBase): - else: - return self.null_value() - -+ - class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -148,7 +171,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'array'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -160,24 +183,34 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): - return None - return method.worker_class(value_type, size) - -+ - # Xmethods for std::deque - -+ - class DequeWorkerBase(gdb.xmethod.XMethodWorker): - def __init__(self, val_type): - self._val_type = val_type - self._bufsize = 512 // val_type.sizeof or 1 - - def size(self, obj): -- first_node = obj['_M_impl']['_M_start']['_M_node'] -- last_node = obj['_M_impl']['_M_finish']['_M_node'] -- cur = obj['_M_impl']['_M_finish']['_M_cur'] -- first = obj['_M_impl']['_M_finish']['_M_first'] -- return (last_node - first_node) * self._bufsize + (cur - first) -+ start = obj['_M_impl']['_M_start'] -+ finish = obj['_M_impl']['_M_finish'] -+ if start['_M_cur'] == finish['_M_cur']: -+ return 0 -+ return (self._bufsize -+ * (finish['_M_node'] - start['_M_node'] - 1) -+ + (finish['_M_cur'] - finish['_M_first']) -+ + (start['_M_last'] - start['_M_cur'])) - - def index(self, obj, idx): -- first_node = obj['_M_impl']['_M_start']['_M_node'] -- index_node = first_node + int(idx) // self._bufsize -- return index_node[0][idx % self._bufsize] -+ start = obj['_M_impl']['_M_start'] -+ first_node_size = start['_M_last'] - start['_M_cur'] -+ if idx < first_node_size: -+ return start['_M_cur'][idx] -+ idx = idx - first_node_size -+ index_node = start['_M_node'][1 + int(idx) // self._bufsize] -+ return index_node[idx % self._bufsize] -+ - - class DequeEmptyWorker(DequeWorkerBase): - def get_arg_types(self): -@@ -190,6 +223,7 @@ class DequeEmptyWorker(DequeWorkerBase): - return (obj['_M_impl']['_M_start']['_M_cur'] == - obj['_M_impl']['_M_finish']['_M_cur']) - -+ - class DequeSizeWorker(DequeWorkerBase): - def get_arg_types(self): - return None -@@ -200,6 +234,7 @@ class DequeSizeWorker(DequeWorkerBase): - def __call__(self, obj): - return self.size(obj) - -+ - class DequeFrontWorker(DequeWorkerBase): - def get_arg_types(self): - return None -@@ -210,6 +245,7 @@ class DequeFrontWorker(DequeWorkerBase): - def __call__(self, obj): - return obj['_M_impl']['_M_start']['_M_cur'][0] - -+ - class DequeBackWorker(DequeWorkerBase): - def get_arg_types(self): - return None -@@ -219,12 +255,13 @@ class DequeBackWorker(DequeWorkerBase): - - def __call__(self, obj): - if (obj['_M_impl']['_M_finish']['_M_cur'] == -- obj['_M_impl']['_M_finish']['_M_first']): -+ obj['_M_impl']['_M_finish']['_M_first']): - prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1 - return prev_node[0][self._bufsize - 1] - else: - return obj['_M_impl']['_M_finish']['_M_cur'][-1] - -+ - class DequeSubscriptWorker(DequeWorkerBase): - def get_arg_types(self): - return get_std_size_type() -@@ -235,6 +272,7 @@ class DequeSubscriptWorker(DequeWorkerBase): - def __call__(self, obj, subscript): - return self.index(obj, subscript) - -+ - class DequeAtWorker(DequeWorkerBase): - def get_arg_types(self): - return get_std_size_type() -@@ -248,7 +286,8 @@ class DequeAtWorker(DequeWorkerBase): - raise IndexError('Deque index "%d" should not be >= %d.' % - (int(index), deque_size)) - else: -- return self.index(obj, index) -+ return self.index(obj, index) -+ - - class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): -@@ -265,7 +304,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'deque'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -274,6 +313,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for std::forward_list - -+ - class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher): - def __init__(self, val_type, node_type): - self._val_type = val_type -@@ -282,6 +322,7 @@ class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher): - def get_arg_types(self): - return None - -+ - class ForwardListEmptyWorker(ForwardListWorkerBase): - def get_result_type(self, obj): - return get_bool_type() -@@ -289,6 +330,7 @@ class ForwardListEmptyWorker(ForwardListWorkerBase): - def __call__(self, obj): - return obj['_M_impl']['_M_head']['_M_next'] == 0 - -+ - class ForwardListFrontWorker(ForwardListWorkerBase): - def get_result_type(self, obj): - return self._val_type -@@ -298,6 +340,7 @@ class ForwardListFrontWorker(ForwardListWorkerBase): - val_address = node['_M_storage']['_M_storage'].address - return val_address.cast(self._val_type.pointer()).dereference() - -+ - class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - matcher_name = matcher_name_prefix + 'forward_list' -@@ -309,7 +352,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'forward_list'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -320,6 +363,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for std::list - -+ - class ListWorkerBase(gdb.xmethod.XMethodWorker): - def __init__(self, val_type, node_type): - self._val_type = val_type -@@ -337,6 +381,7 @@ class ListWorkerBase(gdb.xmethod.XMethodWorker): - addr = node['_M_storage'].address - return addr.cast(self._val_type.pointer()).dereference() - -+ - class ListEmptyWorker(ListWorkerBase): - def get_result_type(self, obj): - return get_bool_type() -@@ -348,6 +393,7 @@ class ListEmptyWorker(ListWorkerBase): - else: - return False - -+ - class ListSizeWorker(ListWorkerBase): - def get_result_type(self, obj): - return get_std_size_type() -@@ -361,6 +407,7 @@ class ListSizeWorker(ListWorkerBase): - size += 1 - return size - -+ - class ListFrontWorker(ListWorkerBase): - def get_result_type(self, obj): - return self._val_type -@@ -369,6 +416,7 @@ class ListFrontWorker(ListWorkerBase): - node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type) - return self.get_value_from_node(node) - -+ - class ListBackWorker(ListWorkerBase): - def get_result_type(self, obj): - return self._val_type -@@ -377,6 +425,7 @@ class ListBackWorker(ListWorkerBase): - prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type) - return self.get_value_from_node(prev_node) - -+ - class ListMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -390,7 +439,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, '(__cxx11::)?list'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -401,6 +450,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for std::vector - -+ - class VectorWorkerBase(gdb.xmethod.XMethodWorker): - def __init__(self, val_type): - self._val_type = val_type -@@ -425,6 +475,7 @@ class VectorWorkerBase(gdb.xmethod.XMethodWorker): - else: - return obj['_M_impl']['_M_start'][index] - -+ - class VectorEmptyWorker(VectorWorkerBase): - def get_arg_types(self): - return None -@@ -435,6 +486,7 @@ class VectorEmptyWorker(VectorWorkerBase): - def __call__(self, obj): - return int(self.size(obj)) == 0 - -+ - class VectorSizeWorker(VectorWorkerBase): - def get_arg_types(self): - return None -@@ -445,6 +497,7 @@ class VectorSizeWorker(VectorWorkerBase): - def __call__(self, obj): - return self.size(obj) - -+ - class VectorFrontWorker(VectorWorkerBase): - def get_arg_types(self): - return None -@@ -455,6 +508,7 @@ class VectorFrontWorker(VectorWorkerBase): - def __call__(self, obj): - return self.get(obj, 0) - -+ - class VectorBackWorker(VectorWorkerBase): - def get_arg_types(self): - return None -@@ -465,6 +519,7 @@ class VectorBackWorker(VectorWorkerBase): - def __call__(self, obj): - return self.get(obj, int(self.size(obj)) - 1) - -+ - class VectorAtWorker(VectorWorkerBase): - def get_arg_types(self): - return get_std_size_type() -@@ -479,6 +534,7 @@ class VectorAtWorker(VectorWorkerBase): - ((int(index), size))) - return self.get(obj, int(index)) - -+ - class VectorSubscriptWorker(VectorWorkerBase): - def get_arg_types(self): - return get_std_size_type() -@@ -489,6 +545,7 @@ class VectorSubscriptWorker(VectorWorkerBase): - def __call__(self, obj, subscript): - return self.get(obj, int(subscript)) - -+ - class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -505,7 +562,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'vector'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -514,6 +571,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for associative containers - -+ - class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): - def __init__(self, unordered): - self._unordered = unordered -@@ -527,6 +585,7 @@ class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): - def get_arg_types(self): - return None - -+ - class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): - def get_result_type(self, obj): - return get_bool_type() -@@ -534,6 +593,7 @@ class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): - def __call__(self, obj): - return int(self.node_count(obj)) == 0 - -+ - class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): - def get_result_type(self, obj): - return get_std_size_type() -@@ -541,6 +601,7 @@ class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): - def __call__(self, obj): - return self.node_count(obj) - -+ - class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self, name): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -554,7 +615,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag): -+ if not is_specialization_of(class_type, self._name): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -564,8 +625,11 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for std::unique_ptr - -+ - class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): -- "Implements std::unique_ptr::get() and std::unique_ptr::operator->()" -+ """ -+ Implement std::unique_ptr::get() and std::unique_ptr::operator->(). -+ """ - - def __init__(self, elem_type): - self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY -@@ -581,19 +645,31 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): - return self._elem_type.pointer() - - def _supports(self, method_name): -- "operator-> is not supported for unique_ptr" -+ # operator-> is not supported for unique_ptr - return method_name == 'get' or not self._is_array - - def __call__(self, obj): - impl_type = obj.dereference().type.fields()[0].type.tag -- if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation -- return obj['_M_t']['_M_t']['_M_head_impl'] -- elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type): -- return obj['_M_t']['_M_head_impl'] -- return None -+ # Check for new implementations first: -+ if is_specialization_of(impl_type, '__uniq_ptr_(data|impl)'): -+ tuple_member = obj['_M_t']['_M_t'] -+ elif is_specialization_of(impl_type, 'tuple'): -+ tuple_member = obj['_M_t'] -+ else: -+ return None -+ tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl -+ tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base -+ head_field = tuple_head_type.fields()[0] -+ if head_field.name == '_M_head_impl': -+ return tuple_member.cast(tuple_head_type)['_M_head_impl'] -+ elif head_field.is_base_class: -+ return tuple_member.cast(head_field.type) -+ else: -+ return None -+ - - class UniquePtrDerefWorker(UniquePtrGetWorker): -- "Implements std::unique_ptr::operator*()" -+ """Implement std::unique_ptr::operator*().""" - - def __init__(self, elem_type): - UniquePtrGetWorker.__init__(self, elem_type) -@@ -602,14 +678,15 @@ class UniquePtrDerefWorker(UniquePtrGetWorker): - return self._elem_type - - def _supports(self, method_name): -- "operator* is not supported for unique_ptr" -+ # operator* is not supported for unique_ptr - return not self._is_array - - def __call__(self, obj): - return UniquePtrGetWorker.__call__(self, obj).dereference() - -+ - class UniquePtrSubscriptWorker(UniquePtrGetWorker): -- "Implements std::unique_ptr::operator[](size_t)" -+ """Implement std::unique_ptr::operator[](size_t).""" - - def __init__(self, elem_type): - UniquePtrGetWorker.__init__(self, elem_type) -@@ -621,12 +698,13 @@ class UniquePtrSubscriptWorker(UniquePtrGetWorker): - return self._elem_type - - def _supports(self, method_name): -- "operator[] is only supported for unique_ptr" -+ # operator[] is only supported for unique_ptr - return self._is_array - - def __call__(self, obj, index): - return UniquePtrGetWorker.__call__(self, obj)[index] - -+ - class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -640,7 +718,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'unique_ptr'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -652,8 +730,11 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - - # Xmethods for std::shared_ptr - -+ - class SharedPtrGetWorker(gdb.xmethod.XMethodWorker): -- "Implements std::shared_ptr::get() and std::shared_ptr::operator->()" -+ """ -+ Implements std::shared_ptr::get() and std::shared_ptr::operator->(). -+ """ - - def __init__(self, elem_type): - self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY -@@ -669,14 +750,15 @@ class SharedPtrGetWorker(gdb.xmethod.XMethodWorker): - return self._elem_type.pointer() - - def _supports(self, method_name): -- "operator-> is not supported for shared_ptr" -+ # operator-> is not supported for shared_ptr - return method_name == 'get' or not self._is_array - - def __call__(self, obj): - return obj['_M_ptr'] - -+ - class SharedPtrDerefWorker(SharedPtrGetWorker): -- "Implements std::shared_ptr::operator*()" -+ """Implement std::shared_ptr::operator*().""" - - def __init__(self, elem_type): - SharedPtrGetWorker.__init__(self, elem_type) -@@ -685,14 +767,15 @@ class SharedPtrDerefWorker(SharedPtrGetWorker): - return self._elem_type - - def _supports(self, method_name): -- "operator* is not supported for shared_ptr" -+ # operator* is not supported for shared_ptr - return not self._is_array - - def __call__(self, obj): - return SharedPtrGetWorker.__call__(self, obj).dereference() - -+ - class SharedPtrSubscriptWorker(SharedPtrGetWorker): -- "Implements std::shared_ptr::operator[](size_t)" -+ """Implement std::shared_ptr::operator[](size_t).""" - - def __init__(self, elem_type): - SharedPtrGetWorker.__init__(self, elem_type) -@@ -704,22 +787,23 @@ class SharedPtrSubscriptWorker(SharedPtrGetWorker): - return self._elem_type - - def _supports(self, method_name): -- "operator[] is only supported for shared_ptr" -+ # operator[] is only supported for shared_ptr - return self._is_array - - def __call__(self, obj, index): - # Check bounds if _elem_type is an array of known bound -- m = re.match('.*\[(\d+)]$', str(self._elem_type)) -+ m = re.match(r'.*\[(\d+)]$', str(self._elem_type)) - if m and index >= int(m.group(1)): - raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' % - (self._elem_type, int(index), int(m.group(1)))) - return SharedPtrGetWorker.__call__(self, obj)[index] - -+ - class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker): -- "Implements std::shared_ptr::use_count()" -+ """Implement std::shared_ptr::use_count().""" - - def __init__(self, elem_type): -- SharedPtrUseCountWorker.__init__(self, elem_type) -+ pass - - def get_arg_types(self): - return None -@@ -727,12 +811,16 @@ class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker): - def get_result_type(self, obj): - return gdb.lookup_type('long') - -+ def _supports(self, method_name): -+ return True -+ - def __call__(self, obj): - refcounts = obj['_M_refcount']['_M_pi'] - return refcounts['_M_use_count'] if refcounts else 0 - -+ - class SharedPtrUniqueWorker(SharedPtrUseCountWorker): -- "Implements std::shared_ptr::unique()" -+ """Implement std::shared_ptr::unique().""" - - def __init__(self, elem_type): - SharedPtrUseCountWorker.__init__(self, elem_type) -@@ -743,6 +831,7 @@ class SharedPtrUniqueWorker(SharedPtrUseCountWorker): - def __call__(self, obj): - return SharedPtrUseCountWorker.__call__(self, obj) == 1 - -+ - class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - def __init__(self): - gdb.xmethod.XMethodMatcher.__init__(self, -@@ -758,7 +847,7 @@ class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - self.methods = [self._method_dict[m] for m in self._method_dict] - - def match(self, class_type, method_name): -- if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag): -+ if not is_specialization_of(class_type, 'shared_ptr'): - return None - method = self._method_dict.get(method_name) - if method is None or not method.enabled: -@@ -768,6 +857,7 @@ class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): - return worker - return None - -+ - def register_libstdcxx_xmethods(locus): - gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher()) - gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher()) diff --git a/SOURCES/gcc8-mcet.patch b/SOURCES/gcc8-mcet.patch deleted file mode 100644 index 6fb78ca..0000000 --- a/SOURCES/gcc8-mcet.patch +++ /dev/null @@ -1,17 +0,0 @@ -2018-04-24 Jakub Jelinek - - * config/i386/i386.opt (mcet): Remporarily re-add as alias to -mshstk. - ---- gcc/config/i386/i386.opt (revision 259613) -+++ gcc/config/i386/i386.opt (revision 259612) -@@ -1006,6 +1006,10 @@ mgeneral-regs-only - Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save - Generate code which uses only the general registers. - -+mcet -+Target Undocumented Alias(mshstk) -+;; Deprecated -+ - mshstk - Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags) Save - Enable shadow stack built-in functions from Control-flow Enforcement diff --git a/SOURCES/gcc8-pch-tweaks.patch b/SOURCES/gcc8-pch-tweaks.patch deleted file mode 100644 index 6d25329..0000000 --- a/SOURCES/gcc8-pch-tweaks.patch +++ /dev/null @@ -1,844 +0,0 @@ -commit fe7c3ecff1f9c0520090a77fa824d8c5d9dbec12 -Author: Jakub Jelinek -Date: Fri Dec 3 11:03:30 2021 +0100 - - pch: Add support for PCH for relocatable executables [PR71934] - - So, if we want to make PCH work for PIEs, I'd say we can: - 1) add a new GTY option, say callback, which would act like - skip for non-PCH and for PCH would make us skip it but - remember for address bias translation - 2) drop the skip for tree_translation_unit_decl::language - 3) change get_unnamed_section to have const char * as - last argument instead of const void *, change - unnamed_section::data also to const char * and update - everything related to that - 4) maybe add a host hook whether it is ok to support binaries - changing addresses (the only thing I'm worried is if - some host that uses function descriptors allocates them - dynamically instead of having them somewhere in the - executable) - 5) maybe add a gengtype warning if it sees in GTY tracked - structure a function pointer without that new callback - option - - Here is 1), 2), 3) implemented. - - Note, on stdc++.h.gch/O2g.gch there are just those 10 relocations without - the second patch, with it a few more, but nothing huge. And for non-PIEs - there isn't really any extra work on the load side except freading two scalar - values and fseek. - - 2021-12-03 Jakub Jelinek - - PR pch/71934 - gcc/ - * ggc.h (gt_pch_note_callback): Declare. - * gengtype.h (enum typekind): Add TYPE_CALLBACK. - (callback_type): Declare. - * gengtype.c (dbgprint_count_type_at): Handle TYPE_CALLBACK. - (callback_type): New variable. - (process_gc_options): Add CALLBACK argument, handle callback - option. - (set_gc_used_type): Adjust process_gc_options caller, if callback, - set type to &callback_type. - (output_mangled_typename): Handle TYPE_CALLBACK. - (walk_type): Likewise. Handle callback option. - (write_types_process_field): Handle TYPE_CALLBACK. - (write_types_local_user_process_field): Likewise. - (write_types_local_process_field): Likewise. - (write_root): Likewise. - (dump_typekind): Likewise. - (dump_type): Likewise. - * gengtype-state.c (type_lineloc): Handle TYPE_CALLBACK. - (state_writer::write_state_callback_type): New method. - (state_writer::write_state_type): Handle TYPE_CALLBACK. - (read_state_callback_type): New function. - (read_state_type): Handle TYPE_CALLBACK. - * ggc-common.c (callback_vec): New variable. - (gt_pch_note_callback): New function. - (gt_pch_save): Stream out gt_pch_save function address and relocation - table. - (gt_pch_restore): Stream in saved gt_pch_save function address and - relocation table and apply relocations if needed. - * doc/gty.texi (callback): Document new GTY option. - * varasm.c (get_unnamed_section): Change callback argument's type and - last argument's type from const void * to const char *. - (output_section_asm_op): Change argument's type from const void * - to const char *, remove unnecessary cast. - * tree-core.h (struct tree_translation_unit_decl): Drop GTY((skip)) - from language member. - * output.h (unnamed_section_callback): Change argument type from - const void * to const char *. - (struct unnamed_section): Use GTY((callback)) instead of GTY((skip)) - for callback member. Change data member type from const void * - to const char *. - (struct noswitch_section): Use GTY((callback)) instead of GTY((skip)) - for callback member. - (get_unnamed_section): Change callback argument's type and - last argument's type from const void * to const char *. - (output_section_asm_op): Change argument's type from const void * - to const char *. - * config/avr/avr.c (avr_output_progmem_section_asm_op): Likewise. - Remove unneeded cast. - * config/darwin.c (output_objc_section_asm_op): Change argument's type - from const void * to const char *. - * config/pa/pa.c (som_output_text_section_asm_op): Likewise. - (som_output_comdat_data_section_asm_op): Likewise. - * config/rs6000/rs6000.c (rs6000_elf_output_toc_section_asm_op): - Likewise. - (rs6000_xcoff_output_readonly_section_asm_op): Likewise. Instead - of dereferencing directive hardcode variable names and decide based on - whether directive is NULL or not. - (rs6000_xcoff_output_readwrite_section_asm_op): Change argument's type - from const void * to const char *. - (rs6000_xcoff_output_tls_section_asm_op): Likewise. Instead - of dereferencing directive hardcode variable names and decide based on - whether directive is NULL or not. - (rs6000_xcoff_output_toc_section_asm_op): Change argument's type - from const void * to const char *. - (rs6000_xcoff_asm_init_sections): Adjust get_unnamed_section callers. - gcc/c-family/ - * c-pch.c (struct c_pch_validity): Remove pch_init member. - (pch_init): Don't initialize v.pch_init. - (c_common_valid_pch): Don't warn and punt if .text addresses change. - libcpp/ - * include/line-map.h (class line_maps): Add GTY((callback)) to - reallocator and round_alloc_size members. - -commit 4dc6d19222581c77a174d44d97507d234fb7e39b -Author: Jakub Jelinek -Date: Mon Dec 6 11:18:58 2021 +0100 - - avr: Fix AVR build [PR71934] - - On Mon, Dec 06, 2021 at 11:00:30AM +0100, Martin Liška wrote: - > Jakub, I think the patch broke avr-linux target: - > - > g++ -fno-PIE -c -g -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-erro - > /home/marxin/Programming/gcc/gcc/config/avr/avr.c: In function ‘void avr_output_data_section_asm_op(const void*)’: - > /home/marxin/Programming/gcc/gcc/config/avr/avr.c:10097:26: error: invalid conversion from ‘const void*’ to ‘const char*’ [-fpermissive] - - This patch fixes that. - - 2021-12-06 Jakub Jelinek - - PR pch/71934 - * config/avr/avr.c (avr_output_data_section_asm_op, - avr_output_bss_section_asm_op): Change argument type from const void * - to const char *. - -diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c -index 5da60423354..2cafa1387bb 100644 ---- a/gcc/c-family/c-pch.c -+++ b/gcc/c-family/c-pch.c -@@ -58,7 +58,6 @@ struct c_pch_validity - { - unsigned char debug_info_type; - signed char match[MATCH_SIZE]; -- void (*pch_init) (void); - size_t target_data_length; - }; - -@@ -123,7 +122,6 @@ pch_init (void) - gcc_assert (v.match[i] == *pch_matching[i].flag_var); - } - } -- v.pch_init = &pch_init; - target_validity = targetm.get_pch_validity (&v.target_data_length); - - if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1 -@@ -287,20 +285,6 @@ c_common_valid_pch (cpp_reader *pfile, c - } - } - -- /* If the text segment was not loaded at the same address as it was -- when the PCH file was created, function pointers loaded from the -- PCH will not be valid. We could in theory remap all the function -- pointers, but no support for that exists at present. -- Since we have the same executable, it should only be necessary to -- check one function. */ -- if (v.pch_init != &pch_init) -- { -- if (cpp_get_options (pfile)->warn_invalid_pch) -- cpp_error (pfile, CPP_DL_WARNING, -- "%s: had text segment at different address", name); -- return 2; -- } -- - /* Check the target-specific validity data. */ - { - void *this_file_data = xmalloc (v.target_data_length); -diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c -index 200701a583c..6ba038881d6 100644 ---- a/gcc/config/avr/avr.c -+++ b/gcc/config/avr/avr.c -@@ -10114,10 +10114,9 @@ avr_output_bss_section_asm_op (const void *data) - /* Unnamed section callback for progmem*.data sections. */ - - static void --avr_output_progmem_section_asm_op (const void *data) -+avr_output_progmem_section_asm_op (const char *data) - { -- fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", -- (const char*) data); -+ fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data); - } - - -diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c -index c5ba7927ce1..8ad5b26c980 100644 ---- a/gcc/config/darwin.c -+++ b/gcc/config/darwin.c -@@ -134,7 +134,7 @@ int emit_aligned_common = false; - DIRECTIVE is as for output_section_asm_op. */ - - static void --output_objc_section_asm_op (const void *directive) -+output_objc_section_asm_op (const char *directive) - { - static bool been_here = false; - -diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c -index f22d25a4066..2b10ef34061 100644 ---- a/gcc/config/pa/pa.c -+++ b/gcc/config/pa/pa.c -@@ -10009,7 +10009,7 @@ pa_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg) - to the default text subspace. */ - - static void --som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED) -+som_output_text_section_asm_op (const char *data ATTRIBUTE_UNUSED) - { - gcc_assert (TARGET_SOM); - if (TARGET_GAS) -@@ -10053,7 +10053,7 @@ som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED) - sections. This function is only used with SOM. */ - - static void --som_output_comdat_data_section_asm_op (const void *data) -+som_output_comdat_data_section_asm_op (const char *data) - { - in_section = NULL; - output_section_asm_op (data); -diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c -index 945157b1c1a..34089743759 100644 ---- a/gcc/config/rs6000/rs6000.c -+++ b/gcc/config/rs6000/rs6000.c -@@ -20599,7 +20599,7 @@ rs6000_ms_bitfield_layout_p (const_tree record_type) - /* A get_unnamed_section callback, used for switching to toc_section. */ - - static void --rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED) -+rs6000_elf_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED) - { - if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) - && TARGET_MINIMAL_TOC) -@@ -21303,35 +21303,39 @@ rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name) - points to the section string variable. */ - - static void --rs6000_xcoff_output_readonly_section_asm_op (const void *directive) -+rs6000_xcoff_output_readonly_section_asm_op (const char *directive) - { - fprintf (asm_out_file, "\t.csect %s[RO],%s\n", -- *(const char *const *) directive, -+ directive -+ ? xcoff_private_rodata_section_name -+ : xcoff_read_only_section_name, - XCOFF_CSECT_DEFAULT_ALIGNMENT_STR); - } - - /* Likewise for read-write sections. */ - - static void --rs6000_xcoff_output_readwrite_section_asm_op (const void *directive) -+rs6000_xcoff_output_readwrite_section_asm_op (const char *) - { - fprintf (asm_out_file, "\t.csect %s[RW],%s\n", -- *(const char *const *) directive, -+ xcoff_private_data_section_name, - XCOFF_CSECT_DEFAULT_ALIGNMENT_STR); - } - - static void --rs6000_xcoff_output_tls_section_asm_op (const void *directive) -+rs6000_xcoff_output_tls_section_asm_op (const char *directive) - { - fprintf (asm_out_file, "\t.csect %s[TL],%s\n", -- *(const char *const *) directive, -+ directive -+ ? xcoff_private_data_section_name -+ : xcoff_tls_data_section_name, - XCOFF_CSECT_DEFAULT_ALIGNMENT_STR); - } - - /* A get_unnamed_section callback, used for switching to toc_section. */ - - static void --rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED) -+rs6000_xcoff_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED) - { - if (TARGET_MINIMAL_TOC) - { -@@ -21358,26 +21362,26 @@ rs6000_xcoff_asm_init_sections (void) - { - read_only_data_section - = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op, -- &xcoff_read_only_section_name); -+ NULL); - - private_data_section - = get_unnamed_section (SECTION_WRITE, - rs6000_xcoff_output_readwrite_section_asm_op, -- &xcoff_private_data_section_name); -+ NULL); - - read_only_private_data_section - = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op, -- &xcoff_private_rodata_section_name); -+ ""); - - tls_data_section - = get_unnamed_section (SECTION_TLS, - rs6000_xcoff_output_tls_section_asm_op, -- &xcoff_tls_data_section_name); -+ NULL); - - tls_private_data_section - = get_unnamed_section (SECTION_TLS, - rs6000_xcoff_output_tls_section_asm_op, -- &xcoff_private_data_section_name); -+ ""); - - toc_section - = get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL); -diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi -index b996ff2c44e..ca2c8404894 100644 ---- a/gcc/doc/gty.texi -+++ b/gcc/doc/gty.texi -@@ -205,6 +205,15 @@ If @code{skip} is applied to a field, the type machinery will ignore it. - This is somewhat dangerous; the only safe use is in a union when one - field really isn't ever used. - -+@findex callback -+@item callback -+ -+@code{callback} should be applied to fields with pointer to function type -+and causes the field to be ignored similarly to @code{skip}, except when -+writing PCH and the field is non-NULL it will remember the field's address -+for relocation purposes if the process writing PCH has different load base -+from a process reading PCH. -+ - @findex for_user - @item for_user - -diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c -index ac9d536963f..36a96e84574 100644 ---- a/gcc/gengtype-state.c -+++ b/gcc/gengtype-state.c -@@ -57,6 +57,7 @@ type_lineloc (const_type_p ty) - case TYPE_STRING: - case TYPE_POINTER: - case TYPE_ARRAY: -+ case TYPE_CALLBACK: - return NULL; - default: - gcc_unreachable (); -@@ -171,6 +172,7 @@ private: - void write_state_version (const char *version); - void write_state_scalar_type (type_p current); - void write_state_string_type (type_p current); -+ void write_state_callback_type (type_p current); - void write_state_undefined_type (type_p current); - void write_state_struct_union_type (type_p current, const char *kindstr); - void write_state_struct_type (type_p current); -@@ -898,6 +900,20 @@ state_writer::write_state_string_type (type_p current) - fatal ("Unexpected type in write_state_string_type"); - } - -+/* Write the callback type. There is only one such thing! */ -+void -+state_writer::write_state_callback_type (type_p current) -+{ -+ if (current == &callback_type) -+ { -+ write_any_indent (0); -+ fprintf (state_file, "callback "); -+ write_state_common_type_content (current); -+ } -+ else -+ fatal ("Unexpected type in write_state_callback_type"); -+} -+ - /* Write an undefined type. */ - void - state_writer::write_state_undefined_type (type_p current) -@@ -1143,6 +1159,9 @@ state_writer::write_state_type (type_p current) - case TYPE_STRING: - write_state_string_type (current); - break; -+ case TYPE_CALLBACK: -+ write_state_callback_type (current); -+ break; - } - } - -@@ -1477,6 +1496,14 @@ read_state_string_type (type_p *type) - read_state_common_type_content (*type); - } - -+/* Read the callback_type. */ -+static void -+read_state_callback_type (type_p *type) -+{ -+ *type = &callback_type; -+ read_state_common_type_content (*type); -+} -+ - - /* Read a lang_bitmap representing a set of GCC front-end languages. */ - static void -@@ -1834,6 +1861,11 @@ read_state_type (type_p *current) - next_state_tokens (1); - read_state_string_type (current); - } -+ else if (state_token_is_name (t0, "callback")) -+ { -+ next_state_tokens (1); -+ read_state_callback_type (current); -+ } - else if (state_token_is_name (t0, "undefined")) - { - *current = XCNEW (struct type); -diff --git a/gcc/gengtype.c b/gcc/gengtype.c -index a77cfd92bfa..b9daaa43689 100644 ---- a/gcc/gengtype.c -+++ b/gcc/gengtype.c -@@ -172,6 +172,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t) - int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0; - int nb_lang_struct = 0; - int nb_user_struct = 0, nb_undefined = 0; -+ int nb_callback = 0; - type_p p = NULL; - for (p = t; p; p = p->next) - { -@@ -202,6 +203,9 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t) - case TYPE_ARRAY: - nb_array++; - break; -+ case TYPE_CALLBACK: -+ nb_callback++; -+ break; - case TYPE_LANG_STRUCT: - nb_lang_struct++; - break; -@@ -217,6 +221,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t) - fprintf (stderr, "@@%%@@ %d structs, %d unions\n", nb_struct, nb_union); - if (nb_pointer > 0 || nb_array > 0) - fprintf (stderr, "@@%%@@ %d pointers, %d arrays\n", nb_pointer, nb_array); -+ if (nb_callback > 0) -+ fprintf (stderr, "@@%%@@ %d callbacks\n", nb_callback); - if (nb_lang_struct > 0) - fprintf (stderr, "@@%%@@ %d lang_structs\n", nb_lang_struct); - if (nb_user_struct > 0) -@@ -495,6 +501,10 @@ struct type scalar_char = { - TYPE_SCALAR, 0, 0, 0, GC_USED, {0} - }; - -+struct type callback_type = { -+ TYPE_CALLBACK, 0, 0, 0, GC_USED, {0} -+}; -+ - /* Lists of various things. */ - - pair_p typedefs = NULL; -@@ -1464,7 +1474,7 @@ static void set_gc_used (pair_p); - - static void - process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, -- int *length, int *skip, type_p *nested_ptr) -+ int *length, int *skip, int *callback, type_p *nested_ptr) - { - options_p o; - for (o = opt; o; o = o->next) -@@ -1478,6 +1488,8 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, - *length = 1; - else if (strcmp (o->name, "skip") == 0) - *skip = 1; -+ else if (strcmp (o->name, "callback") == 0) -+ *callback = 1; - else if (strcmp (o->name, "nested_ptr") == 0 - && o->kind == OPTION_NESTED) - *nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type; -@@ -1526,7 +1538,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, - type_p dummy2; - bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT); - -- process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, -+ process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy, - &dummy2); - - if (t->u.s.base_class) -@@ -1542,9 +1554,10 @@ set_gc_used_type (type_p t, enum gc_used_enum level, - int maybe_undef = 0; - int length = 0; - int skip = 0; -+ int callback = 0; - type_p nested_ptr = NULL; - process_gc_options (f->opt, level, &maybe_undef, &length, &skip, -- &nested_ptr); -+ &callback, &nested_ptr); - - if (nested_ptr && f->type->kind == TYPE_POINTER) - set_gc_used_type (nested_ptr, GC_POINTED_TO); -@@ -1554,6 +1567,8 @@ set_gc_used_type (type_p t, enum gc_used_enum level, - set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO); - else if (skip) - ; /* target type is not used through this field */ -+ else if (callback) -+ f->type = &callback_type; - else - set_gc_used_type (f->type, GC_USED, allow_undefined_field_types); - } -@@ -2519,6 +2534,7 @@ output_mangled_typename (outf_p of, const_type_p t) - { - case TYPE_NONE: - case TYPE_UNDEFINED: -+ case TYPE_CALLBACK: - gcc_unreachable (); - break; - case TYPE_POINTER: -@@ -2719,6 +2735,8 @@ walk_type (type_p t, struct walk_type_data *d) - ; - else if (strcmp (oo->name, "for_user") == 0) - ; -+ else if (strcmp (oo->name, "callback") == 0) -+ ; - else - error_at_line (d->line, "unknown option `%s'\n", oo->name); - -@@ -2744,6 +2762,7 @@ walk_type (type_p t, struct walk_type_data *d) - { - case TYPE_SCALAR: - case TYPE_STRING: -+ case TYPE_CALLBACK: - d->process_field (t, d); - break; - -@@ -3275,6 +3294,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d) - break; - - case TYPE_SCALAR: -+ case TYPE_CALLBACK: - break; - - case TYPE_ARRAY: -@@ -3820,6 +3840,7 @@ write_types_local_user_process_field (type_p f, const struct walk_type_data *d) - break; - - case TYPE_SCALAR: -+ case TYPE_CALLBACK: - break; - - case TYPE_ARRAY: -@@ -3906,6 +3927,13 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d) - case TYPE_SCALAR: - break; - -+ case TYPE_CALLBACK: -+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "", -+ d->prev_val[3]); -+ oprintf (d->of, "%*s gt_pch_note_callback (&(%s), this_obj);\n", -+ d->indent, "", d->val); -+ break; -+ - case TYPE_ARRAY: - case TYPE_NONE: - case TYPE_UNDEFINED: -@@ -4434,6 +4462,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, - case TYPE_UNDEFINED: - case TYPE_UNION: - case TYPE_LANG_STRUCT: -+ case TYPE_CALLBACK: - error_at_line (line, "global `%s' is unimplemented type", name); - } - } -@@ -4728,6 +4757,9 @@ dump_typekind (int indent, enum typekind kind) - case TYPE_ARRAY: - printf ("TYPE_ARRAY"); - break; -+ case TYPE_CALLBACK: -+ printf ("TYPE_CALLBACK"); -+ break; - case TYPE_LANG_STRUCT: - printf ("TYPE_LANG_STRUCT"); - break; -@@ -4894,6 +4926,7 @@ dump_type (int indent, type_p t) - t->u.scalar_is_char ? "true" : "false"); - break; - case TYPE_STRING: -+ case TYPE_CALLBACK: - break; - case TYPE_STRUCT: - case TYPE_UNION: -diff --git a/gcc/gengtype.h b/gcc/gengtype.h -index 8a7a54957ea..8fa7064ca85 100644 ---- a/gcc/gengtype.h -+++ b/gcc/gengtype.h -@@ -154,6 +154,9 @@ enum typekind { - TYPE_UNION, /* Type for GTY-ed discriminated unions. */ - TYPE_POINTER, /* Pointer type to GTY-ed type. */ - TYPE_ARRAY, /* Array of GTY-ed types. */ -+ TYPE_CALLBACK, /* A function pointer that needs relocation if -+ the executable has been loaded at a different -+ address. */ - TYPE_LANG_STRUCT, /* GCC front-end language specific structs. - Various languages may have homonymous but - different structs. */ -@@ -331,6 +334,9 @@ extern struct type string_type; - extern struct type scalar_nonchar; - extern struct type scalar_char; - -+/* The one and only TYPE_CALLBACK. */ -+extern struct type callback_type; -+ - /* Test if a type is a union, either a plain one or a language - specific one. */ - #define UNION_P(x) \ -diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c -index b6abed1d9a2..7c998e95473 100644 ---- a/gcc/ggc-common.c -+++ b/gcc/ggc-common.c -@@ -256,6 +256,7 @@ saving_hasher::equal (const ptr_data *p1 - } - - static hash_table *saving_htab; -+static vec callback_vec; - - /* Register an object in the hash table. */ - -@@ -288,6 +289,23 @@ gt_pch_note_object (void *obj, void *not - return 1; - } - -+/* Register address of a callback pointer. */ -+void -+gt_pch_note_callback (void *obj, void *base) -+{ -+ void *ptr; -+ memcpy (&ptr, obj, sizeof (void *)); -+ if (ptr != NULL) -+ { -+ struct ptr_data *data -+ = (struct ptr_data *) -+ saving_htab->find_with_hash (base, POINTER_HASH (base)); -+ gcc_assert (data); -+ callback_vec.safe_push ((char *) data->new_addr -+ + ((char *) obj - (char *) base)); -+ } -+} -+ - /* Register an object in the hash table. */ - - void -@@ -582,10 +600,20 @@ gt_pch_save (FILE *f) - ggc_pch_finish (state.d, state.f); - gt_pch_fixup_stringpool (); - -+ unsigned num_callbacks = callback_vec.length (); -+ void (*pch_save) (FILE *) = >_pch_save; -+ if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1 -+ || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1 -+ || (num_callbacks -+ && fwrite (callback_vec.address (), sizeof (void *), num_callbacks, -+ f) != num_callbacks)) -+ fatal_error (input_location, "cannot write PCH file: %m"); -+ - XDELETE (state.ptrs); - XDELETE (this_object); - delete saving_htab; - saving_htab = NULL; -+ callback_vec.release (); - } - - /* Read the state of the compiler back in from F. */ -@@ -639,6 +667,30 @@ gt_pch_restore (FILE *f) - ggc_pch_read (f, mmi.preferred_base); - - gt_pch_restore_stringpool (); -+ -+ void (*pch_save) (FILE *); -+ unsigned num_callbacks; -+ if (fread (&pch_save, sizeof (pch_save), 1, f) != 1 -+ || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1) -+ fatal_error (input_location, "cannot read PCH file: %m"); -+ if (pch_save != >_pch_save) -+ { -+ uintptr_t bias = (uintptr_t) >_pch_save - (uintptr_t) pch_save; -+ void **ptrs = XNEWVEC (void *, num_callbacks); -+ unsigned i; -+ -+ if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks) -+ fatal_error (input_location, "cannot read PCH file: %m"); -+ for (i = 0; i < num_callbacks; ++i) -+ { -+ memcpy (&pch_save, ptrs[i], sizeof (pch_save)); -+ pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + bias); -+ memcpy (ptrs[i], &pch_save, sizeof (pch_save)); -+ } -+ XDELETE (ptrs); -+ } -+ else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0) -+ fatal_error (input_location, "cannot read PCH file: %m"); - } - - /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present. -diff --git a/gcc/ggc.h b/gcc/ggc.h -index 5e921d957fd..c005f7e0412 100644 ---- a/gcc/ggc.h -+++ b/gcc/ggc.h -@@ -46,6 +46,10 @@ typedef void (*gt_handle_reorder) (void *, void *, gt_pointer_operator, - /* Used by the gt_pch_n_* routines. Register an object in the hash table. */ - extern int gt_pch_note_object (void *, void *, gt_note_pointers); - -+/* Used by the gt_pch_p_* routines. Register address of a callback -+ pointer. */ -+extern void gt_pch_note_callback (void *, void *); -+ - /* Used by the gt_pch_n_* routines. Register that an object has a reorder - function. */ - extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder); -diff --git a/gcc/output.h b/gcc/output.h -index 8f6f15308f4..4a23795bf7e 100644 ---- a/gcc/output.h -+++ b/gcc/output.h -@@ -456,7 +456,7 @@ struct GTY(()) named_section { - - /* A callback that writes the assembly code for switching to an unnamed - section. The argument provides callback-specific data. */ --typedef void (*unnamed_section_callback) (const void *); -+typedef void (*unnamed_section_callback) (const char *); - - /* Information about a SECTION_UNNAMED section. */ - struct GTY(()) unnamed_section { -@@ -464,8 +464,8 @@ struct GTY(()) unnamed_section { - - /* The callback used to switch to the section, and the data that - should be passed to the callback. */ -- unnamed_section_callback GTY ((skip)) callback; -- const void *GTY ((skip)) data; -+ unnamed_section_callback GTY ((callback)) callback; -+ const char *data; - - /* The next entry in the chain of unnamed sections. */ - section *next; -@@ -489,7 +489,7 @@ struct GTY(()) noswitch_section { - struct section_common common; - - /* The callback used to assemble decls in this section. */ -- noswitch_section_callback GTY ((skip)) callback; -+ noswitch_section_callback GTY ((callback)) callback; - }; - - /* Information about a section, which may be named or unnamed. */ -@@ -524,8 +524,8 @@ extern GTY(()) section *bss_noswitch_sec - extern GTY(()) section *in_section; - extern GTY(()) bool in_cold_section_p; - --extern section *get_unnamed_section (unsigned int, void (*) (const void *), -- const void *); -+extern section *get_unnamed_section (unsigned int, void (*) (const char *), -+ const char *); - extern section *get_section (const char *, unsigned int, tree); - extern section *get_named_section (tree, const char *, int); - extern section *get_variable_section (tree, bool); -@@ -546,7 +546,7 @@ extern section *get_cdtor_priority_secti - - extern bool unlikely_text_section_p (section *); - extern void switch_to_section (section *); --extern void output_section_asm_op (const void *); -+extern void output_section_asm_op (const char *); - - extern void record_tm_clone_pair (tree, tree); - extern void finish_tm_clone_pairs (void); -diff --git a/gcc/tree-core.h b/gcc/tree-core.h -index 8ab119dc9a2..91ae5237d7e 100644 ---- a/gcc/tree-core.h -+++ b/gcc/tree-core.h -@@ -1961,7 +1961,7 @@ struct GTY(()) tree_function_decl { - struct GTY(()) tree_translation_unit_decl { - struct tree_decl_common common; - /* Source language of this translation unit. Used for DWARF output. */ -- const char * GTY((skip(""))) language; -+ const char *language; - /* TODO: Non-optimization used to build this translation unit. */ - /* TODO: Root of a partial DWARF tree for global types and decls. */ - }; -diff --git a/gcc/varasm.c b/gcc/varasm.c -index 9315e2c6936..aff93ca5de9 100644 ---- a/gcc/varasm.c -+++ b/gcc/varasm.c -@@ -250,8 +250,8 @@ object_block_hasher::hash (object_block *old) - /* Return a new unnamed section with the given fields. */ - - section * --get_unnamed_section (unsigned int flags, void (*callback) (const void *), -- const void *data) -+get_unnamed_section (unsigned int flags, void (*callback) (const char *), -+ const char *data) - { - section *sect; - -@@ -7778,9 +7778,9 @@ file_end_indicate_split_stack (void) - a get_unnamed_section callback. */ - - void --output_section_asm_op (const void *directive) -+output_section_asm_op (const char *directive) - { -- fprintf (asm_out_file, "%s\n", (const char *) directive); -+ fprintf (asm_out_file, "%s\n", directive); - } - - /* Emit assembly code to switch to section NEW_SECTION. Do nothing if -diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h -index 8b5e2f82982..bc40e333579 100644 ---- a/libcpp/include/line-map.h -+++ b/libcpp/include/line-map.h -@@ -758,11 +758,11 @@ struct GTY(()) line_maps { - - /* If non-null, the allocator to use when resizing 'maps'. If null, - xrealloc is used. */ -- line_map_realloc reallocator; -+ line_map_realloc GTY((callback)) reallocator; - - /* The allocators' function used to know the actual size it - allocated, for a certain allocation size requested. */ -- line_map_round_alloc_size_func round_alloc_size; -+ line_map_round_alloc_size_func GTY((callback)) round_alloc_size; - - struct location_adhoc_data_map location_adhoc_data_map; - -diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c -index 6ba038881d6..1c2f7d564e7 100644 ---- a/gcc/config/avr/avr.c -+++ b/gcc/config/avr/avr.c -@@ -10089,7 +10089,7 @@ avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name, - to track need of __do_copy_data. */ - - static void --avr_output_data_section_asm_op (const void *data) -+avr_output_data_section_asm_op (const char *data) - { - avr_need_copy_data_p = true; - -@@ -10102,7 +10102,7 @@ avr_output_data_section_asm_op (const void *data) - to track need of __do_clear_bss. */ - - static void --avr_output_bss_section_asm_op (const void *data) -+avr_output_bss_section_asm_op (const char *data) - { - avr_need_clear_bss_p = true; - diff --git a/SOURCES/gcc8-pr100508.patch b/SOURCES/gcc8-pr100508.patch deleted file mode 100644 index 7504ae5..0000000 --- a/SOURCES/gcc8-pr100508.patch +++ /dev/null @@ -1,74 +0,0 @@ -commit ba374dfb937a8ac1c7c4740913331951a924f88b -Author: Jakub Jelinek -Date: Wed May 12 10:38:35 2021 +0200 - - expand: Don't reuse DEBUG_EXPRs with vector type if they have different modes [PR100508] - - The inliner doesn't remap DEBUG_EXPR_DECLs, so the same decls can appear - in multiple functions. - Furthermore, expansion reuses corresponding DEBUG_EXPRs too, so they again - can be reused in multiple functions. - Neither of that is a major problem, DEBUG_EXPRs are just magic value holders - and what value they stand for is independent in each function and driven by - what debug stmts or DEBUG_INSNs they are bound to. - Except for DEBUG_EXPR*s with vector types, TYPE_MODE can be either BLKmode - or some vector mode depending on whether current function's enabled ISAs - support that vector mode or not. On the following testcase, we expand it - first in foo function without AVX2 enabled and so the DEBUG_EXPR is - BLKmode, but later the same DEBUG_EXPR_DECL is used in a simd clone with - AVX2 enabled and expansion ICEs because of a mode mismatch. - - The following patch fixes that by forcing recreation of a DEBUG_EXPR if - there is a mode mismatch for vector typed DEBUG_EXPR_DECL, DEBUG_EXPRs - will be still reused in between functions otherwise and within the same - function the mode should be always the same. - - 2021-05-12 Jakub Jelinek - - PR middle-end/100508 - * cfgexpand.c (expand_debug_expr): For DEBUG_EXPR_DECL with vector - type, don't reuse DECL_RTL if it has different mode, instead force - creation of a new DEBUG_EXPR. - - * gcc.dg/gomp/pr100508.c: New test. - - (cherry picked from commit 19040050aa2c8ee890fc58dda48639fc91bf0af0) - -diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c -index b1535e15d28..a7d05202184 100644 ---- a/gcc/cfgexpand.c -+++ b/gcc/cfgexpand.c -@@ -4358,7 +4358,12 @@ expand_debug_expr (tree exp) - op0 = DECL_RTL_IF_SET (exp); - - if (op0) -- return op0; -+ { -+ if (GET_MODE (op0) != mode) -+ gcc_assert (VECTOR_TYPE_P (TREE_TYPE (exp))); -+ else -+ return op0; -+ } - - op0 = gen_rtx_DEBUG_EXPR (mode); - DEBUG_EXPR_TREE_DECL (op0) = exp; -diff --git a/gcc/testsuite/gcc.dg/gomp/pr100508.c b/gcc/testsuite/gcc.dg/gomp/pr100508.c -new file mode 100644 -index 00000000000..c3fa2fc258e ---- /dev/null -+++ b/gcc/testsuite/gcc.dg/gomp/pr100508.c -@@ -0,0 +1,14 @@ -+/* PR middle-end/100508 */ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -g -fopenmp-simd" } */ -+ -+typedef int __attribute__((__vector_size__(32))) V; -+V j; -+ -+#pragma omp declare simd -+int -+foo (void) -+{ -+ V m = j; -+ return 0; -+} diff --git a/SOURCES/gcc8-pr100797.patch b/SOURCES/gcc8-pr100797.patch deleted file mode 100644 index d84c64d..0000000 --- a/SOURCES/gcc8-pr100797.patch +++ /dev/null @@ -1,137 +0,0 @@ -commit ebfe8b28d40746ff33724bd5b9ade2552e619213 -Author: Jason Merrill -Date: Thu May 27 23:54:52 2021 -0400 - - c++: 'this' adjustment for devirtualized call - - My patch for 95719 made us do a better job of finding the actual virtual - function we want to call, but didn't update the 'this' pointer adjustment to - match. - - This backport also incorporates a bit of the r11-1638 reorganization. - - PR c++/100797 - PR c++/95719 - - gcc/cp/ChangeLog: - - * call.c (build_over_call): Adjust base_binfo in - resolves_to_fixed_type_p case. - - gcc/testsuite/ChangeLog: - - * g++.dg/inherit/virtual15.C: New test. - * g++.dg/inherit/virtual15a.C: New test. - ---- gcc/cp/call.c -+++ gcc/cp/call.c -@@ -8309,19 +8309,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) - || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)))) - flags |= LOOKUP_NONVIRTUAL; - -- /* If we know the dynamic type of the object, look up the final overrider -- in the BINFO. */ -- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 -- && resolves_to_fixed_type_p (arg)) -- { -- tree binfo = cand->conversion_path; -- if (BINFO_TYPE (binfo) != DECL_CONTEXT (fn)) -- binfo = lookup_base (binfo, DECL_CONTEXT (fn), ba_unique, -- NULL, complain); -- fn = lookup_vfn_in_binfo (DECL_VINDEX (fn), binfo); -- flags |= LOOKUP_NONVIRTUAL; -- } -- - /* [class.mfct.nonstatic]: If a nonstatic member function of a class - X is called for an object that is not of type X, or of a type - derived from X, the behavior is undefined. -@@ -8331,10 +8318,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) - gcc_assert (TYPE_PTR_P (parmtype)); - /* Convert to the base in which the function was declared. */ - gcc_assert (cand->conversion_path != NULL_TREE); -- converted_arg = build_base_path (PLUS_EXPR, -- arg, -- cand->conversion_path, -- 1, complain); - /* Check that the base class is accessible. */ - if (!accessible_base_p (TREE_TYPE (argtype), - BINFO_TYPE (cand->conversion_path), true)) -@@ -8349,10 +8332,33 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) - /* If fn was found by a using declaration, the conversion path - will be to the derived class, not the base declaring fn. We - must convert from derived to base. */ -- base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)), -+ base_binfo = lookup_base (cand->conversion_path, - TREE_TYPE (parmtype), ba_unique, - NULL, complain); -- converted_arg = build_base_path (PLUS_EXPR, converted_arg, -+ -+ /* If we know the dynamic type of the object, look up the final overrider -+ in the BINFO. */ -+ if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 -+ && resolves_to_fixed_type_p (arg)) -+ { -+ tree ov = lookup_vfn_in_binfo (DECL_VINDEX (fn), base_binfo); -+ -+ /* And unwind base_binfo to match. If we don't find the type we're -+ looking for in BINFO_INHERITANCE_CHAIN, we're looking at diamond -+ inheritance; for now do a normal virtual call in that case. */ -+ tree octx = DECL_CONTEXT (ov); -+ tree obinfo = base_binfo; -+ while (obinfo && !SAME_BINFO_TYPE_P (BINFO_TYPE (obinfo), octx)) -+ obinfo = BINFO_INHERITANCE_CHAIN (obinfo); -+ if (obinfo) -+ { -+ fn = ov; -+ base_binfo = obinfo; -+ flags |= LOOKUP_NONVIRTUAL; -+ } -+ } -+ -+ converted_arg = build_base_path (PLUS_EXPR, arg, - base_binfo, 1, complain); - - argarray[j++] = converted_arg; ---- /dev/null -+++ gcc/testsuite/g++.dg/inherit/virtual15.C -@@ -0,0 +1,18 @@ -+// PR c++/100797 -+// { dg-do run } -+ -+bool ok = false; -+struct S1 { virtual ~S1() {} }; -+struct S2 { virtual void f1() = 0; }; -+struct S3: S1, S2 { -+ void f1() { f2(); } -+ virtual void f2() = 0; -+}; -+struct S4: S3 { -+ void f2() { ok = true; } -+ using S2::f1; -+}; -+int main() { -+ S4().f1(); -+ if (!ok) __builtin_abort (); -+} ---- /dev/null -+++ gcc/testsuite/g++.dg/inherit/virtual15a.C -@@ -0,0 +1,19 @@ -+// PR c++/100797 plus diamond inheritance -+// { dg-do run } -+ -+bool ok = false; -+struct S1 { virtual ~S1() {} }; -+struct S2 { virtual void f1() = 0; }; -+struct S3: S1, virtual S2 { -+ void f1() { f2(); } -+ virtual void f2() = 0; -+}; -+struct SX: virtual S2 { }; -+struct S4: SX, S3 { -+ void f2() { ok = true; } -+ using S2::f1; -+}; -+int main() { -+ S4().f1(); -+ if (!ok) __builtin_abort (); -+} diff --git a/SOURCES/gcc8-pr105502.patch b/SOURCES/gcc8-pr105502.patch deleted file mode 100644 index 7200b9d..0000000 --- a/SOURCES/gcc8-pr105502.patch +++ /dev/null @@ -1,98 +0,0 @@ -From b005000525ab0a5116d21217c41fb1da5bd03796 Mon Sep 17 00:00:00 2001 -From: Jonathan Wakely -Date: Fri, 6 May 2022 21:19:17 +0100 -Subject: [PATCH] libstdc++: Fix deserialization for std::normal_distribution - [PR105502] - -This fixes a regression in std::normal_distribution deserialization that -caused the object to be left unchanged if the __state_avail value read -from the stream was false. - -libstdc++-v3/ChangeLog: - - PR libstdc++/105502 - * include/bits/random.tcc - (operator>>(basic_istream&, normal_distribution&)): - Update state when __state_avail is false. - * testsuite/26_numerics/random/normal_distribution/operators/serialize.cc: - Check that deserialized object equals serialized one. - -(cherry picked from commit 909ef4e2727ddc50a32d6ad379a1f1ccc1043c6a) ---- - libstdc++-v3/include/bits/random.tcc | 2 +- - .../operators/serialize.cc | 36 ++++++++++++++++++- - 2 files changed, 36 insertions(+), 2 deletions(-) - -diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc -index 0a299baedc5..0f758671f69 100644 ---- a/libstdc++-v3/include/bits/random.tcc -+++ b/libstdc++-v3/include/bits/random.tcc -@@ -1941,7 +1941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - bool __saved_avail; - if (__is >> __mean >> __stddev >> __saved_avail) - { -- if (__saved_avail && (__is >> __x._M_saved)) -+ if (!__saved_avail || (__is >> __x._M_saved)) - { - __x._M_saved_available = __saved_avail; - __x.param(typename normal_distribution<_RealType>:: -diff --git a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc -index a65d4004161..8cc70886bc7 100644 ---- a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc -+++ b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc -@@ -25,6 +25,7 @@ - - #include - #include -+#include - - void - test01() -@@ -37,10 +38,43 @@ test01() - str << u; - - str >> v; -+ VERIFY( u == v ); -+} -+ -+void -+test_pr105502() -+{ -+ // PR libstdc++/105502 std::normal_distribution deserialization issue -+ std::stringstream str; -+ std::normal_distribution<> d{1, 2}, d2; -+ std::minstd_rand0 g; -+ str << d; -+ VERIFY( str ); -+ str >> d2; -+ VERIFY( str ); -+ VERIFY( d == d2 ); -+ -+ (void) d(g); // sets d._M_saved_available = true -+ str.str(""); -+ str.clear(); -+ str << d; -+ VERIFY( str ); -+ str >> d2; -+ VERIFY( str ); -+ VERIFY( d == d2 ); -+ -+ (void) d(g); // sets d._M_saved_available = false -+ str.str(""); -+ str.clear(); -+ str << d; -+ VERIFY( str ); -+ str >> d2; -+ VERIFY( str ); -+ VERIFY( d == d2 ); - } - - int main() - { - test01(); -- return 0; -+ test_pr105502(); - } --- -2.31.1 - diff --git a/SOURCES/gcc8-pr111039.patch b/SOURCES/gcc8-pr111039.patch deleted file mode 100644 index 1dbd97c..0000000 --- a/SOURCES/gcc8-pr111039.patch +++ /dev/null @@ -1,61 +0,0 @@ -commit e150cbf591759af10f3d57acbe0eb381aafa00de -Author: Richard Biener -Date: Thu Aug 17 13:10:14 2023 +0200 - - tree-optimization/111039 - abnormals and bit test merging - - The following guards the bit test merging code in if-combine against - the appearance of SSA names used in abnormal PHIs. - - PR tree-optimization/111039 - * tree-ssa-ifcombine.cc (ifcombine_ifandif): Check for - SSA_NAME_OCCURS_IN_ABNORMAL_PHI. - - * gcc.dg/pr111039.c: New testcase. - - (cherry picked from commit 482551a79a3d3f107f6239679ee74655cfe8707e) - -diff --git a/gcc/testsuite/gcc.dg/pr111039.c b/gcc/testsuite/gcc.dg/pr111039.c -new file mode 100644 -index 00000000000..bec9983b35f ---- /dev/null -+++ b/gcc/testsuite/gcc.dg/pr111039.c -@@ -0,0 +1,15 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O" } */ -+ -+int _setjmp (); -+void abcd (); -+void abcde (); -+void compiler_corruption_function(int flags) -+{ -+ int nowait = flags & 1048576, isexpand = flags & 8388608; -+ abcd(); -+ _setjmp(flags); -+ if (nowait && isexpand) -+ flags &= 0; -+ abcde(); -+} ---- a/gcc/tree-ssa-ifcombine.c -+++ b/gcc/tree-ssa-ifcombine.c -@@ -407,6 +407,9 @@ ifcombine_ifandif (basic_block inner_con - { - tree t, t2; - -+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) -+ return false; -+ - /* Do it. */ - gsi = gsi_for_stmt (inner_cond); - t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1), -@@ -457,6 +460,10 @@ ifcombine_ifandif (basic_block inner_con - gimple_stmt_iterator gsi; - tree t; - -+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1) -+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)) -+ return false; -+ - /* Find the common name which is bit-tested. */ - if (name1 == name2) - ; diff --git a/SOURCES/gcc8-pr111070.patch b/SOURCES/gcc8-pr111070.patch deleted file mode 100644 index 37b2546..0000000 --- a/SOURCES/gcc8-pr111070.patch +++ /dev/null @@ -1,68 +0,0 @@ -commit ad42dcf501e41713047cf6c47cbb1dd9f01088a4 -Author: Richard Biener -Date: Mon Aug 21 09:01:00 2023 +0200 - - tree-optimization/111070 - fix ICE with recent ifcombine fix - - We now got test coverage for non-SSA name bits so the following amends - the SSA_NAME_OCCURS_IN_ABNORMAL_PHI checks. - - PR tree-optimization/111070 - * tree-ssa-ifcombine.cc (ifcombine_ifandif): Check we have - an SSA name before checking SSA_NAME_OCCURS_IN_ABNORMAL_PHI. - - * gcc.dg/pr111070.c: New testcase. - - (cherry picked from commit 966b0a96523fb7adbf498ac71df5e033c70dc546) - -diff --git a/gcc/testsuite/gcc.dg/pr111070.c b/gcc/testsuite/gcc.dg/pr111070.c -new file mode 100644 -index 00000000000..1ebc7adf782 ---- /dev/null -+++ b/gcc/testsuite/gcc.dg/pr111070.c -@@ -0,0 +1,20 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O" } */ -+ -+/* common */ -+char c; -+/* arrays must be 8 byte aligned, regardless of size */ -+char c_ary[1]; -+ -+/* data */ -+char d = 1; -+char d_ary[1] = {1}; -+ -+int main () -+{ -+ if (((unsigned long)&c_ary[0] & 7) != 0) -+ return 1; -+ if (((unsigned long)&d_ary[0] & 7) != 0) -+ return 1; -+ return 0; -+} ---- a/gcc/tree-ssa-ifcombine.c -+++ b/gcc/tree-ssa-ifcombine.c -@@ -436,7 +436,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, - { - tree t, t2; - -- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) -+ if (TREE_CODE (name1) == SSA_NAME -+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) - return false; - - /* Do it. */ -@@ -495,8 +496,10 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, - gimple_stmt_iterator gsi; - tree t; - -- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1) -- || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)) -+ if ((TREE_CODE (name1) == SSA_NAME -+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) -+ || (TREE_CODE (name2) == SSA_NAME -+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))) - return false; - - /* Find the common name which is bit-tested. */ diff --git a/SOURCES/gcc8-pr87723.patch b/SOURCES/gcc8-pr87723.patch deleted file mode 100644 index d0aafcf..0000000 --- a/SOURCES/gcc8-pr87723.patch +++ /dev/null @@ -1,71 +0,0 @@ -commit 8c21b0d164f33d9d47acc26f4f9b99b53e3b1945 -Author: Andreas Krebbel -Date: Tue Nov 6 10:22:05 2018 +0000 - - S/390: Fix PR87723 - - gcc/ChangeLog: - - 2018-11-06 Andreas Krebbel - - PR target/87723 - * config/s390/s390.md ("*rsbg_di_rotl"): Remove mode - attributes for operands 3 and 4. - - gcc/testsuite/ChangeLog: - - 2018-11-06 Andreas Krebbel - - PR target/87723 - * gcc.target/s390/pr87723.c: New test. - - From-SVN: r265832 - -diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md -index 8e7b285e1c3..4ffd438c07c 100644 ---- a/gcc/config/s390/s390.md -+++ b/gcc/config/s390/s390.md -@@ -4230,7 +4230,7 @@ (define_insn "*rsbg_di_rotl" - (match_operand:DI 4 "nonimmediate_operand" "0"))) - (clobber (reg:CC CC_REGNUM))] - "TARGET_Z10" -- "rsbg\t%0,%1,%2,%2,%b3" -+ "rsbg\t%0,%1,%s2,%e2,%b3" - [(set_attr "op_type" "RIE")]) - - ; rosbg, rxsbg -diff --git a/gcc/testsuite/gcc.target/s390/pr87723.c b/gcc/testsuite/gcc.target/s390/pr87723.c -new file mode 100644 -index 00000000000..b0e8a5a3118 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/s390/pr87723.c -@@ -0,0 +1,29 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O3 -march=z196 -m64 -mzarch" } */ -+ -+unsigned long a; -+int b; -+void c(char* i) { -+ for (;;) { -+ char g = 0; -+ for (; g < 24; ++g) -+ b = a << g | a >> 64 - g; -+ { -+ char *d = i; -+ long h = b; -+ char e = 0; -+ for (; e < 8; ++e) -+ d[e] = h; -+ } -+ char *d = i; -+ signed e; -+ unsigned long f = 0; -+ e = 7; -+ for (; e; --e) { -+ f <<= 8; -+ f |= d[e]; -+ } -+ for (; e < 8; ++e) -+ d[e] = f; -+ } -+} diff --git a/SOURCES/gcc8-pr96796.patch b/SOURCES/gcc8-pr96796.patch deleted file mode 100644 index 46d1d2c..0000000 --- a/SOURCES/gcc8-pr96796.patch +++ /dev/null @@ -1,254 +0,0 @@ -commit 6001db79c477b03eacc7e7049560921fb54b7845 -Author: Richard Sandiford -Date: Mon Sep 7 20:15:36 2020 +0100 - - lra: Avoid cycling on certain subreg reloads [PR96796] - - This PR is about LRA cycling for a reload of the form: - - ---------------------------------------------------------------------------- - Changing pseudo 196 in operand 1 of insn 103 on equiv [r105:DI*0x8+r140:DI] - Creating newreg=287, assigning class ALL_REGS to slow/invalid mem r287 - Creating newreg=288, assigning class ALL_REGS to slow/invalid mem r288 - 103: r203:SI=r288:SI<<0x1+r196:DI#0 - REG_DEAD r196:DI - Inserting slow/invalid mem reload before: - 316: r287:DI=[r105:DI*0x8+r140:DI] - 317: r288:SI=r287:DI#0 - ---------------------------------------------------------------------------- - - The problem is with r287. We rightly give it a broad starting class of - POINTER_AND_FP_REGS (reduced from ALL_REGS by preferred_reload_class). - However, we never make forward progress towards narrowing it down to - a specific choice of class (POINTER_REGS or FP_REGS). - - I think in practice we rely on two things to narrow a reload pseudo's - class down to a specific choice: - - (1) a restricted class is specified when the pseudo is created - - This happens for input address reloads, where the class is taken - from the target's chosen base register class. It also happens - for simple REG reloads, where the class is taken from the chosen - alternative's constraints. - - (2) uses of the reload pseudo as a direct input operand - - In this case get_reload_reg tries to reuse the existing register - and narrow its class, instead of creating a new reload pseudo. - - However, neither occurs here. As described above, r287 rightly - starts out with a wide choice of class, ultimately derived from - ALL_REGS, so we don't get (1). And as the comments in the PR - explain, r287 is never used as an input reload, only the subreg is, - so we don't get (2): - - ---------------------------------------------------------------------------- - Choosing alt 13 in insn 317: (0) r (1) w {*movsi_aarch64} - Creating newreg=291, assigning class FP_REGS to r291 - 317: r288:SI=r291:SI - Inserting insn reload before: - 320: r291:SI=r287:DI#0 - ---------------------------------------------------------------------------- - - IMO, in this case we should rely on the reload of r316 to narrow - down the class of r278. Currently we do: - - ---------------------------------------------------------------------------- - Choosing alt 7 in insn 316: (0) r (1) m {*movdi_aarch64} - Creating newreg=289 from oldreg=287, assigning class GENERAL_REGS to r289 - 316: r289:DI=[r105:DI*0x8+r140:DI] - Inserting insn reload after: - 318: r287:DI=r289:DI - --------------------------------------------------- - - i.e. we create a new pseudo register r289 and give *that* pseudo - GENERAL_REGS instead. This is because get_reload_reg only narrows - down the existing class for OP_IN and OP_INOUT, not OP_OUT. - - But if we have a reload pseudo in a reload instruction and have chosen - a specific class for the reload pseudo, I think we should simply install - it for OP_OUT reloads too, if the class is a subset of the existing class. - We will need to pick such a register whatever happens (for r289 in the - example above). And as explained in the PR, doing this actually avoids - an unnecessary move via the FP registers too. - - The patch is quite aggressive in that it does this for all reload - pseudos in all reload instructions. I wondered about reusing the - condition for a reload move in in_class_p: - - INSN_UID (curr_insn) >= new_insn_uid_start - && curr_insn_set != NULL - && ((OBJECT_P (SET_SRC (curr_insn_set)) - && ! CONSTANT_P (SET_SRC (curr_insn_set))) - || (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG - && OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set))) - && ! CONSTANT_P (SUBREG_REG (SET_SRC (curr_insn_set))))))) - - but I can't really justify that on first principles. I think we - should apply the rule consistently until we have a specific reason - for doing otherwise. - - gcc/ - PR rtl-optimization/96796 - * lra-constraints.c (in_class_p): Add a default-false - allow_all_reload_class_changes_p parameter. Do not treat - reload moves specially when the parameter is true. - (get_reload_reg): Try to narrow the class of an existing OP_OUT - reload if we're reloading a reload pseudo in a reload instruction. - - gcc/testsuite/ - PR rtl-optimization/96796 - * gcc.c-torture/compile/pr96796.c: New test. - -diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c -index 580da9c3ed6..161b721efb1 100644 ---- a/gcc/lra-constraints.c -+++ b/gcc/lra-constraints.c -@@ -236,12 +236,17 @@ get_reg_class (int regno) - CL. Use elimination first if REG is a hard register. If REG is a - reload pseudo created by this constraints pass, assume that it will - be allocated a hard register from its allocno class, but allow that -- class to be narrowed to CL if it is currently a superset of CL. -+ class to be narrowed to CL if it is currently a superset of CL and -+ if either: -+ -+ - ALLOW_ALL_RELOAD_CLASS_CHANGES_P is true or -+ - the instruction we're processing is not a reload move. - - If NEW_CLASS is nonnull, set *NEW_CLASS to the new allocno class of - REGNO (reg), or NO_REGS if no change in its class was needed. */ - static bool --in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class) -+in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class, -+ bool allow_all_reload_class_changes_p = false) - { - enum reg_class rclass, common_class; - machine_mode reg_mode; -@@ -266,7 +271,8 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class) - typically moves that have many alternatives, and restricting - reload pseudos for one alternative may lead to situations - where other reload pseudos are no longer allocatable. */ -- || (INSN_UID (curr_insn) >= new_insn_uid_start -+ || (!allow_all_reload_class_changes_p -+ && INSN_UID (curr_insn) >= new_insn_uid_start - && curr_insn_set != NULL - && ((OBJECT_P (SET_SRC (curr_insn_set)) - && ! CONSTANT_P (SET_SRC (curr_insn_set))) -@@ -551,13 +557,12 @@ init_curr_insn_input_reloads (void) - curr_insn_input_reloads_num = 0; - } - --/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse already -- created input reload pseudo (only if TYPE is not OP_OUT). Don't -- reuse pseudo if IN_SUBREG_P is true and the reused pseudo should be -- wrapped up in SUBREG. The result pseudo is returned through -- RESULT_REG. Return TRUE if we created a new pseudo, FALSE if we -- reused the already created input reload pseudo. Use TITLE to -- describe new registers for debug purposes. */ -+/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse an existing -+ reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P -+ is true and the reused pseudo should be wrapped up in a SUBREG. -+ The result pseudo is returned through RESULT_REG. Return TRUE if we -+ created a new pseudo, FALSE if we reused an existing reload pseudo. -+ Use TITLE to describe new registers for debug purposes. */ - static bool - get_reload_reg (enum op_type type, machine_mode mode, rtx original, - enum reg_class rclass, bool in_subreg_p, -@@ -616,6 +621,35 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original, - - if (type == OP_OUT) - { -+ /* Output reload registers tend to start out with a conservative -+ choice of register class. Usually this is ALL_REGS, although -+ a target might narrow it (for performance reasons) through -+ targetm.preferred_reload_class. It's therefore quite common -+ for a reload instruction to require a more restrictive class -+ than the class that was originally assigned to the reload register. -+ -+ In these situations, it's more efficient to refine the choice -+ of register class rather than create a second reload register. -+ This also helps to avoid cycling for registers that are only -+ used by reload instructions. */ -+ if (REG_P (original) -+ && (int) REGNO (original) >= new_regno_start -+ && INSN_UID (curr_insn) >= new_insn_uid_start -+ && in_class_p (original, rclass, &new_class, true)) -+ { -+ unsigned int regno = REGNO (original); -+ if (lra_dump_file != NULL) -+ { -+ fprintf (lra_dump_file, " Reuse r%d for output ", regno); -+ dump_value_slim (lra_dump_file, original, 1); -+ } -+ if (new_class != lra_get_allocno_class (regno)) -+ lra_change_class (regno, new_class, ", change to", false); -+ if (lra_dump_file != NULL) -+ fprintf (lra_dump_file, "\n"); -+ *result_reg = original; -+ return false; -+ } - *result_reg - = lra_create_new_reg_with_unique_value (mode, original, rclass, title); - return true; -diff --git a/gcc/testsuite/gcc.c-torture/compile/pr96796.c b/gcc/testsuite/gcc.c-torture/compile/pr96796.c -new file mode 100644 -index 00000000000..8808e62fe77 ---- /dev/null -+++ b/gcc/testsuite/gcc.c-torture/compile/pr96796.c -@@ -0,0 +1,55 @@ -+/* { dg-additional-options "-fcommon" } */ -+ -+struct S0 { -+ signed f0 : 8; -+ unsigned f1; -+ unsigned f4; -+}; -+struct S1 { -+ long f3; -+ char f4; -+} g_3_4; -+ -+int g_5, func_1_l_32, func_50___trans_tmp_31; -+static struct S0 g_144, g_834, g_1255, g_1261; -+ -+int g_273[120] = {}; -+int *g_555; -+char **g_979; -+static int g_1092_0; -+static int g_1193; -+int safe_mul_func_int16_t_s_s(int si1, int si2) { return si1 * si2; } -+static struct S0 *func_50(); -+int func_1() { func_50(g_3_4, g_5, func_1_l_32, 8, 3); } -+void safe_div_func_int64_t_s_s(int *); -+void safe_mod_func_uint32_t_u_u(struct S0); -+struct S0 *func_50(int p_51, struct S0 p_52, struct S1 p_53, int p_54, -+ int p_55) { -+ int __trans_tmp_30; -+ char __trans_tmp_22; -+ short __trans_tmp_19; -+ long l_985_1; -+ long l_1191[8]; -+ safe_div_func_int64_t_s_s(g_273); -+ __builtin_printf((char*)g_1261.f4); -+ safe_mod_func_uint32_t_u_u(g_834); -+ g_144.f0 += 1; -+ for (;;) { -+ struct S1 l_1350 = {&l_1350}; -+ for (; p_53.f3; p_53.f3 -= 1) -+ for (; g_1193 <= 2; g_1193 += 1) { -+ __trans_tmp_19 = safe_mul_func_int16_t_s_s(l_1191[l_985_1 + p_53.f3], -+ p_55 % (**g_979 = 10)); -+ __trans_tmp_22 = g_1255.f1 * p_53.f4; -+ __trans_tmp_30 = __trans_tmp_19 + __trans_tmp_22; -+ if (__trans_tmp_30) -+ g_1261.f0 = p_51; -+ else { -+ g_1255.f0 = p_53.f3; -+ int *l_1422 = g_834.f0 = g_144.f4 != (*l_1422)++ > 0 < 0 ^ 51; -+ g_555 = ~0; -+ g_1092_0 |= func_50___trans_tmp_31; -+ } -+ } -+ } -+} diff --git a/SOURCES/gcc8-pr99074.patch b/SOURCES/gcc8-pr99074.patch deleted file mode 100644 index 83e9285..0000000 --- a/SOURCES/gcc8-pr99074.patch +++ /dev/null @@ -1,77 +0,0 @@ -commit 6d134ca4b963706f31251f061fc180e517b32546 -Author: Martin Sebor -Date: Tue Feb 23 14:09:00 2021 -0700 - - PR c++/99074 - crash in dynamic_cast<>() on null pointer - - libstdc++-v3/ChangeLog: - - PR c++/99074 - * libsupc++/dyncast.cc (__dynamic_cast): Return null when - first argument is null. - - gcc/testsuite/ChangeLog: - - PR c++/99074 - * g++.dg/warn/Wnonnull11.C: New test. - -diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull11.C b/gcc/testsuite/g++.dg/warn/Wnonnull11.C -new file mode 100644 -index 00000000000..5f1b69d9a41 ---- /dev/null -+++ b/gcc/testsuite/g++.dg/warn/Wnonnull11.C -@@ -0,0 +1,40 @@ -+/* PR c++/99074 - gcc 8 and above is crashing with dynamic_cast<>() on null -+ pointer with optimization level -O1 and above -+ { dg-do run } -+ { dg-options "-O1 -Wall" } */ -+ -+class Base -+{ -+public: -+ virtual ~Base() {} -+ virtual void op() = 0; -+}; -+ -+class Object: public virtual Base { }; -+ -+class AbstractBase: public virtual Base -+{ -+public: -+ Object* _to_object () -+ { -+ return dynamic_cast(this); // { dg-warning "\\\[-Wnonnull" "" { xfail *-*-* } } -+ } -+}; -+ -+class MyAbstractClass: public virtual AbstractBase -+{ -+public: -+ static MyAbstractClass* _nil () { return 0; } -+}; -+ -+ -+int main () -+{ -+ MyAbstractClass *my_abs_type = MyAbstractClass::_nil (); -+ AbstractBase *abs_base = my_abs_type; -+ Object *obj = abs_base->_to_object (); -+ -+ __builtin_printf ("object is: %p\n", obj); -+ -+ return 0; -+} -diff --git a/libstdc++-v3/libsupc++/dyncast.cc b/libstdc++-v3/libsupc++/dyncast.cc -index b7d98495ad3..f8f707ee4d4 100644 ---- a/libstdc++-v3/libsupc++/dyncast.cc -+++ b/libstdc++-v3/libsupc++/dyncast.cc -@@ -47,6 +47,9 @@ __dynamic_cast (const void *src_ptr, // object started from - const __class_type_info *dst_type, // desired target type - ptrdiff_t src2dst) // how src and dst are related - { -+ if (!src_ptr) -+ /* Handle precondition violations gracefully. */ -+ return NULL; - const void *vtable = *static_cast (src_ptr); - const vtable_prefix *prefix = - adjust_pointer (vtable, diff --git a/SOURCES/gcc8-pr99536.patch b/SOURCES/gcc8-pr99536.patch deleted file mode 100644 index db6706e..0000000 --- a/SOURCES/gcc8-pr99536.patch +++ /dev/null @@ -1,47 +0,0 @@ -commit 29dad307b5d7cfdb6626c11c8e43ebff941c950b -Author: Jonathan Wakely -Date: Thu Mar 11 16:43:51 2021 +0000 - - libstdc++: Initialize std::normal_distribution::_M_saved [PR 99536] - - This avoids a false positive -Wmaybe-uninitialized warning, by - initializing _M_saved on construction. - - libstdc++-v3/ChangeLog: - - PR libstdc++/99536 - * include/bits/random.h (normal_distribution): Use - default-initializer for _M_saved and _M_saved_available. - - (cherry picked from commit 67e397660611990efd98f9e4106c1ee81f6803a4) - -diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h -index b36781ed290..3385345d273 100644 ---- a/libstdc++-v3/include/bits/random.h -+++ b/libstdc++-v3/include/bits/random.h -@@ -1974,12 +1974,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - explicit - normal_distribution(result_type __mean = result_type(0), - result_type __stddev = result_type(1)) -- : _M_param(__mean, __stddev), _M_saved_available(false) -+ : _M_param(__mean, __stddev) - { } - - explicit - normal_distribution(const param_type& __p) -- : _M_param(__p), _M_saved_available(false) -+ : _M_param(__p) - { } - - /** -@@ -2158,8 +2158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - const param_type& __p); - - param_type _M_param; -- result_type _M_saved; -- bool _M_saved_available; -+ result_type _M_saved = 0; -+ bool _M_saved_available = false; - }; - - /** diff --git a/SOURCES/gcc8-remove-old-demangle.patch b/SOURCES/gcc8-remove-old-demangle.patch deleted file mode 100644 index 1abb8ed..0000000 --- a/SOURCES/gcc8-remove-old-demangle.patch +++ /dev/null @@ -1,8227 +0,0 @@ -commit 6c8120c5ff130e03d32ff15a8f0d0e703592a2af -Author: Jason Merrill -Date: Sat Dec 22 19:06:34 2018 -0500 - - Remove support for demangling GCC 2.x era mangling schemes. - - libiberty/ - * cplus-dem.c: Remove cplus_mangle_opname, cplus_demangle_opname, - internal_cplus_demangle, and all subroutines. - (libiberty_demanglers): Remove entries for ancient GNU (pre-3.0), - Lucid, ARM, HP, and EDG demangling styles. - (cplus_demangle): Remove 'work' variable. Don't call - internal_cplus_demangle. - include/ - * demangle.h: Remove support for ancient GNU (pre-3.0), Lucid, - ARM, HP, and EDG demangling styles. - - From-SVN: r267363 - ---- include/demangle.h -+++ include/demangle.h -@@ -53,20 +53,13 @@ extern "C" { - */ - - #define DMGL_AUTO (1 << 8) --#define DMGL_GNU (1 << 9) --#define DMGL_LUCID (1 << 10) --#define DMGL_ARM (1 << 11) --#define DMGL_HP (1 << 12) /* For the HP aCC compiler; -- same as ARM except for -- template arguments, etc. */ --#define DMGL_EDG (1 << 13) - #define DMGL_GNU_V3 (1 << 14) - #define DMGL_GNAT (1 << 15) - #define DMGL_DLANG (1 << 16) - #define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */ - - /* If none of these are set, use 'current_demangling_style' as the default. */ --#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST) -+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST) - - /* Enumeration of possible demangling styles. - -@@ -92,11 +85,6 @@ extern enum demangling_styles - no_demangling = -1, - unknown_demangling = 0, - auto_demangling = DMGL_AUTO, -- gnu_demangling = DMGL_GNU, -- lucid_demangling = DMGL_LUCID, -- arm_demangling = DMGL_ARM, -- hp_demangling = DMGL_HP, -- edg_demangling = DMGL_EDG, - gnu_v3_demangling = DMGL_GNU_V3, - java_demangling = DMGL_JAVA, - gnat_demangling = DMGL_GNAT, -@@ -108,11 +96,6 @@ extern enum demangling_styles - - #define NO_DEMANGLING_STYLE_STRING "none" - #define AUTO_DEMANGLING_STYLE_STRING "auto" --#define GNU_DEMANGLING_STYLE_STRING "gnu" --#define LUCID_DEMANGLING_STYLE_STRING "lucid" --#define ARM_DEMANGLING_STYLE_STRING "arm" --#define HP_DEMANGLING_STYLE_STRING "hp" --#define EDG_DEMANGLING_STYLE_STRING "edg" - #define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" - #define JAVA_DEMANGLING_STYLE_STRING "java" - #define GNAT_DEMANGLING_STYLE_STRING "gnat" -@@ -123,11 +106,6 @@ extern enum demangling_styles - - #define CURRENT_DEMANGLING_STYLE current_demangling_style - #define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) --#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) --#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) --#define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) --#define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) --#define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) - #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) - #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) - #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) -@@ -147,17 +125,8 @@ extern const struct demangler_engine - extern char * - cplus_demangle (const char *mangled, int options); - --extern int --cplus_demangle_opname (const char *opname, char *result, int options); -- --extern const char * --cplus_mangle_opname (const char *opname, int options); -- - /* Note: This sets global state. FIXME if you care about multi-threading. */ - --extern void --set_cplus_marker_for_demangling (int ch); -- - extern enum demangling_styles - cplus_demangle_set_style (enum demangling_styles style); - ---- libiberty/cplus-dem.c -+++ libiberty/cplus-dem.c -@@ -29,12 +29,6 @@ License along with libiberty; see the file COPYING.LIB. If - not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, - Boston, MA 02110-1301, USA. */ - --/* This file exports two functions; cplus_mangle_opname and cplus_demangle. -- -- This file imports xmalloc and xrealloc, which are like malloc and -- realloc except that they generate a fatal error if there is no -- available memory. */ -- - /* This file lives in both GCC and libiberty. When making changes, please - try not to break either. */ - -@@ -44,9 +38,7 @@ Boston, MA 02110-1301, USA. */ - - #include "safe-ctype.h" - --#include - #include --#include - - #ifdef HAVE_STDLIB_H - #include -@@ -55,204 +47,14 @@ void * malloc (); - void * realloc (); - #endif - --#ifdef HAVE_LIMITS_H --#include --#endif --#ifndef INT_MAX --# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ --#endif -- - #include - #undef CURRENT_DEMANGLING_STYLE --#define CURRENT_DEMANGLING_STYLE work->options -+#define CURRENT_DEMANGLING_STYLE options - - #include "libiberty.h" - --#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) -- --/* A value at least one greater than the maximum number of characters -- that will be output when using the `%d' format with `printf'. */ --#define INTBUF_SIZE 32 -- --extern void fancy_abort (void) ATTRIBUTE_NORETURN; -- --/* In order to allow a single demangler executable to demangle strings -- using various common values of CPLUS_MARKER, as well as any specific -- one set at compile time, we maintain a string containing all the -- commonly used ones, and check to see if the marker we are looking for -- is in that string. CPLUS_MARKER is usually '$' on systems where the -- assembler can deal with that. Where the assembler can't, it's usually -- '.' (but on many systems '.' is used for other things). We put the -- current defined CPLUS_MARKER first (which defaults to '$'), followed -- by the next most common value, followed by an explicit '$' in case -- the value of CPLUS_MARKER is not '$'. -- -- We could avoid this if we could just get g++ to tell us what the actual -- cplus marker character is as part of the debug information, perhaps by -- ensuring that it is the character that terminates the gcc_compiled -- marker symbol (FIXME). */ -- --#if !defined (CPLUS_MARKER) --#define CPLUS_MARKER '$' --#endif -- - enum demangling_styles current_demangling_style = auto_demangling; - --static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; -- --static char char_str[2] = { '\000', '\000' }; -- --void --set_cplus_marker_for_demangling (int ch) --{ -- cplus_markers[0] = ch; --} -- --typedef struct string /* Beware: these aren't required to be */ --{ /* '\0' terminated. */ -- char *b; /* pointer to start of string */ -- char *p; /* pointer after last character */ -- char *e; /* pointer after end of allocated space */ --} string; -- --/* Stuff that is shared between sub-routines. -- Using a shared structure allows cplus_demangle to be reentrant. */ -- --struct work_stuff --{ -- int options; -- char **typevec; -- char **ktypevec; -- char **btypevec; -- int numk; -- int numb; -- int ksize; -- int bsize; -- int ntypes; -- int typevec_size; -- int constructor; -- int destructor; -- int static_type; /* A static member function */ -- int temp_start; /* index in demangled to start of template args */ -- int type_quals; /* The type qualifiers. */ -- int dllimported; /* Symbol imported from a PE DLL */ -- char **tmpl_argvec; /* Template function arguments. */ -- int ntmpl_args; /* The number of template function arguments. */ -- int forgetting_types; /* Nonzero if we are not remembering the types -- we see. */ -- string* previous_argument; /* The last function argument demangled. */ -- int nrepeats; /* The number of times to repeat the previous -- argument. */ -- int *proctypevec; /* Indices of currently processed remembered typevecs. */ -- int proctypevec_size; -- int nproctypes; --}; -- --#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) --#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) -- --static const struct optable --{ -- const char *const in; -- const char *const out; -- const int flags; --} optable[] = { -- {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ -- {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ -- {"new", " new", 0}, /* old (1.91, and 1.x) */ -- {"delete", " delete", 0}, /* old (1.91, and 1.x) */ -- {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ -- {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ -- {"as", "=", DMGL_ANSI}, /* ansi */ -- {"ne", "!=", DMGL_ANSI}, /* old, ansi */ -- {"eq", "==", DMGL_ANSI}, /* old, ansi */ -- {"ge", ">=", DMGL_ANSI}, /* old, ansi */ -- {"gt", ">", DMGL_ANSI}, /* old, ansi */ -- {"le", "<=", DMGL_ANSI}, /* old, ansi */ -- {"lt", "<", DMGL_ANSI}, /* old, ansi */ -- {"plus", "+", 0}, /* old */ -- {"pl", "+", DMGL_ANSI}, /* ansi */ -- {"apl", "+=", DMGL_ANSI}, /* ansi */ -- {"minus", "-", 0}, /* old */ -- {"mi", "-", DMGL_ANSI}, /* ansi */ -- {"ami", "-=", DMGL_ANSI}, /* ansi */ -- {"mult", "*", 0}, /* old */ -- {"ml", "*", DMGL_ANSI}, /* ansi */ -- {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ -- {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ -- {"convert", "+", 0}, /* old (unary +) */ -- {"negate", "-", 0}, /* old (unary -) */ -- {"trunc_mod", "%", 0}, /* old */ -- {"md", "%", DMGL_ANSI}, /* ansi */ -- {"amd", "%=", DMGL_ANSI}, /* ansi */ -- {"trunc_div", "/", 0}, /* old */ -- {"dv", "/", DMGL_ANSI}, /* ansi */ -- {"adv", "/=", DMGL_ANSI}, /* ansi */ -- {"truth_andif", "&&", 0}, /* old */ -- {"aa", "&&", DMGL_ANSI}, /* ansi */ -- {"truth_orif", "||", 0}, /* old */ -- {"oo", "||", DMGL_ANSI}, /* ansi */ -- {"truth_not", "!", 0}, /* old */ -- {"nt", "!", DMGL_ANSI}, /* ansi */ -- {"postincrement","++", 0}, /* old */ -- {"pp", "++", DMGL_ANSI}, /* ansi */ -- {"postdecrement","--", 0}, /* old */ -- {"mm", "--", DMGL_ANSI}, /* ansi */ -- {"bit_ior", "|", 0}, /* old */ -- {"or", "|", DMGL_ANSI}, /* ansi */ -- {"aor", "|=", DMGL_ANSI}, /* ansi */ -- {"bit_xor", "^", 0}, /* old */ -- {"er", "^", DMGL_ANSI}, /* ansi */ -- {"aer", "^=", DMGL_ANSI}, /* ansi */ -- {"bit_and", "&", 0}, /* old */ -- {"ad", "&", DMGL_ANSI}, /* ansi */ -- {"aad", "&=", DMGL_ANSI}, /* ansi */ -- {"bit_not", "~", 0}, /* old */ -- {"co", "~", DMGL_ANSI}, /* ansi */ -- {"call", "()", 0}, /* old */ -- {"cl", "()", DMGL_ANSI}, /* ansi */ -- {"alshift", "<<", 0}, /* old */ -- {"ls", "<<", DMGL_ANSI}, /* ansi */ -- {"als", "<<=", DMGL_ANSI}, /* ansi */ -- {"arshift", ">>", 0}, /* old */ -- {"rs", ">>", DMGL_ANSI}, /* ansi */ -- {"ars", ">>=", DMGL_ANSI}, /* ansi */ -- {"component", "->", 0}, /* old */ -- {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ -- {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ -- {"indirect", "*", 0}, /* old */ -- {"method_call", "->()", 0}, /* old */ -- {"addr", "&", 0}, /* old (unary &) */ -- {"array", "[]", 0}, /* old */ -- {"vc", "[]", DMGL_ANSI}, /* ansi */ -- {"compound", ", ", 0}, /* old */ -- {"cm", ", ", DMGL_ANSI}, /* ansi */ -- {"cond", "?:", 0}, /* old */ -- {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ -- {"max", ">?", 0}, /* old */ -- {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ -- {"min", "*", DMGL_ANSI}, /* ansi */ -- {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ --}; -- --/* These values are used to indicate the various type varieties. -- They are all non-zero so that they can be used as `success' -- values. */ --typedef enum type_kind_t --{ -- tk_none, -- tk_pointer, -- tk_reference, -- tk_rvalue_reference, -- tk_integral, -- tk_bool, -- tk_char, -- tk_real --} type_kind_t; -- - const struct demangler_engine libiberty_demanglers[] = - { - { -@@ -268,39 +70,9 @@ const struct demangler_engine libiberty_ - } - , - { -- GNU_DEMANGLING_STYLE_STRING, -- gnu_demangling, -- "GNU (g++) style demangling" -- } -- , -- { -- LUCID_DEMANGLING_STYLE_STRING, -- lucid_demangling, -- "Lucid (lcc) style demangling" -- } -- , -- { -- ARM_DEMANGLING_STYLE_STRING, -- arm_demangling, -- "ARM style demangling" -- } -- , -- { -- HP_DEMANGLING_STYLE_STRING, -- hp_demangling, -- "HP (aCC) style demangling" -- } -- , -- { -- EDG_DEMANGLING_STYLE_STRING, -- edg_demangling, -- "EDG style demangling" -- } -- , -- { - GNU_V3_DEMANGLING_STYLE_STRING, - gnu_v3_demangling, -- "GNU (g++) V3 ABI-style demangling" -+ "GNU (g++) V3 (Itanium C++ ABI) style demangling" - } - , - { -@@ -332,474 +104,6 @@ const struct demangler_engine libiberty_ - } - }; - --#define STRING_EMPTY(str) ((str) -> b == (str) -> p) --#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ -- string_append(str, " ");} --#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) -- --/* The scope separator appropriate for the language being demangled. */ -- --#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::") -- --#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ --#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ -- --/* Prototypes for local functions */ -- --static void delete_work_stuff (struct work_stuff *); -- --static void delete_non_B_K_work_stuff (struct work_stuff *); -- --static char *mop_up (struct work_stuff *, string *, int); -- --static void squangle_mop_up (struct work_stuff *); -- --static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *); -- --#if 0 --static int --demangle_method_args (struct work_stuff *, const char **, string *); --#endif -- --static char * --internal_cplus_demangle (struct work_stuff *, const char *); -- --static int --demangle_template_template_parm (struct work_stuff *work, -- const char **, string *); -- --static int --demangle_template (struct work_stuff *work, const char **, string *, -- string *, int, int); -- --static int --arm_pt (struct work_stuff *, const char *, int, const char **, -- const char **); -- --static int --demangle_class_name (struct work_stuff *, const char **, string *); -- --static int --demangle_qualified (struct work_stuff *, const char **, string *, -- int, int); -- --static int demangle_class (struct work_stuff *, const char **, string *); -- --static int demangle_fund_type (struct work_stuff *, const char **, string *); -- --static int demangle_signature (struct work_stuff *, const char **, string *); -- --static int demangle_prefix (struct work_stuff *, const char **, string *); -- --static int gnu_special (struct work_stuff *, const char **, string *); -- --static int arm_special (const char **, string *); -- --static void string_need (string *, int); -- --static void string_delete (string *); -- --static void --string_init (string *); -- --static void string_clear (string *); -- --#if 0 --static int string_empty (string *); --#endif -- --static void string_append (string *, const char *); -- --static void string_appends (string *, string *); -- --static void string_appendn (string *, const char *, int); -- --static void string_prepend (string *, const char *); -- --static void string_prependn (string *, const char *, int); -- --static void string_append_template_idx (string *, int); -- --static int get_count (const char **, int *); -- --static int consume_count (const char **); -- --static int consume_count_with_underscores (const char**); -- --static int demangle_args (struct work_stuff *, const char **, string *); -- --static int demangle_nested_args (struct work_stuff*, const char**, string*); -- --static int do_type (struct work_stuff *, const char **, string *); -- --static int do_arg (struct work_stuff *, const char **, string *); -- --static int --demangle_function_name (struct work_stuff *, const char **, string *, -- const char *); -- --static int --iterate_demangle_function (struct work_stuff *, -- const char **, string *, const char *); -- --static void remember_type (struct work_stuff *, const char *, int); -- --static void push_processed_type (struct work_stuff *, int); -- --static void pop_processed_type (struct work_stuff *); -- --static void remember_Btype (struct work_stuff *, const char *, int, int); -- --static int register_Btype (struct work_stuff *); -- --static void remember_Ktype (struct work_stuff *, const char *, int); -- --static void forget_types (struct work_stuff *); -- --static void forget_B_and_K_types (struct work_stuff *); -- --static void string_prepends (string *, string *); -- --static int --demangle_template_value_parm (struct work_stuff*, const char**, -- string*, type_kind_t); -- --static int --do_hpacc_template_const_value (struct work_stuff *, const char **, string *); -- --static int --do_hpacc_template_literal (struct work_stuff *, const char **, string *); -- --static int snarf_numeric_literal (const char **, string *); -- --/* There is a TYPE_QUAL value for each type qualifier. They can be -- combined by bitwise-or to form the complete set of qualifiers for a -- type. */ -- --#define TYPE_UNQUALIFIED 0x0 --#define TYPE_QUAL_CONST 0x1 --#define TYPE_QUAL_VOLATILE 0x2 --#define TYPE_QUAL_RESTRICT 0x4 -- --static int code_for_qualifier (int); -- --static const char* qualifier_string (int); -- --static const char* demangle_qualifier (int); -- --static int demangle_expression (struct work_stuff *, const char **, string *, -- type_kind_t); -- --static int --demangle_integral_value (struct work_stuff *, const char **, string *); -- --static int --demangle_real_value (struct work_stuff *, const char **, string *); -- --static void --demangle_arm_hp_template (struct work_stuff *, const char **, int, string *); -- --static void --recursively_demangle (struct work_stuff *, const char **, string *, int); -- --/* Translate count to integer, consuming tokens in the process. -- Conversion terminates on the first non-digit character. -- -- Trying to consume something that isn't a count results in no -- consumption of input and a return of -1. -- -- Overflow consumes the rest of the digits, and returns -1. */ -- --static int --consume_count (const char **type) --{ -- int count = 0; -- -- if (! ISDIGIT ((unsigned char)**type)) -- return -1; -- -- while (ISDIGIT ((unsigned char)**type)) -- { -- const int digit = **type - '0'; -- /* Check for overflow. */ -- if (count > ((INT_MAX - digit) / 10)) -- { -- while (ISDIGIT ((unsigned char) **type)) -- (*type)++; -- return -1; -- } -- -- count *= 10; -- count += digit; -- (*type)++; -- } -- -- if (count < 0) -- count = -1; -- -- return (count); --} -- -- --/* Like consume_count, but for counts that are preceded and followed -- by '_' if they are greater than 10. Also, -1 is returned for -- failure, since 0 can be a valid value. */ -- --static int --consume_count_with_underscores (const char **mangled) --{ -- int idx; -- -- if (**mangled == '_') -- { -- (*mangled)++; -- if (!ISDIGIT ((unsigned char)**mangled)) -- return -1; -- -- idx = consume_count (mangled); -- if (**mangled != '_') -- /* The trailing underscore was missing. */ -- return -1; -- -- (*mangled)++; -- } -- else -- { -- if (**mangled < '0' || **mangled > '9') -- return -1; -- -- idx = **mangled - '0'; -- (*mangled)++; -- } -- -- return idx; --} -- --/* C is the code for a type-qualifier. Return the TYPE_QUAL -- corresponding to this qualifier. */ -- --static int --code_for_qualifier (int c) --{ -- switch (c) -- { -- case 'C': -- return TYPE_QUAL_CONST; -- -- case 'V': -- return TYPE_QUAL_VOLATILE; -- -- case 'u': -- return TYPE_QUAL_RESTRICT; -- -- default: -- break; -- } -- -- /* C was an invalid qualifier. */ -- abort (); --} -- --/* Return the string corresponding to the qualifiers given by -- TYPE_QUALS. */ -- --static const char* --qualifier_string (int type_quals) --{ -- switch (type_quals) -- { -- case TYPE_UNQUALIFIED: -- return ""; -- -- case TYPE_QUAL_CONST: -- return "const"; -- -- case TYPE_QUAL_VOLATILE: -- return "volatile"; -- -- case TYPE_QUAL_RESTRICT: -- return "__restrict"; -- -- case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: -- return "const volatile"; -- -- case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: -- return "const __restrict"; -- -- case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: -- return "volatile __restrict"; -- -- case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: -- return "const volatile __restrict"; -- -- default: -- break; -- } -- -- /* TYPE_QUALS was an invalid qualifier set. */ -- abort (); --} -- --/* C is the code for a type-qualifier. Return the string -- corresponding to this qualifier. This function should only be -- called with a valid qualifier code. */ -- --static const char* --demangle_qualifier (int c) --{ -- return qualifier_string (code_for_qualifier (c)); --} -- --int --cplus_demangle_opname (const char *opname, char *result, int options) --{ -- int len, len1, ret; -- string type; -- struct work_stuff work[1]; -- const char *tem; -- -- len = strlen(opname); -- result[0] = '\0'; -- ret = 0; -- memset ((char *) work, 0, sizeof (work)); -- work->options = options; -- -- if (opname[0] == '_' && opname[1] == '_' -- && opname[2] == 'o' && opname[3] == 'p') -- { -- /* ANSI. */ -- /* type conversion operator. */ -- tem = opname + 4; -- if (do_type (work, &tem, &type)) -- { -- strcat (result, "operator "); -- strncat (result, type.b, type.p - type.b); -- string_delete (&type); -- ret = 1; -- } -- } -- else if (opname[0] == '_' && opname[1] == '_' -- && ISLOWER((unsigned char)opname[2]) -- && ISLOWER((unsigned char)opname[3])) -- { -- if (opname[4] == '\0') -- { -- /* Operator. */ -- size_t i; -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- if (strlen (optable[i].in) == 2 -- && memcmp (optable[i].in, opname + 2, 2) == 0) -- { -- strcat (result, "operator"); -- strcat (result, optable[i].out); -- ret = 1; -- break; -- } -- } -- } -- else -- { -- if (opname[2] == 'a' && opname[5] == '\0') -- { -- /* Assignment. */ -- size_t i; -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- if (strlen (optable[i].in) == 3 -- && memcmp (optable[i].in, opname + 2, 3) == 0) -- { -- strcat (result, "operator"); -- strcat (result, optable[i].out); -- ret = 1; -- break; -- } -- } -- } -- } -- } -- else if (len >= 3 -- && opname[0] == 'o' -- && opname[1] == 'p' -- && strchr (cplus_markers, opname[2]) != NULL) -- { -- /* see if it's an assignment expression */ -- if (len >= 10 /* op$assign_ */ -- && memcmp (opname + 3, "assign_", 7) == 0) -- { -- size_t i; -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- len1 = len - 10; -- if ((int) strlen (optable[i].in) == len1 -- && memcmp (optable[i].in, opname + 10, len1) == 0) -- { -- strcat (result, "operator"); -- strcat (result, optable[i].out); -- strcat (result, "="); -- ret = 1; -- break; -- } -- } -- } -- else -- { -- size_t i; -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- len1 = len - 3; -- if ((int) strlen (optable[i].in) == len1 -- && memcmp (optable[i].in, opname + 3, len1) == 0) -- { -- strcat (result, "operator"); -- strcat (result, optable[i].out); -- ret = 1; -- break; -- } -- } -- } -- } -- else if (len >= 5 && memcmp (opname, "type", 4) == 0 -- && strchr (cplus_markers, opname[4]) != NULL) -- { -- /* type conversion operator */ -- tem = opname + 5; -- if (do_type (work, &tem, &type)) -- { -- strcat (result, "operator "); -- strncat (result, type.b, type.p - type.b); -- string_delete (&type); -- ret = 1; -- } -- } -- squangle_mop_up (work); -- return ret; -- --} -- --/* Takes operator name as e.g. "++" and returns mangled -- operator name (e.g. "postincrement_expr"), or NULL if not found. -- -- If OPTIONS & DMGL_ANSI == 1, return the ANSI name; -- if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ -- --const char * --cplus_mangle_opname (const char *opname, int options) --{ -- size_t i; -- int len; -- -- len = strlen (opname); -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- if ((int) strlen (optable[i].out) == len -- && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) -- && memcmp (optable[i].out, opname, len) == 0) -- return optable[i].in; -- } -- return (0); --} -- - /* Add a routine to set the demangling style to be sure it is valid and - allow for any demangler initialization that maybe necessary. */ - -@@ -840,22 +144,6 @@ cplus_demangle_name_to_style (const char - It is the caller's responsibility to free the string which - is returned. - -- The OPTIONS arg may contain one or more of the following bits: -- -- DMGL_ANSI ANSI qualifiers such as `const' and `void' are -- included. -- DMGL_PARAMS Function parameters are included. -- -- For example, -- -- cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" -- cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" -- cplus_demangle ("foo__1Ai", 0) => "A::foo" -- -- cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" -- cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" -- cplus_demangle ("foo__1Afe", 0) => "A::foo" -- - Note that any leading underscores, or other such characters prepended by - the compilation system, are presumed to have already been stripped from - MANGLED. */ -@@ -864,20 +152,17 @@ char * - cplus_demangle (const char *mangled, int options) - { - char *ret; -- struct work_stuff work[1]; - - if (current_demangling_style == no_demangling) - return xstrdup (mangled); - -- memset ((char *) work, 0, sizeof (work)); -- work->options = options; -- if ((work->options & DMGL_STYLE_MASK) == 0) -- work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; -+ if ((options & DMGL_STYLE_MASK) == 0) -+ options |= (int) current_demangling_style & DMGL_STYLE_MASK; - - /* The V3 ABI demangling is implemented elsewhere. */ - if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING) - { -- ret = cplus_demangle_v3 (mangled, work->options); -+ ret = cplus_demangle_v3 (mangled, options); - if (GNU_V3_DEMANGLING) - return ret; - -@@ -915,8 +200,6 @@ cplus_demangle (const char *mangled, int - return ret; - } - -- ret = internal_cplus_demangle (work, mangled); -- squangle_mop_up (work); - return (ret); - } - -@@ -1205,3828 +488,3 @@ ada_demangle (const char *mangled, int o - - return demangled; - } -- --/* This function performs most of what cplus_demangle use to do, but -- to be able to demangle a name with a B, K or n code, we need to -- have a longer term memory of what types have been seen. The original -- now initializes and cleans up the squangle code info, while internal -- calls go directly to this routine to avoid resetting that info. */ -- --static char * --internal_cplus_demangle (struct work_stuff *work, const char *mangled) --{ -- -- string decl; -- int success = 0; -- char *demangled = NULL; -- int s1, s2, s3, s4; -- s1 = work->constructor; -- s2 = work->destructor; -- s3 = work->static_type; -- s4 = work->type_quals; -- work->constructor = work->destructor = 0; -- work->type_quals = TYPE_UNQUALIFIED; -- work->dllimported = 0; -- -- if ((mangled != NULL) && (*mangled != '\0')) -- { -- string_init (&decl); -- -- /* First check to see if gnu style demangling is active and if the -- string to be demangled contains a CPLUS_MARKER. If so, attempt to -- recognize one of the gnu special forms rather than looking for a -- standard prefix. In particular, don't worry about whether there -- is a "__" string in the mangled string. Consider "_$_5__foo" for -- example. */ -- -- if ((AUTO_DEMANGLING || GNU_DEMANGLING)) -- { -- success = gnu_special (work, &mangled, &decl); -- if (!success) -- { -- delete_work_stuff (work); -- string_delete (&decl); -- } -- } -- if (!success) -- { -- success = demangle_prefix (work, &mangled, &decl); -- } -- if (success && (*mangled != '\0')) -- { -- success = demangle_signature (work, &mangled, &decl); -- } -- if (work->constructor == 2) -- { -- string_prepend (&decl, "global constructors keyed to "); -- work->constructor = 0; -- } -- else if (work->destructor == 2) -- { -- string_prepend (&decl, "global destructors keyed to "); -- work->destructor = 0; -- } -- else if (work->dllimported == 1) -- { -- string_prepend (&decl, "import stub for "); -- work->dllimported = 0; -- } -- demangled = mop_up (work, &decl, success); -- } -- work->constructor = s1; -- work->destructor = s2; -- work->static_type = s3; -- work->type_quals = s4; -- return demangled; --} -- -- --/* Clear out and squangling related storage */ --static void --squangle_mop_up (struct work_stuff *work) --{ -- /* clean up the B and K type mangling types. */ -- forget_B_and_K_types (work); -- if (work -> btypevec != NULL) -- { -- free ((char *) work -> btypevec); -- work->btypevec = NULL; -- work->bsize = 0; -- } -- if (work -> ktypevec != NULL) -- { -- free ((char *) work -> ktypevec); -- work->ktypevec = NULL; -- work->ksize = 0; -- } --} -- -- --/* Copy the work state and storage. */ -- --static void --work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from) --{ -- int i; -- -- delete_work_stuff (to); -- -- /* Shallow-copy scalars. */ -- memcpy (to, from, sizeof (*to)); -- -- /* Deep-copy dynamic storage. */ -- if (from->typevec_size) -- to->typevec = XNEWVEC (char *, from->typevec_size); -- -- for (i = 0; i < from->ntypes; i++) -- { -- int len = strlen (from->typevec[i]) + 1; -- -- to->typevec[i] = XNEWVEC (char, len); -- memcpy (to->typevec[i], from->typevec[i], len); -- } -- -- if (from->ksize) -- to->ktypevec = XNEWVEC (char *, from->ksize); -- -- for (i = 0; i < from->numk; i++) -- { -- int len = strlen (from->ktypevec[i]) + 1; -- -- to->ktypevec[i] = XNEWVEC (char, len); -- memcpy (to->ktypevec[i], from->ktypevec[i], len); -- } -- -- if (from->bsize) -- to->btypevec = XNEWVEC (char *, from->bsize); -- -- for (i = 0; i < from->numb; i++) -- { -- int len = strlen (from->btypevec[i]) + 1; -- -- to->btypevec[i] = XNEWVEC (char , len); -- memcpy (to->btypevec[i], from->btypevec[i], len); -- } -- -- if (from->proctypevec) -- to->proctypevec = -- XDUPVEC (int, from->proctypevec, from->proctypevec_size); -- -- if (from->ntmpl_args) -- to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args); -- -- for (i = 0; i < from->ntmpl_args; i++) -- { -- int len = strlen (from->tmpl_argvec[i]) + 1; -- -- to->tmpl_argvec[i] = XNEWVEC (char, len); -- memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); -- } -- -- if (from->previous_argument) -- { -- to->previous_argument = XNEW (string); -- string_init (to->previous_argument); -- string_appends (to->previous_argument, from->previous_argument); -- } --} -- -- --/* Delete dynamic stuff in work_stuff that is not to be re-used. */ -- --static void --delete_non_B_K_work_stuff (struct work_stuff *work) --{ -- /* Discard the remembered types, if any. */ -- -- forget_types (work); -- if (work->typevec != NULL) -- { -- free ((char *) work->typevec); -- work->typevec = NULL; -- work->typevec_size = 0; -- } -- if (work->proctypevec != NULL) -- { -- free (work->proctypevec); -- work->proctypevec = NULL; -- work->proctypevec_size = 0; -- } -- if (work->tmpl_argvec) -- { -- int i; -- -- for (i = 0; i < work->ntmpl_args; i++) -- free ((char*) work->tmpl_argvec[i]); -- -- free ((char*) work->tmpl_argvec); -- work->tmpl_argvec = NULL; -- } -- if (work->previous_argument) -- { -- string_delete (work->previous_argument); -- free ((char*) work->previous_argument); -- work->previous_argument = NULL; -- } --} -- -- --/* Delete all dynamic storage in work_stuff. */ --static void --delete_work_stuff (struct work_stuff *work) --{ -- delete_non_B_K_work_stuff (work); -- squangle_mop_up (work); --} -- -- --/* Clear out any mangled storage */ -- --static char * --mop_up (struct work_stuff *work, string *declp, int success) --{ -- char *demangled = NULL; -- -- delete_non_B_K_work_stuff (work); -- -- /* If demangling was successful, ensure that the demangled string is null -- terminated and return it. Otherwise, free the demangling decl. */ -- -- if (!success) -- { -- string_delete (declp); -- } -- else -- { -- string_appendn (declp, "", 1); -- demangled = declp->b; -- } -- return (demangled); --} -- --/* -- --LOCAL FUNCTION -- -- demangle_signature -- demangle the signature part of a mangled name -- --SYNOPSIS -- -- static int -- demangle_signature (struct work_stuff *work, const char **mangled, -- string *declp); -- --DESCRIPTION -- -- Consume and demangle the signature portion of the mangled name. -- -- DECLP is the string where demangled output is being built. At -- entry it contains the demangled root name from the mangled name -- prefix. I.E. either a demangled operator name or the root function -- name. In some special cases, it may contain nothing. -- -- *MANGLED points to the current unconsumed location in the mangled -- name. As tokens are consumed and demangling is performed, the -- pointer is updated to continuously point at the next token to -- be consumed. -- -- Demangling GNU style mangled names is nasty because there is no -- explicit token that marks the start of the outermost function -- argument list. */ -- --static int --demangle_signature (struct work_stuff *work, -- const char **mangled, string *declp) --{ -- int success = 1; -- int func_done = 0; -- int expect_func = 0; -- int expect_return_type = 0; -- const char *oldmangled = NULL; -- string trawname; -- string tname; -- -- while (success && (**mangled != '\0')) -- { -- switch (**mangled) -- { -- case 'Q': -- oldmangled = *mangled; -- success = demangle_qualified (work, mangled, declp, 1, 0); -- if (success) -- remember_type (work, oldmangled, *mangled - oldmangled); -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- expect_func = 1; -- oldmangled = NULL; -- break; -- -- case 'K': -- oldmangled = *mangled; -- success = demangle_qualified (work, mangled, declp, 1, 0); -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- { -- expect_func = 1; -- } -- oldmangled = NULL; -- break; -- -- case 'S': -- /* Static member function */ -- if (oldmangled == NULL) -- { -- oldmangled = *mangled; -- } -- (*mangled)++; -- work -> static_type = 1; -- break; -- -- case 'C': -- case 'V': -- case 'u': -- work->type_quals |= code_for_qualifier (**mangled); -- -- /* a qualified member function */ -- if (oldmangled == NULL) -- oldmangled = *mangled; -- (*mangled)++; -- break; -- -- case 'L': -- /* Local class name follows after "Lnnn_" */ -- if (HP_DEMANGLING) -- { -- while (**mangled && (**mangled != '_')) -- (*mangled)++; -- if (!**mangled) -- success = 0; -- else -- (*mangled)++; -- } -- else -- success = 0; -- break; -- -- case '0': case '1': case '2': case '3': case '4': -- case '5': case '6': case '7': case '8': case '9': -- if (oldmangled == NULL) -- { -- oldmangled = *mangled; -- } -- work->temp_start = -1; /* uppermost call to demangle_class */ -- success = demangle_class (work, mangled, declp); -- if (success) -- { -- remember_type (work, oldmangled, *mangled - oldmangled); -- } -- if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) -- { -- /* EDG and others will have the "F", so we let the loop cycle -- if we are looking at one. */ -- if (**mangled != 'F') -- expect_func = 1; -- } -- oldmangled = NULL; -- break; -- -- case 'B': -- { -- string s; -- success = do_type (work, mangled, &s); -- if (success) -- { -- string_append (&s, SCOPE_STRING (work)); -- string_prepends (declp, &s); -- string_delete (&s); -- } -- oldmangled = NULL; -- expect_func = 1; -- } -- break; -- -- case 'F': -- /* Function */ -- /* ARM/HP style demangling includes a specific 'F' character after -- the class name. For GNU style, it is just implied. So we can -- safely just consume any 'F' at this point and be compatible -- with either style. */ -- -- oldmangled = NULL; -- func_done = 1; -- (*mangled)++; -- -- /* For lucid/ARM/HP style we have to forget any types we might -- have remembered up to this point, since they were not argument -- types. GNU style considers all types seen as available for -- back references. See comment in demangle_args() */ -- -- if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) -- { -- forget_types (work); -- } -- success = demangle_args (work, mangled, declp); -- /* After picking off the function args, we expect to either -- find the function return type (preceded by an '_') or the -- end of the string. */ -- if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') -- { -- ++(*mangled); -- /* At this level, we do not care about the return type. */ -- success = do_type (work, mangled, &tname); -- string_delete (&tname); -- } -- -- break; -- -- case 't': -- /* G++ Template */ -- string_init(&trawname); -- string_init(&tname); -- if (oldmangled == NULL) -- { -- oldmangled = *mangled; -- } -- success = demangle_template (work, mangled, &tname, -- &trawname, 1, 1); -- if (success) -- { -- remember_type (work, oldmangled, *mangled - oldmangled); -- } -- string_append (&tname, SCOPE_STRING (work)); -- -- string_prepends(declp, &tname); -- if (work -> destructor & 1) -- { -- string_prepend (&trawname, "~"); -- string_appends (declp, &trawname); -- work->destructor -= 1; -- } -- if ((work->constructor & 1) || (work->destructor & 1)) -- { -- string_appends (declp, &trawname); -- work->constructor -= 1; -- } -- string_delete(&trawname); -- string_delete(&tname); -- oldmangled = NULL; -- expect_func = 1; -- break; -- -- case '_': -- if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) -- { -- /* Read the return type. */ -- string return_type; -- -- (*mangled)++; -- success = do_type (work, mangled, &return_type); -- APPEND_BLANK (&return_type); -- -- string_prepends (declp, &return_type); -- string_delete (&return_type); -- break; -- } -- else -- /* At the outermost level, we cannot have a return type specified, -- so if we run into another '_' at this point we are dealing with -- a mangled name that is either bogus, or has been mangled by -- some algorithm we don't know how to deal with. So just -- reject the entire demangling. */ -- /* However, "_nnn" is an expected suffix for alternate entry point -- numbered nnn for a function, with HP aCC, so skip over that -- without reporting failure. pai/1997-09-04 */ -- if (HP_DEMANGLING) -- { -- (*mangled)++; -- while (**mangled && ISDIGIT ((unsigned char)**mangled)) -- (*mangled)++; -- } -- else -- success = 0; -- break; -- -- case 'H': -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- { -- /* A G++ template function. Read the template arguments. */ -- success = demangle_template (work, mangled, declp, 0, 0, -- 0); -- if (!(work->constructor & 1)) -- expect_return_type = 1; -- if (!**mangled) -- success = 0; -- else -- (*mangled)++; -- break; -- } -- /* fall through */ -- -- default: -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- { -- /* Assume we have stumbled onto the first outermost function -- argument token, and start processing args. */ -- func_done = 1; -- success = demangle_args (work, mangled, declp); -- } -- else -- { -- /* Non-GNU demanglers use a specific token to mark the start -- of the outermost function argument tokens. Typically 'F', -- for ARM/HP-demangling, for example. So if we find something -- we are not prepared for, it must be an error. */ -- success = 0; -- } -- break; -- } -- /* -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- */ -- { -- if (success && expect_func) -- { -- func_done = 1; -- if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) -- { -- forget_types (work); -- } -- success = demangle_args (work, mangled, declp); -- /* Since template include the mangling of their return types, -- we must set expect_func to 0 so that we don't try do -- demangle more arguments the next time we get here. */ -- expect_func = 0; -- } -- } -- } -- if (success && !func_done) -- { -- if (AUTO_DEMANGLING || GNU_DEMANGLING) -- { -- /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and -- bar__3fooi is 'foo::bar(int)'. We get here when we find the -- first case, and need to ensure that the '(void)' gets added to -- the current declp. Note that with ARM/HP, the first case -- represents the name of a static data member 'foo::bar', -- which is in the current declp, so we leave it alone. */ -- success = demangle_args (work, mangled, declp); -- } -- } -- if (success && PRINT_ARG_TYPES) -- { -- if (work->static_type) -- string_append (declp, " static"); -- if (work->type_quals != TYPE_UNQUALIFIED) -- { -- APPEND_BLANK (declp); -- string_append (declp, qualifier_string (work->type_quals)); -- } -- } -- -- return (success); --} -- --#if 0 -- --static int --demangle_method_args (struct work_stuff *work, const char **mangled, -- string *declp) --{ -- int success = 0; -- -- if (work -> static_type) -- { -- string_append (declp, *mangled + 1); -- *mangled += strlen (*mangled); -- success = 1; -- } -- else -- { -- success = demangle_args (work, mangled, declp); -- } -- return (success); --} -- --#endif -- --static int --demangle_template_template_parm (struct work_stuff *work, -- const char **mangled, string *tname) --{ -- int i; -- int r; -- int need_comma = 0; -- int success = 1; -- string temp; -- -- string_append (tname, "template <"); -- /* get size of template parameter list */ -- if (get_count (mangled, &r)) -- { -- for (i = 0; i < r; i++) -- { -- if (need_comma) -- { -- string_append (tname, ", "); -- } -- -- /* Z for type parameters */ -- if (**mangled == 'Z') -- { -- (*mangled)++; -- string_append (tname, "class"); -- } -- /* z for template parameters */ -- else if (**mangled == 'z') -- { -- (*mangled)++; -- success = -- demangle_template_template_parm (work, mangled, tname); -- if (!success) -- { -- break; -- } -- } -- else -- { -- /* temp is initialized in do_type */ -- success = do_type (work, mangled, &temp); -- if (success) -- { -- string_appends (tname, &temp); -- } -- string_delete(&temp); -- if (!success) -- { -- break; -- } -- } -- need_comma = 1; -- } -- -- } -- if (tname->p[-1] == '>') -- string_append (tname, " "); -- string_append (tname, "> class"); -- return (success); --} -- --static int --demangle_expression (struct work_stuff *work, const char **mangled, -- string *s, type_kind_t tk) --{ -- int need_operator = 0; -- int success; -- -- success = 1; -- string_appendn (s, "(", 1); -- (*mangled)++; -- while (success && **mangled != 'W' && **mangled != '\0') -- { -- if (need_operator) -- { -- size_t i; -- size_t len; -- -- success = 0; -- -- len = strlen (*mangled); -- -- for (i = 0; i < ARRAY_SIZE (optable); ++i) -- { -- size_t l = strlen (optable[i].in); -- -- if (l <= len -- && memcmp (optable[i].in, *mangled, l) == 0) -- { -- string_appendn (s, " ", 1); -- string_append (s, optable[i].out); -- string_appendn (s, " ", 1); -- success = 1; -- (*mangled) += l; -- break; -- } -- } -- -- if (!success) -- break; -- } -- else -- need_operator = 1; -- -- success = demangle_template_value_parm (work, mangled, s, tk); -- } -- -- if (**mangled != 'W') -- success = 0; -- else -- { -- string_appendn (s, ")", 1); -- (*mangled)++; -- } -- -- return success; --} -- --static int --demangle_integral_value (struct work_stuff *work, -- const char **mangled, string *s) --{ -- int success; -- -- if (**mangled == 'E') -- success = demangle_expression (work, mangled, s, tk_integral); -- else if (**mangled == 'Q' || **mangled == 'K') -- success = demangle_qualified (work, mangled, s, 0, 1); -- else -- { -- int value; -- -- /* By default, we let the number decide whether we shall consume an -- underscore. */ -- int multidigit_without_leading_underscore = 0; -- int leave_following_underscore = 0; -- -- success = 0; -- -- if (**mangled == '_') -- { -- if (mangled[0][1] == 'm') -- { -- /* Since consume_count_with_underscores does not handle the -- `m'-prefix we must do it here, using consume_count and -- adjusting underscores: we have to consume the underscore -- matching the prepended one. */ -- multidigit_without_leading_underscore = 1; -- string_appendn (s, "-", 1); -- (*mangled) += 2; -- } -- else -- { -- /* Do not consume a following underscore; -- consume_count_with_underscores will consume what -- should be consumed. */ -- leave_following_underscore = 1; -- } -- } -- else -- { -- /* Negative numbers are indicated with a leading `m'. */ -- if (**mangled == 'm') -- { -- string_appendn (s, "-", 1); -- (*mangled)++; -- } -- /* Since consume_count_with_underscores does not handle -- multi-digit numbers that do not start with an underscore, -- and this number can be an integer template parameter, -- we have to call consume_count. */ -- multidigit_without_leading_underscore = 1; -- /* These multi-digit numbers never end on an underscore, -- so if there is one then don't eat it. */ -- leave_following_underscore = 1; -- } -- -- /* We must call consume_count if we expect to remove a trailing -- underscore, since consume_count_with_underscores expects -- the leading underscore (that we consumed) if it is to handle -- multi-digit numbers. */ -- if (multidigit_without_leading_underscore) -- value = consume_count (mangled); -- else -- value = consume_count_with_underscores (mangled); -- -- if (value != -1) -- { -- char buf[INTBUF_SIZE]; -- sprintf (buf, "%d", value); -- string_append (s, buf); -- -- /* Numbers not otherwise delimited, might have an underscore -- appended as a delimeter, which we should skip. -- -- ??? This used to always remove a following underscore, which -- is wrong. If other (arbitrary) cases are followed by an -- underscore, we need to do something more radical. */ -- -- if ((value > 9 || multidigit_without_leading_underscore) -- && ! leave_following_underscore -- && **mangled == '_') -- (*mangled)++; -- -- /* All is well. */ -- success = 1; -- } -- } -- -- return success; --} -- --/* Demangle the real value in MANGLED. */ -- --static int --demangle_real_value (struct work_stuff *work, -- const char **mangled, string *s) --{ -- if (**mangled == 'E') -- return demangle_expression (work, mangled, s, tk_real); -- -- if (**mangled == 'm') -- { -- string_appendn (s, "-", 1); -- (*mangled)++; -- } -- while (ISDIGIT ((unsigned char)**mangled)) -- { -- string_appendn (s, *mangled, 1); -- (*mangled)++; -- } -- if (**mangled == '.') /* fraction */ -- { -- string_appendn (s, ".", 1); -- (*mangled)++; -- while (ISDIGIT ((unsigned char)**mangled)) -- { -- string_appendn (s, *mangled, 1); -- (*mangled)++; -- } -- } -- if (**mangled == 'e') /* exponent */ -- { -- string_appendn (s, "e", 1); -- (*mangled)++; -- while (ISDIGIT ((unsigned char)**mangled)) -- { -- string_appendn (s, *mangled, 1); -- (*mangled)++; -- } -- } -- -- return 1; --} -- --static int --demangle_template_value_parm (struct work_stuff *work, const char **mangled, -- string *s, type_kind_t tk) --{ -- int success = 1; -- -- if (**mangled == 'Y') -- { -- /* The next argument is a template parameter. */ -- int idx; -- -- (*mangled)++; -- idx = consume_count_with_underscores (mangled); -- if (idx == -1 -- || (work->tmpl_argvec && idx >= work->ntmpl_args) -- || consume_count_with_underscores (mangled) == -1) -- return -1; -- if (work->tmpl_argvec) -- string_append (s, work->tmpl_argvec[idx]); -- else -- string_append_template_idx (s, idx); -- } -- else if (tk == tk_integral) -- success = demangle_integral_value (work, mangled, s); -- else if (tk == tk_char) -- { -- char tmp[2]; -- int val; -- if (**mangled == 'm') -- { -- string_appendn (s, "-", 1); -- (*mangled)++; -- } -- string_appendn (s, "'", 1); -- val = consume_count(mangled); -- if (val <= 0) -- success = 0; -- else -- { -- tmp[0] = (char)val; -- tmp[1] = '\0'; -- string_appendn (s, &tmp[0], 1); -- string_appendn (s, "'", 1); -- } -- } -- else if (tk == tk_bool) -- { -- int val = consume_count (mangled); -- if (val == 0) -- string_appendn (s, "false", 5); -- else if (val == 1) -- string_appendn (s, "true", 4); -- else -- success = 0; -- } -- else if (tk == tk_real) -- success = demangle_real_value (work, mangled, s); -- else if (tk == tk_pointer || tk == tk_reference -- || tk == tk_rvalue_reference) -- { -- if (**mangled == 'Q') -- success = demangle_qualified (work, mangled, s, -- /*isfuncname=*/0, -- /*append=*/1); -- else -- { -- int symbol_len = consume_count (mangled); -- if (symbol_len == -1 -- || symbol_len > (long) strlen (*mangled)) -- return -1; -- if (symbol_len == 0) -- string_appendn (s, "0", 1); -- else -- { -- char *p = XNEWVEC (char, symbol_len + 1), *q; -- strncpy (p, *mangled, symbol_len); -- p [symbol_len] = '\0'; -- /* We use cplus_demangle here, rather than -- internal_cplus_demangle, because the name of the entity -- mangled here does not make use of any of the squangling -- or type-code information we have built up thus far; it is -- mangled independently. */ -- q = cplus_demangle (p, work->options); -- if (tk == tk_pointer) -- string_appendn (s, "&", 1); -- /* FIXME: Pointer-to-member constants should get a -- qualifying class name here. */ -- if (q) -- { -- string_append (s, q); -- free (q); -- } -- else -- string_append (s, p); -- free (p); -- } -- *mangled += symbol_len; -- } -- } -- -- return success; --} -- --/* Demangle the template name in MANGLED. The full name of the -- template (e.g., S) is placed in TNAME. The name without the -- template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is -- non-NULL. If IS_TYPE is nonzero, this template is a type template, -- not a function template. If both IS_TYPE and REMEMBER are nonzero, -- the template is remembered in the list of back-referenceable -- types. */ -- --static int --demangle_template (struct work_stuff *work, const char **mangled, -- string *tname, string *trawname, -- int is_type, int remember) --{ -- int i; -- int r; -- int need_comma = 0; -- int success = 0; -- int is_java_array = 0; -- string temp; -- -- (*mangled)++; -- if (is_type) -- { -- /* get template name */ -- if (**mangled == 'z') -- { -- int idx; -- (*mangled)++; -- if (**mangled == '\0') -- return (0); -- (*mangled)++; -- -- idx = consume_count_with_underscores (mangled); -- if (idx == -1 -- || (work->tmpl_argvec && idx >= work->ntmpl_args) -- || consume_count_with_underscores (mangled) == -1) -- return (0); -- -- if (work->tmpl_argvec) -- { -- string_append (tname, work->tmpl_argvec[idx]); -- if (trawname) -- string_append (trawname, work->tmpl_argvec[idx]); -- } -- else -- { -- string_append_template_idx (tname, idx); -- if (trawname) -- string_append_template_idx (trawname, idx); -- } -- } -- else -- { -- if ((r = consume_count (mangled)) <= 0 -- || (int) strlen (*mangled) < r) -- { -- return (0); -- } -- is_java_array = (work -> options & DMGL_JAVA) -- && strncmp (*mangled, "JArray1Z", 8) == 0; -- if (! is_java_array) -- { -- string_appendn (tname, *mangled, r); -- } -- if (trawname) -- string_appendn (trawname, *mangled, r); -- *mangled += r; -- } -- } -- if (!is_java_array) -- string_append (tname, "<"); -- /* get size of template parameter list */ -- if (!get_count (mangled, &r)) -- { -- return (0); -- } -- if (!is_type) -- { -- /* Create an array for saving the template argument values. */ -- work->tmpl_argvec = XNEWVEC (char *, r); -- work->ntmpl_args = r; -- for (i = 0; i < r; i++) -- work->tmpl_argvec[i] = 0; -- } -- for (i = 0; i < r; i++) -- { -- if (need_comma) -- { -- string_append (tname, ", "); -- } -- /* Z for type parameters */ -- if (**mangled == 'Z') -- { -- (*mangled)++; -- /* temp is initialized in do_type */ -- success = do_type (work, mangled, &temp); -- if (success) -- { -- string_appends (tname, &temp); -- -- if (!is_type) -- { -- /* Save the template argument. */ -- int len = temp.p - temp.b; -- work->tmpl_argvec[i] = XNEWVEC (char, len + 1); -- memcpy (work->tmpl_argvec[i], temp.b, len); -- work->tmpl_argvec[i][len] = '\0'; -- } -- } -- string_delete(&temp); -- if (!success) -- { -- break; -- } -- } -- /* z for template parameters */ -- else if (**mangled == 'z') -- { -- int r2; -- (*mangled)++; -- success = demangle_template_template_parm (work, mangled, tname); -- -- if (success -- && (r2 = consume_count (mangled)) > 0 -- && (int) strlen (*mangled) >= r2) -- { -- string_append (tname, " "); -- string_appendn (tname, *mangled, r2); -- if (!is_type) -- { -- /* Save the template argument. */ -- int len = r2; -- work->tmpl_argvec[i] = XNEWVEC (char, len + 1); -- memcpy (work->tmpl_argvec[i], *mangled, len); -- work->tmpl_argvec[i][len] = '\0'; -- } -- *mangled += r2; -- } -- if (!success) -- { -- break; -- } -- } -- else -- { -- string param; -- string* s; -- -- /* otherwise, value parameter */ -- -- /* temp is initialized in do_type */ -- success = do_type (work, mangled, &temp); -- string_delete(&temp); -- if (!success) -- break; -- -- if (!is_type) -- { -- s = ¶m; -- string_init (s); -- } -- else -- s = tname; -- -- success = demangle_template_value_parm (work, mangled, s, -- (type_kind_t) success); -- -- if (!success) -- { -- if (!is_type) -- string_delete (s); -- success = 0; -- break; -- } -- -- if (!is_type) -- { -- int len = s->p - s->b; -- work->tmpl_argvec[i] = XNEWVEC (char, len + 1); -- memcpy (work->tmpl_argvec[i], s->b, len); -- work->tmpl_argvec[i][len] = '\0'; -- -- string_appends (tname, s); -- string_delete (s); -- } -- } -- need_comma = 1; -- } -- if (is_java_array) -- { -- string_append (tname, "[]"); -- } -- else -- { -- if (tname->p[-1] == '>') -- string_append (tname, " "); -- string_append (tname, ">"); -- } -- -- if (is_type && remember) -- { -- const int bindex = register_Btype (work); -- remember_Btype (work, tname->b, LEN_STRING (tname), bindex); -- } -- -- /* -- if (work -> static_type) -- { -- string_append (declp, *mangled + 1); -- *mangled += strlen (*mangled); -- success = 1; -- } -- else -- { -- success = demangle_args (work, mangled, declp); -- } -- } -- */ -- return (success); --} -- --static int --arm_pt (struct work_stuff *work, const char *mangled, -- int n, const char **anchor, const char **args) --{ -- /* Check if ARM template with "__pt__" in it ("parameterized type") */ -- /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ -- if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) -- { -- int len; -- *args = *anchor + 6; -- len = consume_count (args); -- if (len == -1) -- return 0; -- if (*args + len == mangled + n && **args == '_') -- { -- ++*args; -- return 1; -- } -- } -- if (AUTO_DEMANGLING || EDG_DEMANGLING) -- { -- if ((*anchor = strstr (mangled, "__tm__")) -- || (*anchor = strstr (mangled, "__ps__")) -- || (*anchor = strstr (mangled, "__pt__"))) -- { -- int len; -- *args = *anchor + 6; -- len = consume_count (args); -- if (len == -1) -- return 0; -- if (*args + len == mangled + n && **args == '_') -- { -- ++*args; -- return 1; -- } -- } -- else if ((*anchor = strstr (mangled, "__S"))) -- { -- int len; -- *args = *anchor + 3; -- len = consume_count (args); -- if (len == -1) -- return 0; -- if (*args + len == mangled + n && **args == '_') -- { -- ++*args; -- return 1; -- } -- } -- } -- -- return 0; --} -- --static void --demangle_arm_hp_template (struct work_stuff *work, const char **mangled, -- int n, string *declp) --{ -- const char *p; -- const char *args; -- const char *e = *mangled + n; -- string arg; -- -- /* Check for HP aCC template spec: classXt1t2 where t1, t2 are -- template args */ -- if (HP_DEMANGLING && ((*mangled)[n] == 'X')) -- { -- char *start_spec_args = NULL; -- int hold_options; -- -- /* First check for and omit template specialization pseudo-arguments, -- such as in "Spec<#1,#1.*>" */ -- start_spec_args = strchr (*mangled, '<'); -- if (start_spec_args && (start_spec_args - *mangled < n)) -- string_appendn (declp, *mangled, start_spec_args - *mangled); -- else -- string_appendn (declp, *mangled, n); -- (*mangled) += n + 1; -- string_init (&arg); -- if (work->temp_start == -1) /* non-recursive call */ -- work->temp_start = declp->p - declp->b; -- -- /* We want to unconditionally demangle parameter types in -- template parameters. */ -- hold_options = work->options; -- work->options |= DMGL_PARAMS; -- -- string_append (declp, "<"); -- while (1) -- { -- string_delete (&arg); -- switch (**mangled) -- { -- case 'T': -- /* 'T' signals a type parameter */ -- (*mangled)++; -- if (!do_type (work, mangled, &arg)) -- goto hpacc_template_args_done; -- break; -- -- case 'U': -- case 'S': -- /* 'U' or 'S' signals an integral value */ -- if (!do_hpacc_template_const_value (work, mangled, &arg)) -- goto hpacc_template_args_done; -- break; -- -- case 'A': -- /* 'A' signals a named constant expression (literal) */ -- if (!do_hpacc_template_literal (work, mangled, &arg)) -- goto hpacc_template_args_done; -- break; -- -- default: -- /* Today, 1997-09-03, we have only the above types -- of template parameters */ -- /* FIXME: maybe this should fail and return null */ -- goto hpacc_template_args_done; -- } -- string_appends (declp, &arg); -- /* Check if we're at the end of template args. -- 0 if at end of static member of template class, -- _ if done with template args for a function */ -- if ((**mangled == '\000') || (**mangled == '_')) -- break; -- else -- string_append (declp, ","); -- } -- hpacc_template_args_done: -- string_append (declp, ">"); -- string_delete (&arg); -- if (**mangled == '_') -- (*mangled)++; -- work->options = hold_options; -- return; -- } -- /* ARM template? (Also handles HP cfront extensions) */ -- else if (arm_pt (work, *mangled, n, &p, &args)) -- { -- int hold_options; -- string type_str; -- -- string_init (&arg); -- string_appendn (declp, *mangled, p - *mangled); -- if (work->temp_start == -1) /* non-recursive call */ -- work->temp_start = declp->p - declp->b; -- -- /* We want to unconditionally demangle parameter types in -- template parameters. */ -- hold_options = work->options; -- work->options |= DMGL_PARAMS; -- -- string_append (declp, "<"); -- /* should do error checking here */ -- while (args < e) { -- string_delete (&arg); -- -- /* Check for type or literal here */ -- switch (*args) -- { -- /* HP cfront extensions to ARM for template args */ -- /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ -- /* FIXME: We handle only numeric literals for HP cfront */ -- case 'X': -- /* A typed constant value follows */ -- args++; -- if (!do_type (work, &args, &type_str)) -- goto cfront_template_args_done; -- string_append (&arg, "("); -- string_appends (&arg, &type_str); -- string_delete (&type_str); -- string_append (&arg, ")"); -- if (*args != 'L') -- goto cfront_template_args_done; -- args++; -- /* Now snarf a literal value following 'L' */ -- if (!snarf_numeric_literal (&args, &arg)) -- goto cfront_template_args_done; -- break; -- -- case 'L': -- /* Snarf a literal following 'L' */ -- args++; -- if (!snarf_numeric_literal (&args, &arg)) -- goto cfront_template_args_done; -- break; -- default: -- /* Not handling other HP cfront stuff */ -- { -- const char* old_args = args; -- if (!do_type (work, &args, &arg)) -- goto cfront_template_args_done; -- -- /* Fail if we didn't make any progress: prevent infinite loop. */ -- if (args == old_args) -- { -- work->options = hold_options; -- return; -- } -- } -- } -- string_appends (declp, &arg); -- string_append (declp, ","); -- } -- cfront_template_args_done: -- string_delete (&arg); -- if (args >= e) -- --declp->p; /* remove extra comma */ -- string_append (declp, ">"); -- work->options = hold_options; -- } -- else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 -- && (*mangled)[9] == 'N' -- && (*mangled)[8] == (*mangled)[10] -- && strchr (cplus_markers, (*mangled)[8])) -- { -- /* A member of the anonymous namespace. */ -- string_append (declp, "{anonymous}"); -- } -- else -- { -- if (work->temp_start == -1) /* non-recursive call only */ -- work->temp_start = 0; /* disable in recursive calls */ -- string_appendn (declp, *mangled, n); -- } -- *mangled += n; --} -- --/* Extract a class name, possibly a template with arguments, from the -- mangled string; qualifiers, local class indicators, etc. have -- already been dealt with */ -- --static int --demangle_class_name (struct work_stuff *work, const char **mangled, -- string *declp) --{ -- int n; -- int success = 0; -- -- n = consume_count (mangled); -- if (n == -1) -- return 0; -- if ((int) strlen (*mangled) >= n) -- { -- demangle_arm_hp_template (work, mangled, n, declp); -- success = 1; -- } -- -- return (success); --} -- --/* -- --LOCAL FUNCTION -- -- demangle_class -- demangle a mangled class sequence -- --SYNOPSIS -- -- static int -- demangle_class (struct work_stuff *work, const char **mangled, -- strint *declp) -- --DESCRIPTION -- -- DECLP points to the buffer into which demangling is being done. -- -- *MANGLED points to the current token to be demangled. On input, -- it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) -- On exit, it points to the next token after the mangled class on -- success, or the first unconsumed token on failure. -- -- If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then -- we are demangling a constructor or destructor. In this case -- we prepend "class::class" or "class::~class" to DECLP. -- -- Otherwise, we prepend "class::" to the current DECLP. -- -- Reset the constructor/destructor flags once they have been -- "consumed". This allows demangle_class to be called later during -- the same demangling, to do normal class demangling. -- -- Returns 1 if demangling is successful, 0 otherwise. -- --*/ -- --static int --demangle_class (struct work_stuff *work, const char **mangled, string *declp) --{ -- int success = 0; -- int btype; -- string class_name; -- char *save_class_name_end = 0; -- -- string_init (&class_name); -- btype = register_Btype (work); -- if (demangle_class_name (work, mangled, &class_name)) -- { -- save_class_name_end = class_name.p; -- if ((work->constructor & 1) || (work->destructor & 1)) -- { -- /* adjust so we don't include template args */ -- if (work->temp_start && (work->temp_start != -1)) -- { -- class_name.p = class_name.b + work->temp_start; -- } -- string_prepends (declp, &class_name); -- if (work -> destructor & 1) -- { -- string_prepend (declp, "~"); -- work -> destructor -= 1; -- } -- else -- { -- work -> constructor -= 1; -- } -- } -- class_name.p = save_class_name_end; -- remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); -- remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); -- string_prepend (declp, SCOPE_STRING (work)); -- string_prepends (declp, &class_name); -- success = 1; -- } -- string_delete (&class_name); -- return (success); --} -- -- --/* Called when there's a "__" in the mangled name, with `scan' pointing to -- the rightmost guess. -- -- Find the correct "__"-sequence where the function name ends and the -- signature starts, which is ambiguous with GNU mangling. -- Call demangle_signature here, so we can make sure we found the right -- one; *mangled will be consumed so caller will not make further calls to -- demangle_signature. */ -- --static int --iterate_demangle_function (struct work_stuff *work, const char **mangled, -- string *declp, const char *scan) --{ -- const char *mangle_init = *mangled; -- int success = 0; -- string decl_init; -- struct work_stuff work_init; -- -- if (*(scan + 2) == '\0') -- return 0; -- -- /* Do not iterate for some demangling modes, or if there's only one -- "__"-sequence. This is the normal case. */ -- if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING -- || strstr (scan + 2, "__") == NULL) -- return demangle_function_name (work, mangled, declp, scan); -- -- /* Save state so we can restart if the guess at the correct "__" was -- wrong. */ -- string_init (&decl_init); -- string_appends (&decl_init, declp); -- memset (&work_init, 0, sizeof work_init); -- work_stuff_copy_to_from (&work_init, work); -- -- /* Iterate over occurrences of __, allowing names and types to have a -- "__" sequence in them. We must start with the first (not the last) -- occurrence, since "__" most often occur between independent mangled -- parts, hence starting at the last occurence inside a signature -- might get us a "successful" demangling of the signature. */ -- -- while (scan[2]) -- { -- if (demangle_function_name (work, mangled, declp, scan)) -- { -- success = demangle_signature (work, mangled, declp); -- if (success) -- break; -- } -- -- /* Reset demangle state for the next round. */ -- *mangled = mangle_init; -- string_clear (declp); -- string_appends (declp, &decl_init); -- work_stuff_copy_to_from (work, &work_init); -- -- /* Leave this underscore-sequence. */ -- scan += 2; -- -- /* Scan for the next "__" sequence. */ -- while (*scan && (scan[0] != '_' || scan[1] != '_')) -- scan++; -- -- /* Move to last "__" in this sequence. */ -- while (*scan && *scan == '_') -- scan++; -- scan -= 2; -- } -- -- /* Delete saved state. */ -- delete_work_stuff (&work_init); -- string_delete (&decl_init); -- -- return success; --} -- --/* -- --LOCAL FUNCTION -- -- demangle_prefix -- consume the mangled name prefix and find signature -- --SYNOPSIS -- -- static int -- demangle_prefix (struct work_stuff *work, const char **mangled, -- string *declp); -- --DESCRIPTION -- -- Consume and demangle the prefix of the mangled name. -- While processing the function name root, arrange to call -- demangle_signature if the root is ambiguous. -- -- DECLP points to the string buffer into which demangled output is -- placed. On entry, the buffer is empty. On exit it contains -- the root function name, the demangled operator name, or in some -- special cases either nothing or the completely demangled result. -- -- MANGLED points to the current pointer into the mangled name. As each -- token of the mangled name is consumed, it is updated. Upon entry -- the current mangled name pointer points to the first character of -- the mangled name. Upon exit, it should point to the first character -- of the signature if demangling was successful, or to the first -- unconsumed character if demangling of the prefix was unsuccessful. -- -- Returns 1 on success, 0 otherwise. -- */ -- --static int --demangle_prefix (struct work_stuff *work, const char **mangled, -- string *declp) --{ -- int success = 1; -- const char *scan; -- int i; -- -- if (strlen(*mangled) > 6 -- && (strncmp(*mangled, "_imp__", 6) == 0 -- || strncmp(*mangled, "__imp_", 6) == 0)) -- { -- /* it's a symbol imported from a PE dynamic library. Check for both -- new style prefix _imp__ and legacy __imp_ used by older versions -- of dlltool. */ -- (*mangled) += 6; -- work->dllimported = 1; -- } -- else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) -- { -- char *marker = strchr (cplus_markers, (*mangled)[8]); -- if (marker != NULL && *marker == (*mangled)[10]) -- { -- if ((*mangled)[9] == 'D') -- { -- /* it's a GNU global destructor to be executed at program exit */ -- (*mangled) += 11; -- work->destructor = 2; -- if (gnu_special (work, mangled, declp)) -- return success; -- } -- else if ((*mangled)[9] == 'I') -- { -- /* it's a GNU global constructor to be executed at program init */ -- (*mangled) += 11; -- work->constructor = 2; -- if (gnu_special (work, mangled, declp)) -- return success; -- } -- } -- } -- else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) -- { -- /* it's a ARM global destructor to be executed at program exit */ -- (*mangled) += 7; -- work->destructor = 2; -- } -- else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) -- { -- /* it's a ARM global constructor to be executed at program initial */ -- (*mangled) += 7; -- work->constructor = 2; -- } -- -- /* This block of code is a reduction in strength time optimization -- of: -- scan = strstr (*mangled, "__"); */ -- -- { -- scan = *mangled; -- -- do { -- scan = strchr (scan, '_'); -- } while (scan != NULL && *++scan != '_'); -- -- if (scan != NULL) --scan; -- } -- -- if (scan != NULL) -- { -- /* We found a sequence of two or more '_', ensure that we start at -- the last pair in the sequence. */ -- i = strspn (scan, "_"); -- if (i > 2) -- { -- scan += (i - 2); -- } -- } -- -- if (scan == NULL) -- { -- success = 0; -- } -- else if (work -> static_type) -- { -- if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) -- { -- success = 0; -- } -- } -- else if ((scan == *mangled) -- && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') -- || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) -- { -- /* The ARM says nothing about the mangling of local variables. -- But cfront mangles local variables by prepending __ -- to them. As an extension to ARM demangling we handle this case. */ -- if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) -- && ISDIGIT ((unsigned char)scan[2])) -- { -- *mangled = scan + 2; -- consume_count (mangled); -- string_append (declp, *mangled); -- *mangled += strlen (*mangled); -- success = 1; -- } -- else -- { -- /* A GNU style constructor starts with __[0-9Qt]. But cfront uses -- names like __Q2_3foo3bar for nested type names. So don't accept -- this style of constructor for cfront demangling. A GNU -- style member-template constructor starts with 'H'. */ -- if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) -- work -> constructor += 1; -- *mangled = scan + 2; -- } -- } -- else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') -- { -- /* Cfront-style parameterized type. Handled later as a signature. */ -- success = 1; -- -- /* ARM template? */ -- demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); -- } -- else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') -- || (scan[2] == 'p' && scan[3] == 's') -- || (scan[2] == 'p' && scan[3] == 't'))) -- { -- /* EDG-style parameterized type. Handled later as a signature. */ -- success = 1; -- -- /* EDG template? */ -- demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); -- } -- else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) -- && (scan[2] != 't')) -- { -- /* Mangled name starts with "__". Skip over any leading '_' characters, -- then find the next "__" that separates the prefix from the signature. -- */ -- if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) -- || (arm_special (mangled, declp) == 0)) -- { -- while (*scan == '_') -- { -- scan++; -- } -- if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) -- { -- /* No separator (I.E. "__not_mangled"), or empty signature -- (I.E. "__not_mangled_either__") */ -- success = 0; -- } -- else -- return iterate_demangle_function (work, mangled, declp, scan); -- } -- } -- else if (*(scan + 2) != '\0') -- { -- /* Mangled name does not start with "__" but does have one somewhere -- in there with non empty stuff after it. Looks like a global -- function name. Iterate over all "__":s until the right -- one is found. */ -- return iterate_demangle_function (work, mangled, declp, scan); -- } -- else -- { -- /* Doesn't look like a mangled name */ -- success = 0; -- } -- -- if (!success && (work->constructor == 2 || work->destructor == 2)) -- { -- string_append (declp, *mangled); -- *mangled += strlen (*mangled); -- success = 1; -- } -- return (success); --} -- --/* -- --LOCAL FUNCTION -- -- gnu_special -- special handling of gnu mangled strings -- --SYNOPSIS -- -- static int -- gnu_special (struct work_stuff *work, const char **mangled, -- string *declp); -- -- --DESCRIPTION -- -- Process some special GNU style mangling forms that don't fit -- the normal pattern. For example: -- -- _$_3foo (destructor for class foo) -- _vt$foo (foo virtual table) -- _vt$foo$bar (foo::bar virtual table) -- __vt_foo (foo virtual table, new style with thunks) -- _3foo$varname (static data member) -- _Q22rs2tu$vw (static data member) -- __t6vector1Zii (constructor with template) -- __thunk_4__$_7ostream (virtual function thunk) -- */ -- --static int --gnu_special (struct work_stuff *work, const char **mangled, string *declp) --{ -- int n; -- int success = 1; -- const char *p; -- -- if ((*mangled)[0] == '_' && (*mangled)[1] != '\0' -- && strchr (cplus_markers, (*mangled)[1]) != NULL -- && (*mangled)[2] == '_') -- { -- /* Found a GNU style destructor, get past "__" */ -- (*mangled) += 3; -- work -> destructor += 1; -- } -- else if ((*mangled)[0] == '_' -- && (((*mangled)[1] == '_' -- && (*mangled)[2] == 'v' -- && (*mangled)[3] == 't' -- && (*mangled)[4] == '_') -- || ((*mangled)[1] == 'v' -- && (*mangled)[2] == 't' && (*mangled)[3] != '\0' -- && strchr (cplus_markers, (*mangled)[3]) != NULL))) -- { -- /* Found a GNU style virtual table, get past "_vt" -- and create the decl. Note that we consume the entire mangled -- input string, which means that demangle_signature has no work -- to do. */ -- if ((*mangled)[2] == 'v') -- (*mangled) += 5; /* New style, with thunks: "__vt_" */ -- else -- (*mangled) += 4; /* Old style, no thunks: "_vt" */ -- while (**mangled != '\0') -- { -- switch (**mangled) -- { -- case 'Q': -- case 'K': -- success = demangle_qualified (work, mangled, declp, 0, 1); -- break; -- case 't': -- success = demangle_template (work, mangled, declp, 0, 1, -- 1); -- break; -- default: -- if (ISDIGIT((unsigned char)*mangled[0])) -- { -- n = consume_count(mangled); -- /* We may be seeing a too-large size, or else a -- "." indicating a static local symbol. In -- any case, declare victory and move on; *don't* try -- to use n to allocate. */ -- if (n > (int) strlen (*mangled)) -- { -- success = 1; -- break; -- } -- else if (n == -1) -- { -- success = 0; -- break; -- } -- } -- else -- { -- n = strcspn (*mangled, cplus_markers); -- } -- string_appendn (declp, *mangled, n); -- (*mangled) += n; -- } -- -- p = strpbrk (*mangled, cplus_markers); -- if (success && ((p == NULL) || (p == *mangled))) -- { -- if (p != NULL) -- { -- string_append (declp, SCOPE_STRING (work)); -- (*mangled)++; -- } -- } -- else -- { -- success = 0; -- break; -- } -- } -- if (success) -- string_append (declp, " virtual table"); -- } -- else if ((*mangled)[0] == '_' -- && (strchr("0123456789Qt", (*mangled)[1]) != NULL) -- && (p = strpbrk (*mangled, cplus_markers)) != NULL) -- { -- /* static data member, "_3foo$varname" for example */ -- (*mangled)++; -- switch (**mangled) -- { -- case 'Q': -- case 'K': -- success = demangle_qualified (work, mangled, declp, 0, 1); -- break; -- case 't': -- success = demangle_template (work, mangled, declp, 0, 1, 1); -- break; -- default: -- n = consume_count (mangled); -- if (n < 0 || n > (long) strlen (*mangled)) -- { -- success = 0; -- break; -- } -- -- if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 -- && (*mangled)[9] == 'N' -- && (*mangled)[8] == (*mangled)[10] -- && strchr (cplus_markers, (*mangled)[8])) -- { -- /* A member of the anonymous namespace. There's information -- about what identifier or filename it was keyed to, but -- it's just there to make the mangled name unique; we just -- step over it. */ -- string_append (declp, "{anonymous}"); -- (*mangled) += n; -- -- /* Now p points to the marker before the N, so we need to -- update it to the first marker after what we consumed. */ -- p = strpbrk (*mangled, cplus_markers); -- break; -- } -- -- string_appendn (declp, *mangled, n); -- (*mangled) += n; -- } -- if (success && (p == *mangled)) -- { -- /* Consumed everything up to the cplus_marker, append the -- variable name. */ -- (*mangled)++; -- string_append (declp, SCOPE_STRING (work)); -- n = strlen (*mangled); -- string_appendn (declp, *mangled, n); -- (*mangled) += n; -- } -- else -- { -- success = 0; -- } -- } -- else if (strncmp (*mangled, "__thunk_", 8) == 0) -- { -- int delta; -- -- (*mangled) += 8; -- delta = consume_count (mangled); -- if (delta == -1) -- success = 0; -- else if (**mangled != '_') -- success = 0; -- else -- { -- char *method = internal_cplus_demangle (work, ++*mangled); -- -- if (method) -- { -- char buf[50]; -- sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); -- string_append (declp, buf); -- string_append (declp, method); -- free (method); -- n = strlen (*mangled); -- (*mangled) += n; -- } -- else -- { -- success = 0; -- } -- } -- } -- else if (strncmp (*mangled, "__t", 3) == 0 -- && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) -- { -- p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; -- (*mangled) += 4; -- switch (**mangled) -- { -- case 'Q': -- case 'K': -- success = demangle_qualified (work, mangled, declp, 0, 1); -- break; -- case 't': -- success = demangle_template (work, mangled, declp, 0, 1, 1); -- break; -- default: -- success = do_type (work, mangled, declp); -- break; -- } -- if (success && **mangled != '\0') -- success = 0; -- if (success) -- string_append (declp, p); -- } -- else -- { -- success = 0; -- } -- return (success); --} -- --static void --recursively_demangle(struct work_stuff *work, const char **mangled, -- string *result, int namelength) --{ -- char * recurse = (char *)NULL; -- char * recurse_dem = (char *)NULL; -- -- recurse = XNEWVEC (char, namelength + 1); -- memcpy (recurse, *mangled, namelength); -- recurse[namelength] = '\000'; -- -- recurse_dem = cplus_demangle (recurse, work->options); -- -- if (recurse_dem) -- { -- string_append (result, recurse_dem); -- free (recurse_dem); -- } -- else -- { -- string_appendn (result, *mangled, namelength); -- } -- free (recurse); -- *mangled += namelength; --} -- --/* -- --LOCAL FUNCTION -- -- arm_special -- special handling of ARM/lucid mangled strings -- --SYNOPSIS -- -- static int -- arm_special (const char **mangled, -- string *declp); -- -- --DESCRIPTION -- -- Process some special ARM style mangling forms that don't fit -- the normal pattern. For example: -- -- __vtbl__3foo (foo virtual table) -- __vtbl__3foo__3bar (bar::foo virtual table) -- -- */ -- --static int --arm_special (const char **mangled, string *declp) --{ -- int n; -- int success = 1; -- const char *scan; -- -- if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) -- { -- /* Found a ARM style virtual table, get past ARM_VTABLE_STRING -- and create the decl. Note that we consume the entire mangled -- input string, which means that demangle_signature has no work -- to do. */ -- scan = *mangled + ARM_VTABLE_STRLEN; -- while (*scan != '\0') /* first check it can be demangled */ -- { -- n = consume_count (&scan); -- if (n == -1) -- { -- return (0); /* no good */ -- } -- scan += n; -- if (scan[0] == '_' && scan[1] == '_') -- { -- scan += 2; -- } -- } -- (*mangled) += ARM_VTABLE_STRLEN; -- while (**mangled != '\0') -- { -- n = consume_count (mangled); -- if (n == -1 -- || n > (long) strlen (*mangled)) -- return 0; -- string_prependn (declp, *mangled, n); -- (*mangled) += n; -- if ((*mangled)[0] == '_' && (*mangled)[1] == '_') -- { -- string_prepend (declp, "::"); -- (*mangled) += 2; -- } -- } -- string_append (declp, " virtual table"); -- } -- else -- { -- success = 0; -- } -- return (success); --} -- --/* -- --LOCAL FUNCTION -- -- demangle_qualified -- demangle 'Q' qualified name strings -- --SYNOPSIS -- -- static int -- demangle_qualified (struct work_stuff *, const char *mangled, -- string *result, int isfuncname, int append); -- --DESCRIPTION -- -- Demangle a qualified name, such as "Q25Outer5Inner" which is -- the mangled form of "Outer::Inner". The demangled output is -- prepended or appended to the result string according to the -- state of the append flag. -- -- If isfuncname is nonzero, then the qualified name we are building -- is going to be used as a member function name, so if it is a -- constructor or destructor function, append an appropriate -- constructor or destructor name. I.E. for the above example, -- the result for use as a constructor is "Outer::Inner::Inner" -- and the result for use as a destructor is "Outer::Inner::~Inner". -- --BUGS -- -- Numeric conversion is ASCII dependent (FIXME). -- -- */ -- --static int --demangle_qualified (struct work_stuff *work, const char **mangled, -- string *result, int isfuncname, int append) --{ -- int qualifiers = 0; -- int success = 1; -- char num[2]; -- string temp; -- string last_name; -- int bindex = register_Btype (work); -- -- /* We only make use of ISFUNCNAME if the entity is a constructor or -- destructor. */ -- isfuncname = (isfuncname -- && ((work->constructor & 1) || (work->destructor & 1))); -- -- string_init (&temp); -- string_init (&last_name); -- -- if ((*mangled)[0] == 'K') -- { -- /* Squangling qualified name reuse */ -- int idx; -- (*mangled)++; -- idx = consume_count_with_underscores (mangled); -- if (idx == -1 || idx >= work -> numk) -- success = 0; -- else -- string_append (&temp, work -> ktypevec[idx]); -- } -- else -- switch ((*mangled)[1]) -- { -- case '_': -- /* GNU mangled name with more than 9 classes. The count is preceded -- by an underscore (to distinguish it from the <= 9 case) and followed -- by an underscore. */ -- (*mangled)++; -- qualifiers = consume_count_with_underscores (mangled); -- if (qualifiers == -1) -- success = 0; -- break; -- -- case '1': -- case '2': -- case '3': -- case '4': -- case '5': -- case '6': -- case '7': -- case '8': -- case '9': -- /* The count is in a single digit. */ -- num[0] = (*mangled)[1]; -- num[1] = '\0'; -- qualifiers = atoi (num); -- -- /* If there is an underscore after the digit, skip it. This is -- said to be for ARM-qualified names, but the ARM makes no -- mention of such an underscore. Perhaps cfront uses one. */ -- if ((*mangled)[2] == '_') -- { -- (*mangled)++; -- } -- (*mangled) += 2; -- break; -- -- case '0': -- default: -- success = 0; -- } -- -- if (!success) -- return success; -- -- /* Pick off the names and collect them in the temp buffer in the order -- in which they are found, separated by '::'. */ -- -- while (qualifiers-- > 0) -- { -- int remember_K = 1; -- string_clear (&last_name); -- -- if (*mangled[0] == '_') -- (*mangled)++; -- -- if (*mangled[0] == 't') -- { -- /* Here we always append to TEMP since we will want to use -- the template name without the template parameters as a -- constructor or destructor name. The appropriate -- (parameter-less) value is returned by demangle_template -- in LAST_NAME. We do not remember the template type here, -- in order to match the G++ mangling algorithm. */ -- success = demangle_template(work, mangled, &temp, -- &last_name, 1, 0); -- if (!success) -- break; -- } -- else if (*mangled[0] == 'K') -- { -- int idx; -- (*mangled)++; -- idx = consume_count_with_underscores (mangled); -- if (idx == -1 || idx >= work->numk) -- success = 0; -- else -- string_append (&temp, work->ktypevec[idx]); -- remember_K = 0; -- -- if (!success) break; -- } -- else -- { -- if (EDG_DEMANGLING) -- { -- int namelength; -- /* Now recursively demangle the qualifier -- * This is necessary to deal with templates in -- * mangling styles like EDG */ -- namelength = consume_count (mangled); -- if (namelength == -1) -- { -- success = 0; -- break; -- } -- recursively_demangle(work, mangled, &temp, namelength); -- } -- else -- { -- string_delete (&last_name); -- success = do_type (work, mangled, &last_name); -- if (!success) -- break; -- string_appends (&temp, &last_name); -- } -- } -- -- if (remember_K) -- remember_Ktype (work, temp.b, LEN_STRING (&temp)); -- -- if (qualifiers > 0) -- string_append (&temp, SCOPE_STRING (work)); -- } -- -- remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); -- -- /* If we are using the result as a function name, we need to append -- the appropriate '::' separated constructor or destructor name. -- We do this here because this is the most convenient place, where -- we already have a pointer to the name and the length of the name. */ -- -- if (isfuncname) -- { -- string_append (&temp, SCOPE_STRING (work)); -- if (work -> destructor & 1) -- string_append (&temp, "~"); -- string_appends (&temp, &last_name); -- } -- -- /* Now either prepend the temp buffer to the result, or append it, -- depending upon the state of the append flag. */ -- -- if (append) -- string_appends (result, &temp); -- else -- { -- if (!STRING_EMPTY (result)) -- string_append (&temp, SCOPE_STRING (work)); -- string_prepends (result, &temp); -- } -- -- string_delete (&last_name); -- string_delete (&temp); -- return (success); --} -- --/* -- --LOCAL FUNCTION -- -- get_count -- convert an ascii count to integer, consuming tokens -- --SYNOPSIS -- -- static int -- get_count (const char **type, int *count) -- --DESCRIPTION -- -- Assume that *type points at a count in a mangled name; set -- *count to its value, and set *type to the next character after -- the count. There are some weird rules in effect here. -- -- If *type does not point at a string of digits, return zero. -- -- If *type points at a string of digits followed by an -- underscore, set *count to their value as an integer, advance -- *type to point *after the underscore, and return 1. -- -- If *type points at a string of digits not followed by an -- underscore, consume only the first digit. Set *count to its -- value as an integer, leave *type pointing after that digit, -- and return 1. -- -- The excuse for this odd behavior: in the ARM and HP demangling -- styles, a type can be followed by a repeat count of the form -- `Nxy', where: -- -- `x' is a single digit specifying how many additional copies -- of the type to append to the argument list, and -- -- `y' is one or more digits, specifying the zero-based index of -- the first repeated argument in the list. Yes, as you're -- unmangling the name you can figure this out yourself, but -- it's there anyway. -- -- So, for example, in `bar__3fooFPiN51', the first argument is a -- pointer to an integer (`Pi'), and then the next five arguments -- are the same (`N5'), and the first repeat is the function's -- second argument (`1'). --*/ -- --static int --get_count (const char **type, int *count) --{ -- const char *p; -- int n; -- -- if (!ISDIGIT ((unsigned char)**type)) -- return (0); -- else -- { -- *count = **type - '0'; -- (*type)++; -- if (ISDIGIT ((unsigned char)**type)) -- { -- p = *type; -- n = *count; -- do -- { -- n *= 10; -- n += *p - '0'; -- p++; -- } -- while (ISDIGIT ((unsigned char)*p)); -- if (*p == '_') -- { -- *type = p + 1; -- *count = n; -- } -- } -- } -- return (1); --} -- --/* RESULT will be initialised here; it will be freed on failure. The -- value returned is really a type_kind_t. */ -- --static int --do_type (struct work_stuff *work, const char **mangled, string *result) --{ -- int n; -- int i; -- int is_proctypevec; -- int done; -- int success; -- string decl; -- const char *remembered_type; -- int type_quals; -- type_kind_t tk = tk_none; -- -- string_init (&decl); -- string_init (result); -- -- done = 0; -- success = 1; -- is_proctypevec = 0; -- while (success && !done) -- { -- int member; -- switch (**mangled) -- { -- -- /* A pointer type */ -- case 'P': -- case 'p': -- (*mangled)++; -- if (! (work -> options & DMGL_JAVA)) -- string_prepend (&decl, "*"); -- if (tk == tk_none) -- tk = tk_pointer; -- break; -- -- /* A reference type */ -- case 'R': -- (*mangled)++; -- string_prepend (&decl, "&"); -- if (tk == tk_none) -- tk = tk_reference; -- break; -- -- /* An rvalue reference type */ -- case 'O': -- (*mangled)++; -- string_prepend (&decl, "&&"); -- if (tk == tk_none) -- tk = tk_rvalue_reference; -- break; -- -- /* An array */ -- case 'A': -- { -- ++(*mangled); -- if (!STRING_EMPTY (&decl) -- && (decl.b[0] == '*' || decl.b[0] == '&')) -- { -- string_prepend (&decl, "("); -- string_append (&decl, ")"); -- } -- string_append (&decl, "["); -- if (**mangled != '_') -- success = demangle_template_value_parm (work, mangled, &decl, -- tk_integral); -- if (**mangled == '_') -- ++(*mangled); -- string_append (&decl, "]"); -- break; -- } -- -- /* A back reference to a previously seen type */ -- case 'T': -- (*mangled)++; -- if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes) -- { -- success = 0; -- } -- else -- for (i = 0; i < work->nproctypes; i++) -- if (work -> proctypevec [i] == n) -- success = 0; -- -- if (success) -- { -- is_proctypevec = 1; -- push_processed_type (work, n); -- remembered_type = work->typevec[n]; -- mangled = &remembered_type; -- } -- break; -- -- /* A function */ -- case 'F': -- (*mangled)++; -- if (!STRING_EMPTY (&decl) -- && (decl.b[0] == '*' || decl.b[0] == '&')) -- { -- string_prepend (&decl, "("); -- string_append (&decl, ")"); -- } -- /* After picking off the function args, we expect to either find the -- function return type (preceded by an '_') or the end of the -- string. */ -- if (!demangle_nested_args (work, mangled, &decl) -- || (**mangled != '_' && **mangled != '\0')) -- { -- success = 0; -- break; -- } -- if (success && (**mangled == '_')) -- (*mangled)++; -- break; -- -- case 'M': -- { -- type_quals = TYPE_UNQUALIFIED; -- -- member = **mangled == 'M'; -- (*mangled)++; -- -- string_append (&decl, ")"); -- -- /* We don't need to prepend `::' for a qualified name; -- demangle_qualified will do that for us. */ -- if (**mangled != 'Q') -- string_prepend (&decl, SCOPE_STRING (work)); -- -- if (ISDIGIT ((unsigned char)**mangled)) -- { -- n = consume_count (mangled); -- if (n == -1 -- || (int) strlen (*mangled) < n) -- { -- success = 0; -- break; -- } -- string_prependn (&decl, *mangled, n); -- *mangled += n; -- } -- else if (**mangled == 'X' || **mangled == 'Y') -- { -- string temp; -- do_type (work, mangled, &temp); -- string_prepends (&decl, &temp); -- string_delete (&temp); -- } -- else if (**mangled == 't') -- { -- string temp; -- string_init (&temp); -- success = demangle_template (work, mangled, &temp, -- NULL, 1, 1); -- if (success) -- { -- string_prependn (&decl, temp.b, temp.p - temp.b); -- string_delete (&temp); -- } -- else -- { -- string_delete (&temp); -- break; -- } -- } -- else if (**mangled == 'Q') -- { -- success = demangle_qualified (work, mangled, &decl, -- /*isfuncnam=*/0, -- /*append=*/0); -- if (!success) -- break; -- } -- else -- { -- success = 0; -- break; -- } -- -- string_prepend (&decl, "("); -- if (member) -- { -- switch (**mangled) -- { -- case 'C': -- case 'V': -- case 'u': -- type_quals |= code_for_qualifier (**mangled); -- (*mangled)++; -- break; -- -- default: -- break; -- } -- -- if (*(*mangled) != 'F') -- { -- success = 0; -- break; -- } -- (*mangled)++; -- } -- if ((member && !demangle_nested_args (work, mangled, &decl)) -- || **mangled != '_') -- { -- success = 0; -- break; -- } -- (*mangled)++; -- if (! PRINT_ANSI_QUALIFIERS) -- { -- break; -- } -- if (type_quals != TYPE_UNQUALIFIED) -- { -- APPEND_BLANK (&decl); -- string_append (&decl, qualifier_string (type_quals)); -- } -- break; -- } -- case 'G': -- (*mangled)++; -- break; -- -- case 'C': -- case 'V': -- case 'u': -- if (PRINT_ANSI_QUALIFIERS) -- { -- if (!STRING_EMPTY (&decl)) -- string_prepend (&decl, " "); -- -- string_prepend (&decl, demangle_qualifier (**mangled)); -- } -- (*mangled)++; -- break; -- /* -- } -- */ -- -- /* fall through */ -- default: -- done = 1; -- break; -- } -- } -- -- if (success) switch (**mangled) -- { -- /* A qualified name, such as "Outer::Inner". */ -- case 'Q': -- case 'K': -- { -- success = demangle_qualified (work, mangled, result, 0, 1); -- break; -- } -- -- /* A back reference to a previously seen squangled type */ -- case 'B': -- (*mangled)++; -- if (!get_count (mangled, &n) || n < 0 || n >= work -> numb) -- success = 0; -- else -- string_append (result, work->btypevec[n]); -- break; -- -- case 'X': -- case 'Y': -- /* A template parm. We substitute the corresponding argument. */ -- { -- int idx; -- -- (*mangled)++; -- idx = consume_count_with_underscores (mangled); -- -- if (idx == -1 -- || (work->tmpl_argvec && idx >= work->ntmpl_args) -- || consume_count_with_underscores (mangled) == -1) -- { -- success = 0; -- break; -- } -- -- if (work->tmpl_argvec) -- string_append (result, work->tmpl_argvec[idx]); -- else -- string_append_template_idx (result, idx); -- -- success = 1; -- } -- break; -- -- default: -- success = demangle_fund_type (work, mangled, result); -- if (tk == tk_none) -- tk = (type_kind_t) success; -- break; -- } -- -- if (success) -- { -- if (!STRING_EMPTY (&decl)) -- { -- string_append (result, " "); -- string_appends (result, &decl); -- } -- } -- else -- string_delete (result); -- string_delete (&decl); -- -- if (is_proctypevec) -- pop_processed_type (work); -- -- if (success) -- /* Assume an integral type, if we're not sure. */ -- return (int) ((tk == tk_none) ? tk_integral : tk); -- else -- return 0; --} -- --/* Given a pointer to a type string that represents a fundamental type -- argument (int, long, unsigned int, etc) in TYPE, a pointer to the -- string in which the demangled output is being built in RESULT, and -- the WORK structure, decode the types and add them to the result. -- -- For example: -- -- "Ci" => "const int" -- "Sl" => "signed long" -- "CUs" => "const unsigned short" -- -- The value returned is really a type_kind_t. */ -- --static int --demangle_fund_type (struct work_stuff *work, -- const char **mangled, string *result) --{ -- int done = 0; -- int success = 1; -- char buf[INTBUF_SIZE + 5 /* 'int%u_t' */]; -- unsigned int dec = 0; -- type_kind_t tk = tk_integral; -- -- /* First pick off any type qualifiers. There can be more than one. */ -- -- while (!done) -- { -- switch (**mangled) -- { -- case 'C': -- case 'V': -- case 'u': -- if (PRINT_ANSI_QUALIFIERS) -- { -- if (!STRING_EMPTY (result)) -- string_prepend (result, " "); -- string_prepend (result, demangle_qualifier (**mangled)); -- } -- (*mangled)++; -- break; -- case 'U': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "unsigned"); -- break; -- case 'S': /* signed char only */ -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "signed"); -- break; -- case 'J': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "__complex"); -- break; -- default: -- done = 1; -- break; -- } -- } -- -- /* Now pick off the fundamental type. There can be only one. */ -- -- switch (**mangled) -- { -- case '\0': -- case '_': -- break; -- case 'v': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "void"); -- break; -- case 'x': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "long long"); -- break; -- case 'l': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "long"); -- break; -- case 'i': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "int"); -- break; -- case 's': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "short"); -- break; -- case 'b': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "bool"); -- tk = tk_bool; -- break; -- case 'c': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "char"); -- tk = tk_char; -- break; -- case 'w': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "wchar_t"); -- tk = tk_char; -- break; -- case 'r': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "long double"); -- tk = tk_real; -- break; -- case 'd': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "double"); -- tk = tk_real; -- break; -- case 'f': -- (*mangled)++; -- APPEND_BLANK (result); -- string_append (result, "float"); -- tk = tk_real; -- break; -- case 'G': -- (*mangled)++; -- if (!ISDIGIT ((unsigned char)**mangled)) -- { -- success = 0; -- break; -- } -- /* fall through */ -- case 'I': -- (*mangled)++; -- if (**mangled == '_') -- { -- int i; -- (*mangled)++; -- for (i = 0; -- i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; -- (*mangled)++, i++) -- buf[i] = **mangled; -- if (**mangled != '_') -- { -- success = 0; -- break; -- } -- buf[i] = '\0'; -- (*mangled)++; -- } -- else -- { -- strncpy (buf, *mangled, 2); -- buf[2] = '\0'; -- *mangled += min (strlen (*mangled), 2); -- } -- sscanf (buf, "%x", &dec); -- sprintf (buf, "int%u_t", dec); -- APPEND_BLANK (result); -- string_append (result, buf); -- break; -- -- /* fall through */ -- /* An explicit type, such as "6mytype" or "7integer" */ -- case '0': -- case '1': -- case '2': -- case '3': -- case '4': -- case '5': -- case '6': -- case '7': -- case '8': -- case '9': -- { -- int bindex = register_Btype (work); -- string btype; -- string_init (&btype); -- if (demangle_class_name (work, mangled, &btype)) { -- remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); -- APPEND_BLANK (result); -- string_appends (result, &btype); -- } -- else -- success = 0; -- string_delete (&btype); -- break; -- } -- case 't': -- { -- string btype; -- string_init (&btype); -- success = demangle_template (work, mangled, &btype, 0, 1, 1); -- string_appends (result, &btype); -- string_delete (&btype); -- break; -- } -- default: -- success = 0; -- break; -- } -- -- return success ? ((int) tk) : 0; --} -- -- --/* Handle a template's value parameter for HP aCC (extension from ARM) -- **mangled points to 'S' or 'U' */ -- --static int --do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED, -- const char **mangled, string *result) --{ -- int unsigned_const; -- -- if (**mangled != 'U' && **mangled != 'S') -- return 0; -- -- unsigned_const = (**mangled == 'U'); -- -- (*mangled)++; -- -- switch (**mangled) -- { -- case 'N': -- string_append (result, "-"); -- /* fall through */ -- case 'P': -- (*mangled)++; -- break; -- case 'M': -- /* special case for -2^31 */ -- string_append (result, "-2147483648"); -- (*mangled)++; -- return 1; -- default: -- return 0; -- } -- -- /* We have to be looking at an integer now */ -- if (!(ISDIGIT ((unsigned char)**mangled))) -- return 0; -- -- /* We only deal with integral values for template -- parameters -- so it's OK to look only for digits */ -- while (ISDIGIT ((unsigned char)**mangled)) -- { -- char_str[0] = **mangled; -- string_append (result, char_str); -- (*mangled)++; -- } -- -- if (unsigned_const) -- string_append (result, "U"); -- -- /* FIXME? Some day we may have 64-bit (or larger :-) ) constants -- with L or LL suffixes. pai/1997-09-03 */ -- -- return 1; /* success */ --} -- --/* Handle a template's literal parameter for HP aCC (extension from ARM) -- **mangled is pointing to the 'A' */ -- --static int --do_hpacc_template_literal (struct work_stuff *work, const char **mangled, -- string *result) --{ -- int literal_len = 0; -- char * recurse; -- char * recurse_dem; -- -- if (**mangled != 'A') -- return 0; -- -- (*mangled)++; -- -- literal_len = consume_count (mangled); -- -- if (literal_len <= 0 -- || literal_len > (long) strlen (*mangled)) -- return 0; -- -- /* Literal parameters are names of arrays, functions, etc. and the -- canonical representation uses the address operator */ -- string_append (result, "&"); -- -- /* Now recursively demangle the literal name */ -- recurse = XNEWVEC (char, literal_len + 1); -- memcpy (recurse, *mangled, literal_len); -- recurse[literal_len] = '\000'; -- -- recurse_dem = cplus_demangle (recurse, work->options); -- -- if (recurse_dem) -- { -- string_append (result, recurse_dem); -- free (recurse_dem); -- } -- else -- { -- string_appendn (result, *mangled, literal_len); -- } -- (*mangled) += literal_len; -- free (recurse); -- -- return 1; --} -- --static int --snarf_numeric_literal (const char **args, string *arg) --{ -- if (**args == '-') -- { -- char_str[0] = '-'; -- string_append (arg, char_str); -- (*args)++; -- } -- else if (**args == '+') -- (*args)++; -- -- if (!ISDIGIT ((unsigned char)**args)) -- return 0; -- -- while (ISDIGIT ((unsigned char)**args)) -- { -- char_str[0] = **args; -- string_append (arg, char_str); -- (*args)++; -- } -- -- return 1; --} -- --/* Demangle the next argument, given by MANGLED into RESULT, which -- *should be an uninitialized* string. It will be initialized here, -- and free'd should anything go wrong. */ -- --static int --do_arg (struct work_stuff *work, const char **mangled, string *result) --{ -- /* Remember where we started so that we can record the type, for -- non-squangling type remembering. */ -- const char *start = *mangled; -- -- string_init (result); -- -- if (work->nrepeats > 0) -- { -- --work->nrepeats; -- -- if (work->previous_argument == 0) -- return 0; -- -- /* We want to reissue the previous type in this argument list. */ -- string_appends (result, work->previous_argument); -- return 1; -- } -- -- if (**mangled == 'n') -- { -- /* A squangling-style repeat. */ -- (*mangled)++; -- work->nrepeats = consume_count(mangled); -- -- if (work->nrepeats <= 0) -- /* This was not a repeat count after all. */ -- return 0; -- -- if (work->nrepeats > 9) -- { -- if (**mangled != '_') -- /* The repeat count should be followed by an '_' in this -- case. */ -- return 0; -- else -- (*mangled)++; -- } -- -- /* Now, the repeat is all set up. */ -- return do_arg (work, mangled, result); -- } -- -- /* Save the result in WORK->previous_argument so that we can find it -- if it's repeated. Note that saving START is not good enough: we -- do not want to add additional types to the back-referenceable -- type vector when processing a repeated type. */ -- if (work->previous_argument) -- string_delete (work->previous_argument); -- else -- work->previous_argument = XNEW (string); -- -- if (!do_type (work, mangled, work->previous_argument)) -- return 0; -- -- string_appends (result, work->previous_argument); -- -- remember_type (work, start, *mangled - start); -- return 1; --} -- --static void --push_processed_type (struct work_stuff *work, int typevec_index) --{ -- if (work->nproctypes >= work->proctypevec_size) -- { -- if (!work->proctypevec_size) -- { -- work->proctypevec_size = 4; -- work->proctypevec = XNEWVEC (int, work->proctypevec_size); -- } -- else -- { -- if (work->proctypevec_size < 16) -- /* Double when small. */ -- work->proctypevec_size *= 2; -- else -- { -- /* Grow slower when large. */ -- if (work->proctypevec_size > (INT_MAX / 3) * 2) -- xmalloc_failed (INT_MAX); -- work->proctypevec_size = (work->proctypevec_size * 3 / 2); -- } -- work->proctypevec -- = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size); -- } -- } -- work->proctypevec [work->nproctypes++] = typevec_index; --} -- --static void --pop_processed_type (struct work_stuff *work) --{ -- work->nproctypes--; --} -- --static void --remember_type (struct work_stuff *work, const char *start, int len) --{ -- char *tem; -- -- if (work->forgetting_types) -- return; -- -- if (work -> ntypes >= work -> typevec_size) -- { -- if (work -> typevec_size == 0) -- { -- work -> typevec_size = 3; -- work -> typevec = XNEWVEC (char *, work->typevec_size); -- } -- else -- { -- if (work -> typevec_size > INT_MAX / 2) -- xmalloc_failed (INT_MAX); -- work -> typevec_size *= 2; -- work -> typevec -- = XRESIZEVEC (char *, work->typevec, work->typevec_size); -- } -- } -- tem = XNEWVEC (char, len + 1); -- memcpy (tem, start, len); -- tem[len] = '\0'; -- work -> typevec[work -> ntypes++] = tem; --} -- -- --/* Remember a K type class qualifier. */ --static void --remember_Ktype (struct work_stuff *work, const char *start, int len) --{ -- char *tem; -- -- if (work -> numk >= work -> ksize) -- { -- if (work -> ksize == 0) -- { -- work -> ksize = 5; -- work -> ktypevec = XNEWVEC (char *, work->ksize); -- } -- else -- { -- if (work -> ksize > INT_MAX / 2) -- xmalloc_failed (INT_MAX); -- work -> ksize *= 2; -- work -> ktypevec -- = XRESIZEVEC (char *, work->ktypevec, work->ksize); -- } -- } -- tem = XNEWVEC (char, len + 1); -- memcpy (tem, start, len); -- tem[len] = '\0'; -- work -> ktypevec[work -> numk++] = tem; --} -- --/* Register a B code, and get an index for it. B codes are registered -- as they are seen, rather than as they are completed, so map > -- registers map > as B0, and temp as B1 */ -- --static int --register_Btype (struct work_stuff *work) --{ -- int ret; -- -- if (work -> numb >= work -> bsize) -- { -- if (work -> bsize == 0) -- { -- work -> bsize = 5; -- work -> btypevec = XNEWVEC (char *, work->bsize); -- } -- else -- { -- if (work -> bsize > INT_MAX / 2) -- xmalloc_failed (INT_MAX); -- work -> bsize *= 2; -- work -> btypevec -- = XRESIZEVEC (char *, work->btypevec, work->bsize); -- } -- } -- ret = work -> numb++; -- work -> btypevec[ret] = NULL; -- return(ret); --} -- --/* Store a value into a previously registered B code type. */ -- --static void --remember_Btype (struct work_stuff *work, const char *start, -- int len, int index) --{ -- char *tem; -- -- tem = XNEWVEC (char, len + 1); -- memcpy (tem, start, len); -- tem[len] = '\0'; -- work -> btypevec[index] = tem; --} -- --/* Lose all the info related to B and K type codes. */ --static void --forget_B_and_K_types (struct work_stuff *work) --{ -- int i; -- -- while (work -> numk > 0) -- { -- i = --(work -> numk); -- if (work -> ktypevec[i] != NULL) -- { -- free (work -> ktypevec[i]); -- work -> ktypevec[i] = NULL; -- } -- } -- -- while (work -> numb > 0) -- { -- i = --(work -> numb); -- if (work -> btypevec[i] != NULL) -- { -- free (work -> btypevec[i]); -- work -> btypevec[i] = NULL; -- } -- } --} --/* Forget the remembered types, but not the type vector itself. */ -- --static void --forget_types (struct work_stuff *work) --{ -- int i; -- -- while (work -> ntypes > 0) -- { -- i = --(work -> ntypes); -- if (work -> typevec[i] != NULL) -- { -- free (work -> typevec[i]); -- work -> typevec[i] = NULL; -- } -- } --} -- --/* Process the argument list part of the signature, after any class spec -- has been consumed, as well as the first 'F' character (if any). For -- example: -- -- "__als__3fooRT0" => process "RT0" -- "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" -- -- DECLP must be already initialised, usually non-empty. It won't be freed -- on failure. -- -- Note that g++ differs significantly from ARM and lucid style mangling -- with regards to references to previously seen types. For example, given -- the source fragment: -- -- class foo { -- public: -- foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); -- }; -- -- foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } -- void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } -- -- g++ produces the names: -- -- __3fooiRT0iT2iT2 -- foo__FiR3fooiT1iT1 -- -- while lcc (and presumably other ARM style compilers as well) produces: -- -- foo__FiR3fooT1T2T1T2 -- __ct__3fooFiR3fooT1T2T1T2 -- -- Note that g++ bases its type numbers starting at zero and counts all -- previously seen types, while lucid/ARM bases its type numbers starting -- at one and only considers types after it has seen the 'F' character -- indicating the start of the function args. For lucid/ARM style, we -- account for this difference by discarding any previously seen types when -- we see the 'F' character, and subtracting one from the type number -- reference. -- -- */ -- --static int --demangle_args (struct work_stuff *work, const char **mangled, -- string *declp) --{ -- string arg; -- int need_comma = 0; -- int r; -- int t; -- const char *tem; -- char temptype; -- -- if (PRINT_ARG_TYPES) -- { -- string_append (declp, "("); -- if (**mangled == '\0') -- { -- string_append (declp, "void"); -- } -- } -- -- while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') -- || work->nrepeats > 0) -- { -- if ((**mangled == 'N') || (**mangled == 'T')) -- { -- temptype = *(*mangled)++; -- -- if (temptype == 'N') -- { -- if (!get_count (mangled, &r)) -- { -- return (0); -- } -- } -- else -- { -- r = 1; -- } -- if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) -- { -- /* If we have 10 or more types we might have more than a 1 digit -- index so we'll have to consume the whole count here. This -- will lose if the next thing is a type name preceded by a -- count but it's impossible to demangle that case properly -- anyway. Eg if we already have 12 types is T12Pc "(..., type1, -- Pc, ...)" or "(..., type12, char *, ...)" */ -- if ((t = consume_count(mangled)) <= 0) -- { -- return (0); -- } -- } -- else -- { -- if (!get_count (mangled, &t)) -- { -- return (0); -- } -- } -- if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) -- { -- t--; -- } -- /* Validate the type index. Protect against illegal indices from -- malformed type strings. */ -- if ((t < 0) || (t >= work -> ntypes)) -- { -- return (0); -- } -- while (work->nrepeats > 0 || --r >= 0) -- { -- tem = work -> typevec[t]; -- if (need_comma && PRINT_ARG_TYPES) -- { -- string_append (declp, ", "); -- } -- push_processed_type (work, t); -- if (!do_arg (work, &tem, &arg)) -- { -- pop_processed_type (work); -- return (0); -- } -- pop_processed_type (work); -- if (PRINT_ARG_TYPES) -- { -- string_appends (declp, &arg); -- } -- string_delete (&arg); -- need_comma = 1; -- } -- } -- else -- { -- if (need_comma && PRINT_ARG_TYPES) -- string_append (declp, ", "); -- if (!do_arg (work, mangled, &arg)) -- return (0); -- if (PRINT_ARG_TYPES) -- string_appends (declp, &arg); -- string_delete (&arg); -- need_comma = 1; -- } -- } -- -- if (**mangled == 'e') -- { -- (*mangled)++; -- if (PRINT_ARG_TYPES) -- { -- if (need_comma) -- { -- string_append (declp, ","); -- } -- string_append (declp, "..."); -- } -- } -- -- if (PRINT_ARG_TYPES) -- { -- string_append (declp, ")"); -- } -- return (1); --} -- --/* Like demangle_args, but for demangling the argument lists of function -- and method pointers or references, not top-level declarations. */ -- --static int --demangle_nested_args (struct work_stuff *work, const char **mangled, -- string *declp) --{ -- string* saved_previous_argument; -- int result; -- int saved_nrepeats; -- -- /* The G++ name-mangling algorithm does not remember types on nested -- argument lists, unless -fsquangling is used, and in that case the -- type vector updated by remember_type is not used. So, we turn -- off remembering of types here. */ -- ++work->forgetting_types; -- -- /* For the repeat codes used with -fsquangling, we must keep track of -- the last argument. */ -- saved_previous_argument = work->previous_argument; -- saved_nrepeats = work->nrepeats; -- work->previous_argument = 0; -- work->nrepeats = 0; -- -- /* Actually demangle the arguments. */ -- result = demangle_args (work, mangled, declp); -- -- /* Restore the previous_argument field. */ -- if (work->previous_argument) -- { -- string_delete (work->previous_argument); -- free ((char *) work->previous_argument); -- } -- work->previous_argument = saved_previous_argument; -- --work->forgetting_types; -- work->nrepeats = saved_nrepeats; -- -- return result; --} -- --/* Returns 1 if a valid function name was found or 0 otherwise. */ -- --static int --demangle_function_name (struct work_stuff *work, const char **mangled, -- string *declp, const char *scan) --{ -- size_t i; -- string type; -- const char *tem; -- -- string_appendn (declp, (*mangled), scan - (*mangled)); -- string_need (declp, 1); -- *(declp -> p) = '\0'; -- -- /* Consume the function name, including the "__" separating the name -- from the signature. We are guaranteed that SCAN points to the -- separator. */ -- -- (*mangled) = scan + 2; -- /* We may be looking at an instantiation of a template function: -- foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a -- following _F marks the start of the function arguments. Handle -- the template arguments first. */ -- -- if (HP_DEMANGLING && (**mangled == 'X')) -- { -- demangle_arm_hp_template (work, mangled, 0, declp); -- /* This leaves MANGLED pointing to the 'F' marking func args */ -- } -- -- if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) -- { -- -- /* See if we have an ARM style constructor or destructor operator. -- If so, then just record it, clear the decl, and return. -- We can't build the actual constructor/destructor decl until later, -- when we recover the class name from the signature. */ -- -- if (strcmp (declp -> b, "__ct") == 0) -- { -- work -> constructor += 1; -- string_clear (declp); -- return 1; -- } -- else if (strcmp (declp -> b, "__dt") == 0) -- { -- work -> destructor += 1; -- string_clear (declp); -- return 1; -- } -- } -- -- if (declp->p - declp->b >= 3 -- && declp->b[0] == 'o' -- && declp->b[1] == 'p' -- && strchr (cplus_markers, declp->b[2]) != NULL) -- { -- /* see if it's an assignment expression */ -- if (declp->p - declp->b >= 10 /* op$assign_ */ -- && memcmp (declp->b + 3, "assign_", 7) == 0) -- { -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- int len = declp->p - declp->b - 10; -- if ((int) strlen (optable[i].in) == len -- && memcmp (optable[i].in, declp->b + 10, len) == 0) -- { -- string_clear (declp); -- string_append (declp, "operator"); -- string_append (declp, optable[i].out); -- string_append (declp, "="); -- break; -- } -- } -- } -- else -- { -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- int len = declp->p - declp->b - 3; -- if ((int) strlen (optable[i].in) == len -- && memcmp (optable[i].in, declp->b + 3, len) == 0) -- { -- string_clear (declp); -- string_append (declp, "operator"); -- string_append (declp, optable[i].out); -- break; -- } -- } -- } -- } -- else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 -- && strchr (cplus_markers, declp->b[4]) != NULL) -- { -- /* type conversion operator */ -- tem = declp->b + 5; -- if (do_type (work, &tem, &type)) -- { -- string_clear (declp); -- string_append (declp, "operator "); -- string_appends (declp, &type); -- string_delete (&type); -- } -- } -- else if (declp->b[0] == '_' && declp->b[1] == '_' -- && declp->b[2] == 'o' && declp->b[3] == 'p') -- { -- /* ANSI. */ -- /* type conversion operator. */ -- tem = declp->b + 4; -- if (do_type (work, &tem, &type)) -- { -- string_clear (declp); -- string_append (declp, "operator "); -- string_appends (declp, &type); -- string_delete (&type); -- } -- } -- else if (declp->b[0] == '_' && declp->b[1] == '_' -- && ISLOWER((unsigned char)declp->b[2]) -- && ISLOWER((unsigned char)declp->b[3])) -- { -- if (declp->b[4] == '\0') -- { -- /* Operator. */ -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- if (strlen (optable[i].in) == 2 -- && memcmp (optable[i].in, declp->b + 2, 2) == 0) -- { -- string_clear (declp); -- string_append (declp, "operator"); -- string_append (declp, optable[i].out); -- break; -- } -- } -- } -- else -- { -- if (declp->b[2] == 'a' && declp->b[5] == '\0') -- { -- /* Assignment. */ -- for (i = 0; i < ARRAY_SIZE (optable); i++) -- { -- if (strlen (optable[i].in) == 3 -- && memcmp (optable[i].in, declp->b + 2, 3) == 0) -- { -- string_clear (declp); -- string_append (declp, "operator"); -- string_append (declp, optable[i].out); -- break; -- } -- } -- } -- } -- } -- -- /* If a function name was obtained but it's not valid, we were not -- successful. */ -- if (LEN_STRING (declp) == 1 && declp->b[0] == '.') -- return 0; -- else -- return 1; --} -- --/* a mini string-handling package */ -- --static void --string_need (string *s, int n) --{ -- int tem; -- -- if (s->b == NULL) -- { -- if (n < 32) -- { -- n = 32; -- } -- s->p = s->b = XNEWVEC (char, n); -- s->e = s->b + n; -- } -- else if (s->e - s->p < n) -- { -- tem = s->p - s->b; -- if (n > INT_MAX / 2 - tem) -- xmalloc_failed (INT_MAX); -- n += tem; -- n *= 2; -- s->b = XRESIZEVEC (char, s->b, n); -- s->p = s->b + tem; -- s->e = s->b + n; -- } --} -- --static void --string_delete (string *s) --{ -- if (s->b != NULL) -- { -- free (s->b); -- s->b = s->e = s->p = NULL; -- } --} -- --static void --string_init (string *s) --{ -- s->b = s->p = s->e = NULL; --} -- --static void --string_clear (string *s) --{ -- s->p = s->b; --} -- --#if 0 -- --static int --string_empty (string *s) --{ -- return (s->b == s->p); --} -- --#endif -- --static void --string_append (string *p, const char *s) --{ -- int n; -- if (s == NULL || *s == '\0') -- return; -- n = strlen (s); -- string_need (p, n); -- memcpy (p->p, s, n); -- p->p += n; --} -- --static void --string_appends (string *p, string *s) --{ -- int n; -- -- if (s->b != s->p) -- { -- n = s->p - s->b; -- string_need (p, n); -- memcpy (p->p, s->b, n); -- p->p += n; -- } --} -- --static void --string_appendn (string *p, const char *s, int n) --{ -- if (n != 0) -- { -- string_need (p, n); -- memcpy (p->p, s, n); -- p->p += n; -- } --} -- --static void --string_prepend (string *p, const char *s) --{ -- if (s != NULL && *s != '\0') -- { -- string_prependn (p, s, strlen (s)); -- } --} -- --static void --string_prepends (string *p, string *s) --{ -- if (s->b != s->p) -- { -- string_prependn (p, s->b, s->p - s->b); -- } --} -- --static void --string_prependn (string *p, const char *s, int n) --{ -- char *q; -- -- if (n != 0) -- { -- string_need (p, n); -- for (q = p->p - 1; q >= p->b; q--) -- { -- q[n] = q[0]; -- } -- memcpy (p->b, s, n); -- p->p += n; -- } --} -- --static void --string_append_template_idx (string *s, int idx) --{ -- char buf[INTBUF_SIZE + 1 /* 'T' */]; -- sprintf(buf, "T%d", idx); -- string_append (s, buf); --} ---- libiberty/testsuite/demangle-expected -+++ libiberty/testsuite/demangle-expected -@@ -20,3315 +20,64 @@ - # A line starting with `#' is ignored. - # However, blank lines in this file are NOT ignored. - # ----format=gnu --no-params --AddAlignment__9ivTSolverUiP12ivInteractorP7ivTGlue --ivTSolver::AddAlignment(unsigned int, ivInteractor *, ivTGlue *) --ivTSolver::AddAlignment --# ----format=gnu --no-params --ArrowheadIntersects__9ArrowLineP9ArrowheadR6BoxObjP7Graphic --ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &, Graphic *) --ArrowLine::ArrowheadIntersects --# ----format=gnu --no-params --ArrowheadIntersects__9ArrowLineP9ArrowheadO6BoxObjP7Graphic --ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &&, Graphic *) --ArrowLine::ArrowheadIntersects --# ----format=gnu --no-params --AtEnd__13ivRubberGroup --ivRubberGroup::AtEnd(void) --ivRubberGroup::AtEnd --# ----format=gnu --no-params --BgFilter__9ivTSolverP12ivInteractor --ivTSolver::BgFilter(ivInteractor *) --ivTSolver::BgFilter --# ----format=gnu --no-params --Check__6UArrayi --UArray::Check(int) --UArray::Check --# ----format=gnu --no-params --CoreConstDecls__8TextCodeR7ostream --TextCode::CoreConstDecls(ostream &) --TextCode::CoreConstDecls --# ----format=gnu --no-params --CoreConstDecls__8TextCodeO7ostream --TextCode::CoreConstDecls(ostream &&) --TextCode::CoreConstDecls --# ----format=gnu --no-params --Detach__8StateVarP12StateVarView --StateVar::Detach(StateVarView *) --StateVar::Detach --# ----format=gnu --no-params --Done__9ComponentG8Iterator --Component::Done(Iterator) --Component::Done --# ----format=gnu --no-params --Effect__11RelateManipR7ivEvent --RelateManip::Effect(ivEvent &) --RelateManip::Effect --# ----format=gnu --no-params --Effect__11RelateManipO7ivEvent --RelateManip::Effect(ivEvent &&) --RelateManip::Effect --# ----format=gnu --no-params --FindFixed__FRP4CNetP4CNet --FindFixed(CNet *&, CNet *) --FindFixed --# ----format=gnu --no-params --FindFixed__FOP4CNetP4CNet --FindFixed(CNet *&&, CNet *) --FindFixed --# ----format=gnu --no-params --Fix48_abort__FR8twolongs --Fix48_abort(twolongs &) --Fix48_abort --# ----format=gnu --no-params --Fix48_abort__FO8twolongs --Fix48_abort(twolongs &&) --Fix48_abort --# ----format=gnu --no-params --GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveRiT2 --iv2_6_VScroller::GetBarInfo(ivPerspective *, int &, int &) --iv2_6_VScroller::GetBarInfo --# ----format=gnu --no-params --GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveOiT2 --iv2_6_VScroller::GetBarInfo(ivPerspective *, int &&, int &&) --iv2_6_VScroller::GetBarInfo --# ----format=gnu --no-params --GetBgColor__C9ivPainter --ivPainter::GetBgColor(void) const --ivPainter::GetBgColor --# ----format=gnu --no-params --InsertBody__15H_PullrightMenuii --H_PullrightMenu::InsertBody(int, int) --H_PullrightMenu::InsertBody --# ----format=gnu --no-params --InsertCharacter__9TextManipc --TextManip::InsertCharacter(char) --TextManip::InsertCharacter --# ----format=gnu --no-params --InsertToplevel__7ivWorldP12ivInteractorT1 --ivWorld::InsertToplevel(ivInteractor *, ivInteractor *) --ivWorld::InsertToplevel --# ----format=gnu --no-params --InsertToplevel__7ivWorldP12ivInteractorT1iiUi --ivWorld::InsertToplevel(ivInteractor *, ivInteractor *, int, int, unsigned int) --ivWorld::InsertToplevel --# ----format=gnu --no-params --IsAGroup__FP11GraphicViewP11GraphicComp --IsAGroup(GraphicView *, GraphicComp *) --IsAGroup --# ----format=gnu --no-params --IsA__10ButtonCodeUl --ButtonCode::IsA(unsigned long) --ButtonCode::IsA --# ----format=gnu --no-params --ReadName__FR7istreamPc --ReadName(istream &, char *) --ReadName --# ----format=gnu --no-params --Redraw__13StringBrowseriiii --StringBrowser::Redraw(int, int, int, int) --StringBrowser::Redraw --# ----format=gnu --no-params --Rotate__13ivTransformerf --ivTransformer::Rotate(float) --ivTransformer::Rotate --# ----format=gnu --no-params --Rotated__C13ivTransformerf --ivTransformer::Rotated(float) const --ivTransformer::Rotated --# ----format=gnu --no-params --Round__Ff --Round(float) --Round --# ----format=gnu --no-params --SetExport__16MemberSharedNameUi --MemberSharedName::SetExport(unsigned int) --MemberSharedName::SetExport --# ----format=gnu --no-params --Set__14ivControlState13ControlStatusUi --ivControlState::Set(ControlStatus, unsigned int) --ivControlState::Set --# ----format=gnu --no-params --Set__5DFacePcii --DFace::Set(char *, int, int) --DFace::Set --# ----format=gnu --no-params --VConvert__9ivTSolverP12ivInteractorRP8TElementT2 --ivTSolver::VConvert(ivInteractor *, TElement *&, TElement *&) --ivTSolver::VConvert --# ----format=gnu --no-params --VConvert__9ivTSolverP7ivTGlueRP8TElement --ivTSolver::VConvert(ivTGlue *, TElement *&) --ivTSolver::VConvert --# ----format=gnu --no-params --VOrder__9ivTSolverUiRP12ivInteractorT2 --ivTSolver::VOrder(unsigned int, ivInteractor *&, ivInteractor *&) --ivTSolver::VOrder --# ----format=gnu --no-params --_10PageButton$__both --PageButton::__both --PageButton::__both --# ----format=gnu --no-params --_3RNG$singleMantissa --RNG::singleMantissa --RNG::singleMantissa --# ----format=gnu --no-params --_5IComp$_release --IComp::_release --IComp::_release --# ----format=gnu --no-params --_$_10BitmapComp --BitmapComp::~BitmapComp(void) --BitmapComp::~BitmapComp --# ----format=gnu --no-params --_$_9__io_defs --__io_defs::~__io_defs(void) --__io_defs::~__io_defs --# ----format=gnu --no-params --_$_Q23foo3bar --foo::bar::~bar(void) --foo::bar::~bar --# ----format=gnu --no-params --_$_Q33foo3bar4bell --foo::bar::bell::~bell(void) --foo::bar::bell::~bell --# ----format=gnu --no-params --__10ivTelltaleiP7ivGlyph --ivTelltale::ivTelltale(int, ivGlyph *) --ivTelltale::ivTelltale --# ----format=gnu --no-params --__10ivViewportiP12ivInteractorUi --ivViewport::ivViewport(int, ivInteractor *, unsigned int) --ivViewport::ivViewport --# ----format=gnu --no-params --__10ostrstream --ostrstream::ostrstream(void) --ostrstream::ostrstream --# ----format=gnu --no-params --__10ostrstreamPcii --ostrstream::ostrstream(char *, int, int) --ostrstream::ostrstream --# ----format=gnu --no-params --__11BitmapTablei --BitmapTable::BitmapTable(int) --BitmapTable::BitmapTable --# ----format=gnu --no-params --__12ViewportCodeP12ViewportComp --ViewportCode::ViewportCode(ViewportComp *) --ViewportCode::ViewportCode --# ----format=gnu --no-params --__12iv2_6_Borderii --iv2_6_Border::iv2_6_Border(int, int) --iv2_6_Border::iv2_6_Border --# ----format=gnu --no-params --__12ivBreak_Listl --ivBreak_List::ivBreak_List(long) --ivBreak_List::ivBreak_List --# ----format=gnu --no-params --__14iv2_6_MenuItemiP12ivInteractor --iv2_6_MenuItem::iv2_6_MenuItem(int, ivInteractor *) --iv2_6_MenuItem::iv2_6_MenuItem --# ----format=gnu --no-params --__20DisplayList_IteratorR11DisplayList --DisplayList_Iterator::DisplayList_Iterator(DisplayList &) --DisplayList_Iterator::DisplayList_Iterator --# ----format=gnu --no-params --__3fooRT0 --foo::foo(foo &) --foo::foo --# ----format=gnu --no-params --__3fooiN31 --foo::foo(int, int, int, int) --foo::foo --# ----format=gnu --no-params --__3fooiRT0iT2iT2 --foo::foo(int, foo &, int, foo &, int, foo &) --foo::foo --# ----format=gnu --no-params --__6KeyMapPT0 --KeyMap::KeyMap(KeyMap *) --KeyMap::KeyMap --# ----format=gnu --no-params --__8ArrowCmdP6EditorUiUi --ArrowCmd::ArrowCmd(Editor *, unsigned int, unsigned int) --ArrowCmd::ArrowCmd --# ----format=gnu --no-params --__9F_EllipseiiiiP7Graphic --F_Ellipse::F_Ellipse(int, int, int, int, Graphic *) --F_Ellipse::F_Ellipse --# ----format=gnu --no-params --__9FrameDataP9FrameCompi --FrameData::FrameData(FrameComp *, int) --FrameData::FrameData --# ----format=gnu --no-params --__9HVGraphicP9CanvasVarP7Graphic --HVGraphic::HVGraphic(CanvasVar *, Graphic *) --HVGraphic::HVGraphic --# ----format=gnu --no-params --__Q23foo3bar --foo::bar::bar(void) --foo::bar::bar --# ----format=gnu --no-params --__Q33foo3bar4bell --foo::bar::bell::bell(void) --foo::bar::bell::bell --# ----format=gnu --no-params --__aa__3fooRT0 --foo::operator&&(foo &) --foo::operator&& --# ----format=gnu --no-params --__aad__3fooRT0 --foo::operator&=(foo &) --foo::operator&= --# ----format=gnu --no-params --__ad__3fooRT0 --foo::operator&(foo &) --foo::operator& --# ----format=gnu --no-params --__adv__3fooRT0 --foo::operator/=(foo &) --foo::operator/= --# ----format=gnu --no-params --__aer__3fooRT0 --foo::operator^=(foo &) --foo::operator^= --# ----format=gnu --no-params --__als__3fooRT0 --foo::operator<<=(foo &) --foo::operator<<= --# ----format=gnu --no-params --__amd__3fooRT0 --foo::operator%=(foo &) --foo::operator%= --# ----format=gnu --no-params --__ami__3fooRT0 --foo::operator-=(foo &) --foo::operator-= --# ----format=gnu --no-params --__aml__3FixRT0 --Fix::operator*=(Fix &) --Fix::operator*= --# ----format=gnu --no-params --__aml__5Fix16i --Fix16::operator*=(int) --Fix16::operator*= --# ----format=gnu --no-params --__aml__5Fix32RT0 --Fix32::operator*=(Fix32 &) --Fix32::operator*= --# ----format=gnu --no-params --__aor__3fooRT0 --foo::operator|=(foo &) --foo::operator|= --# ----format=gnu --no-params --__apl__3fooRT0 --foo::operator+=(foo &) --foo::operator+= --# ----format=gnu --no-params --__ars__3fooRT0 --foo::operator>>=(foo &) --foo::operator>>= --# ----format=gnu --no-params --__as__3fooRT0 --foo::operator=(foo &) --foo::operator= --# ----format=gnu --no-params --__cl__3fooRT0 --foo::operator()(foo &) --foo::operator() --# ----format=gnu --no-params --__cl__6Normal --Normal::operator()(void) --Normal::operator() --# ----format=gnu --no-params --__cl__6Stringii --String::operator()(int, int) --String::operator() --# ----format=gnu --no-params --__cm__3fooRT0 --foo::operator, (foo &) --foo::operator, --# ----format=gnu --no-params --__co__3foo --foo::operator~(void) --foo::operator~ --# ----format=gnu --no-params --__dl__3fooPv --foo::operator delete(void *) --foo::operator delete --# ----format=gnu --no-params --__dv__3fooRT0 --foo::operator/(foo &) --foo::operator/ --# ----format=gnu --no-params --__eq__3fooRT0 --foo::operator==(foo &) --foo::operator== --# ----format=gnu --no-params --__er__3fooRT0 --foo::operator^(foo &) --foo::operator^ --# ----format=gnu --no-params --__ge__3fooRT0 --foo::operator>=(foo &) --foo::operator>= --# ----format=gnu --no-params --__gt__3fooRT0 --foo::operator>(foo &) --foo::operator> --# ----format=gnu --no-params --__le__3fooRT0 --foo::operator<=(foo &) --foo::operator<= --# ----format=gnu --no-params --__ls__3fooRT0 --foo::operator<<(foo &) --foo::operator<< --# ----format=gnu --no-params --__ls__FR7ostreamPFR3ios_R3ios --operator<<(ostream &, ios &(*)(ios &)) --operator<< --# ----format=gnu --no-params --__ls__FR7ostreamR3Fix --operator<<(ostream &, Fix &) --operator<< --# ----format=gnu --no-params --__lt__3fooRT0 --foo::operator<(foo &) --foo::operator< --# ----format=gnu --no-params --__md__3fooRT0 --foo::operator%(foo &) --foo::operator% --# ----format=gnu --no-params --__mi__3fooRT0 --foo::operator-(foo &) --foo::operator- --# ----format=gnu --no-params --__ml__3fooRT0 --foo::operator*(foo &) --foo::operator* --# ----format=gnu --no-params --__mm__3fooi --foo::operator--(int) --foo::operator-- --# ----format=gnu --no-params --__ne__3fooRT0 --foo::operator!=(foo &) --foo::operator!= --# ----format=gnu --no-params --__nt__3foo --foo::operator!(void) --foo::operator! --# ----format=gnu --no-params --__nw__3fooi --foo::operator new(int) --foo::operator new --# ----format=gnu --no-params --__oo__3fooRT0 --foo::operator||(foo &) --foo::operator|| --# ----format=gnu --no-params --__opPc__3foo --foo::operator char *(void) --foo::operator char * --# ----format=gnu --no-params --__opi__3foo --foo::operator int(void) --foo::operator int --# ----format=gnu --no-params --__or__3fooRT0 --foo::operator|(foo &) --foo::operator| --# ----format=gnu --no-params --__pl__3fooRT0 --foo::operator+(foo &) --foo::operator+ --# ----format=gnu --no-params --__pp__3fooi --foo::operator++(int) --foo::operator++ --# ----format=gnu --no-params --__rf__3foo --foo::operator->(void) --foo::operator-> --# ----format=gnu --no-params --__rm__3fooRT0 --foo::operator->*(foo &) --foo::operator->* --# ----format=gnu --no-params --__rs__3fooRT0 --foo::operator>>(foo &) --foo::operator>> --# ----format=gnu --no-params --_new_Fix__FUs --_new_Fix(unsigned short) --_new_Fix --# ----format=gnu --no-params --_vt.foo --foo virtual table --foo virtual table --# ----format=gnu --no-params --_vt.foo.bar --foo::bar virtual table --foo::bar virtual table --# ----format=gnu --no-params --_vt$foo --foo virtual table --foo virtual table --# ----format=gnu --no-params --_vt$foo$bar --foo::bar virtual table --foo::bar virtual table --# ----format=gnu --no-params --append__7ivGlyphPT0 --ivGlyph::append(ivGlyph *) --ivGlyph::append --# ----format=gnu --no-params --clearok__FP7_win_sti --clearok(_win_st *, int) --clearok --# ----format=gnu --no-params --complexfunc2__FPFPc_i --complexfunc2(int (*)(char *)) --complexfunc2 --# ----format=gnu --no-params --complexfunc3__FPFPFPl_s_i --complexfunc3(int (*)(short (*)(long *))) --complexfunc3 --# ----format=gnu --no-params --complexfunc4__FPFPFPc_s_i --complexfunc4(int (*)(short (*)(char *))) --complexfunc4 --# ----format=gnu --no-params --complexfunc5__FPFPc_PFl_i --complexfunc5(int (*(*)(char *))(long)) --complexfunc5 --# ----format=gnu --no-params --complexfunc6__FPFPi_PFl_i --complexfunc6(int (*(*)(int *))(long)) --complexfunc6 --# ----format=gnu --no-params --complexfunc7__FPFPFPc_i_PFl_i --complexfunc7(int (*(*)(int (*)(char *)))(long)) --complexfunc7 --# ----format=gnu --no-params --foo__FiN30 --foo(int, int, int, int) --foo --# ----format=gnu --no-params --foo__FiR3fooiT1iT1 --foo(int, foo &, int, foo &, int, foo &) --foo --# ----format=gnu --no-params --foo___3barl --bar::foo_(long) --bar::foo_ --# ----format=gnu --no-params --insert__15ivClippingStacklRP8_XRegion --ivClippingStack::insert(long, _XRegion *&) --ivClippingStack::insert --# ----format=gnu --no-params --insert__16ChooserInfo_ListlR11ChooserInfo --ChooserInfo_List::insert(long, ChooserInfo &) --ChooserInfo_List::insert --# ----format=gnu --no-params --insert__17FontFamilyRepListlRP15ivFontFamilyRep --FontFamilyRepList::insert(long, ivFontFamilyRep *&) --FontFamilyRepList::insert --# ----format=gnu --no-params --leaveok__FP7_win_stc --leaveok(_win_st *, char) --leaveok --# ----format=gnu --no-params --left_mover__C7ivMFKitP12ivAdjustableP7ivStyle --ivMFKit::left_mover(ivAdjustable *, ivStyle *) const --ivMFKit::left_mover --# ----format=gnu --no-params --overload1arg__FSc --overload1arg(signed char) --overload1arg --# ----format=gnu --no-params --overload1arg__FUc --overload1arg(unsigned char) --overload1arg --# ----format=gnu --no-params --overload1arg__FUi --overload1arg(unsigned int) --overload1arg --# ----format=gnu --no-params --overload1arg__FUl --overload1arg(unsigned long) --overload1arg --# ----format=gnu --no-params --overload1arg__FUs --overload1arg(unsigned short) --overload1arg --# ----format=gnu --no-params --overload1arg__Fc --overload1arg(char) --overload1arg --# ----format=gnu --no-params --overload1arg__Fd --overload1arg(double) --overload1arg --# ----format=gnu --no-params --overload1arg__Ff --overload1arg(float) --overload1arg --# ----format=gnu --no-params --overload1arg__Fi --overload1arg(int) --overload1arg --# ----format=gnu --no-params --overload1arg__Fl --overload1arg(long) --overload1arg --# ----format=gnu --no-params --overload1arg__Fs --overload1arg(short) --overload1arg --# ----format=gnu --no-params --overload1arg__Fv --overload1arg(void) --overload1arg --# ----format=gnu --no-params --overloadargs__Fi --overloadargs(int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fii --overloadargs(int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiii --overloadargs(int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiii --overloadargs(int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiii --overloadargs(int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiii --overloadargs(int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiiii --overloadargs(int, int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiiiii --overloadargs(int, int, int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiiiiii --overloadargs(int, int, int, int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiiiiiii --overloadargs(int, int, int, int, int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --overloadargs__Fiiiiiiiiiii --overloadargs(int, int, int, int, int, int, int, int, int, int, int) --overloadargs --# ----format=gnu --no-params --poke__8ivRasterUlUlffff --ivRaster::poke(unsigned long, unsigned long, float, float, float, float) --ivRaster::poke --# ----format=gnu --no-params --polar__Fdd --polar(double, double) --polar --# ----format=gnu --no-params --scale__13ivTransformerff --ivTransformer::scale(float, float) --ivTransformer::scale --# ----format=gnu --no-params --sgetn__7filebufPci --filebuf::sgetn(char *, int) --filebuf::sgetn --# ----format=gnu --no-params --shift__FP5_FrepiT0 --shift(_Frep *, int, _Frep *) --shift --# ----format=gnu --no-params --test__C6BitSeti --BitSet::test(int) const --BitSet::test --# ----format=gnu --no-params --test__C6BitSetii --BitSet::test(int, int) const --BitSet::test --# ----format=gnu --no-params --text_source__8Documentl --Document::text_source(long) --Document::text_source --# ----format=gnu --no-params --variance__6Erlangd --Erlang::variance(double) --Erlang::variance --# ----format=gnu --no-params --view__14DocumentViewerP8ItemViewP11TabularItem --DocumentViewer::view(ItemView *, TabularItem *) --DocumentViewer::view --# ----format=gnu --no-params --xy_extents__11ivExtensionffff --ivExtension::xy_extents(float, float, float, float) --ivExtension::xy_extents --# ----format=gnu --no-params --zero__8osMemoryPvUi --osMemory::zero(void *, unsigned int) --osMemory::zero --# ----format=gnu --no-params --_2T4$N --T4::N --T4::N --# ----format=gnu --no-params --_Q22T42t1$N --T4::t1::N --T4::t1::N --# ----format=gnu --no-params --get__2T1 --T1::get(void) --T1::get --# ----format=gnu --no-params --get__Q22T11a --T1::a::get(void) --T1::a::get --# ----format=gnu --no-params --get__Q32T11a1b --T1::a::b::get(void) --T1::a::b::get --# ----format=gnu --no-params --get__Q42T11a1b1c --T1::a::b::c::get(void) --T1::a::b::c::get --# ----format=gnu --no-params --get__Q52T11a1b1c1d --T1::a::b::c::d::get(void) --T1::a::b::c::d::get --# ----format=gnu --no-params --put__2T1i --T1::put(int) --T1::put --# ----format=gnu --no-params --put__Q22T11ai --T1::a::put(int) --T1::a::put --# ----format=gnu --no-params --put__Q32T11a1bi --T1::a::b::put(int) --T1::a::b::put --# ----format=gnu --no-params --put__Q42T11a1b1ci --T1::a::b::c::put(int) --T1::a::b::c::put --# ----format=gnu --no-params --put__Q52T11a1b1c1di --T1::a::b::c::d::put(int) --T1::a::b::c::d::put --# ----format=gnu --no-params --bar__3fooPv --foo::bar(void *) --foo::bar --# ----format=gnu --no-params --bar__C3fooPv --foo::bar(void *) const --foo::bar --# ----format=gnu --no-params --__eq__3fooRT0 --foo::operator==(foo &) --foo::operator== --# ----format=gnu --no-params --__eq__C3fooR3foo --foo::operator==(foo &) const --foo::operator== --# ----format=gnu --no-params --elem__t6vector1Zdi --vector::elem(int) --vector::elem --# ----format=gnu --no-params --elem__t6vector1Zii --vector::elem(int) --vector::elem --# ----format=gnu --no-params --__t6vector1Zdi --vector::vector(int) --vector::vector --# ----format=gnu --no-params --__t6vector1Zii --vector::vector(int) --vector::vector --# ----format=gnu --no-params --_$_t6vector1Zdi --vector::~vector(int) --vector::~vector --# ----format=gnu --no-params --_$_t6vector1Zii --vector::~vector(int) --vector::~vector --# ----format=gnu --no-params --__nw__t2T11ZcUi --T1::operator new(unsigned int) --T1::operator new --# ----format=gnu --no-params --__nw__t2T11Z1tUi --T1::operator new(unsigned int) --T1::operator new --# ----format=gnu --no-params --__dl__t2T11ZcPv --T1::operator delete(void *) --T1::operator delete --# ----format=gnu --no-params --__dl__t2T11Z1tPv --T1::operator delete(void *) --T1::operator delete --# ----format=gnu --no-params --__t2T11Zci --T1::T1(int) --T1::T1 --# ----format=gnu --no-params --__t2T11Zc --T1::T1(void) --T1::T1 --# ----format=gnu --no-params --__t2T11Z1ti --T1::T1(int) --T1::T1 --# ----format=gnu --no-params --__t2T11Z1t --T1::T1(void) --T1::T1 --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity3Pix --List::Pix::Pix(void) --List::Pix::Pix --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity3PixPQ2t4List1Z10VHDLEntity7element --List::Pix::Pix(List::element *) --List::Pix::Pix --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity3PixRCQ2t4List1Z10VHDLEntity3Pix --List::Pix::Pix(List::Pix const &) --List::Pix::Pix --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity3PixOCQ2t4List1Z10VHDLEntity3Pix --List::Pix::Pix(List::Pix const &&) --List::Pix::Pix --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity7elementRC10VHDLEntityPT0 --List::element::element(VHDLEntity const &, List::element *) --List::element::element --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity7elementOC10VHDLEntityPT0 --List::element::element(VHDLEntity const &&, List::element *) --List::element::element --# ----format=gnu --no-params --__Q2t4List1Z10VHDLEntity7elementRCQ2t4List1Z10VHDLEntity7element --List::element::element(List::element const &) --List::element::element --# ----format=gnu --no-params --__cl__C11VHDLLibraryGt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --VHDLLibrary::operator()(PixX >) const --VHDLLibrary::operator() --# ----format=gnu --no-params --__cl__Ct4List1Z10VHDLEntityRCQ2t4List1Z10VHDLEntity3Pix --List::operator()(List::Pix const &) const --List::operator() --# ----format=gnu --no-params --__ne__FPvRCQ2t4List1Z10VHDLEntity3Pix --operator!=(void *, List::Pix const &) --operator!= --# ----format=gnu --no-params --__ne__FPvRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --operator!=(void *, PixX > const &) --operator!= --# ----format=gnu --no-params --__t4List1Z10VHDLEntityRCt4List1Z10VHDLEntity --List::List(List const &) --List::List --# ----format=gnu --no-params --__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --PixX >::PixX(void) --PixX >::PixX --# ----format=gnu --no-params --__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityP14VHDLLibraryRepGQ2t4List1Z10VHDLEntity3Pix --PixX >::PixX(VHDLLibraryRep *, List::Pix) --PixX >::PixX --# ----format=gnu --no-params --__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --PixX >::PixX(PixX > const &) --PixX >::PixX --# ----format=gnu --no-params --__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityOCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --PixX >::PixX(PixX > const &&) --PixX >::PixX --# ----format=gnu --no-params --nextE__C11VHDLLibraryRt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity --VHDLLibrary::nextE(PixX > &) const --VHDLLibrary::nextE --# ----format=gnu --no-params --next__Ct4List1Z10VHDLEntityRQ2t4List1Z10VHDLEntity3Pix --List::next(List::Pix &) const --List::next --# ----format=gnu --no-params --_GLOBAL_$D$set --global destructors keyed to set --global destructors keyed to set --# ----format=gnu --no-params --_GLOBAL_$I$set --global constructors keyed to set --global constructors keyed to set --# ----format=gnu --no-params --__as__t5ListS1ZUiRCt5ListS1ZUi --ListS::operator=(ListS const &) --ListS::operator= --# ----format=gnu --no-params --__cl__Ct5ListS1ZUiRCQ2t5ListS1ZUi3Vix --ListS::operator()(ListS::Vix const &) const --ListS::operator() --# ----format=gnu --no-params --__cl__Ct5SetLS1ZUiRCQ2t5SetLS1ZUi3Vix --SetLS::operator()(SetLS::Vix const &) const --SetLS::operator() --# ----format=gnu --no-params --__t10ListS_link1ZUiRCUiPT0 --ListS_link::ListS_link(unsigned int const &, ListS_link *) --ListS_link::ListS_link --# ----format=gnu --no-params --__t10ListS_link1ZUiRCt10ListS_link1ZUi --ListS_link::ListS_link(ListS_link const &) --ListS_link::ListS_link --# ----format=gnu --no-params --__t5ListS1ZUiRCt5ListS1ZUi --ListS::ListS(ListS const &) --ListS::ListS --# ----format=gnu --no-params --next__Ct5ListS1ZUiRQ2t5ListS1ZUi3Vix --ListS::next(ListS::Vix &) const --ListS::next --# ----format=gnu --no-params --__ne__FPvRCQ2t5SetLS1ZUi3Vix --operator!=(void *, SetLS::Vix const &) --operator!= --# ----format=gnu --no-params --__t8ListElem1Z5LabelRt4List1Z5Label --ListElem