summaryrefslogtreecommitdiff
path: root/lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h
diff options
context:
space:
mode:
authoralk3pInjection <webmaster@raspii.tech>2024-02-04 16:16:35 +0800
committeralk3pInjection <webmaster@raspii.tech>2024-02-04 16:16:35 +0800
commitabdaadbcae30fe0c9a66c7516798279fdfd97750 (patch)
tree00a54a6e25601e43876d03c1a4a12a749d4a914c /lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h
Import stripped Arm GNU Toolchain 13.2.Rel1HEADumineko
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads Change-Id: I7303388733328cd98ab9aa3c30236db67f2e9e9c
Diffstat (limited to 'lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h')
-rw-r--r--lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h289
1 files changed, 289 insertions, 0 deletions
diff --git a/lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h
new file mode 100644
index 0000000..e0c9cb3
--- /dev/null
+++ b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/opt-problem.h
@@ -0,0 +1,289 @@
+/* Rich information on why an optimization wasn't possible.
+ Copyright (C) 2018-2023 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_OPT_PROBLEM_H
+#define GCC_OPT_PROBLEM_H
+
+#include "diagnostic-core.h" /* for ATTRIBUTE_GCC_DIAG. */
+#include "optinfo.h" /* for optinfo. */
+
+/* This header declares a family of wrapper classes for tracking a
+ success/failure value, while optionally supporting propagating an
+ opt_problem * describing any failure back up the call stack.
+
+ For instance, at the deepest point of the callstack where the failure
+ happens, rather than:
+
+ if (!check_something ())
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "foo is unsupported.\n");
+ return false;
+ }
+ // [...more checks...]
+
+ // All checks passed:
+ return true;
+
+ we can capture the cause of the failure via:
+
+ if (!check_something ())
+ return opt_result::failure_at (stmt, "foo is unsupported");
+ // [...more checks...]
+
+ // All checks passed:
+ return opt_result::success ();
+
+ which effectively returns true or false, whilst recording any problem.
+
+ opt_result::success and opt_result::failure return opt_result values
+ which "looks like" true/false respectively, via operator bool().
+ If dump_enabled_p, then opt_result::failure also creates an opt_problem *,
+ capturing the pertinent data (here, "foo is unsupported " and "stmt").
+ If dumps are disabled, then opt_problem instances aren't
+ created, and it's equivalent to just returning a bool.
+
+ The opt_problem can be propagated via opt_result values back up
+ the call stack to where it makes most sense to the user.
+ For instance, rather than:
+
+ bool ok = try_something_that_might_fail ();
+ if (!ok)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "some message.\n");
+ return false;
+ }
+
+ we can replace the bool with an opt_result, so if dump_enabled_p, we
+ assume that if try_something_that_might_fail, an opt_problem * will be
+ created, and we can propagate it up the call chain:
+
+ opt_result ok = try_something_that_might_fail ();
+ if (!ok)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "some message.\n");
+ return ok; // propagating the opt_result
+ }
+
+ opt_result is an opt_wrapper<bool>, where opt_wrapper<T> is a base
+ class for wrapping a T, optionally propagating an opt_problem in
+ case of failure_at (when dumps are enabled). Similarly,
+ opt_pointer_wrapper<T> can be used to wrap pointer types (where non-NULL
+ signifies success, NULL signifies failure).
+
+ In all cases, opt_wrapper<T> acts as if the opt_problem were one of its
+ fields, but the opt_problem is actually stored in a global, so that when
+ compiled, an opt_wrapper<T> is effectively just a T, so that we're
+ still just passing e.g. a bool around; the opt_wrapper<T> classes
+ simply provide type-checking and an API to ensure that we provide
+ error-messages deep in the callstack at the places where problems
+ occur, and that we propagate them. This also avoids having
+ to manage the ownership of the opt_problem instances.
+
+ Using opt_result and opt_wrapper<T> documents the intent of the code
+ for the places where we represent success values, and allows the C++ type
+ system to track where the deepest points in the callstack are where we
+ need to emit the failure messages from. */
+
+/* A bundle of information about why an optimization failed (e.g.
+ vectorization), and the location in both the user's code and
+ in GCC itself where the problem occurred.
+
+ Instances are created by static member functions in opt_wrapper
+ subclasses, such as opt_result::failure.
+
+ Instances are only created when dump_enabled_p (). */
+
+class opt_problem
+{
+ public:
+ static opt_problem *get_singleton () { return s_the_problem; }
+
+ opt_problem (const dump_location_t &loc,
+ const char *fmt, va_list *ap)
+ ATTRIBUTE_GCC_DUMP_PRINTF (3, 0);
+
+ const dump_location_t &
+ get_dump_location () const { return m_optinfo.get_dump_location (); }
+
+ const optinfo & get_optinfo () const { return m_optinfo; }
+
+ void emit_and_clear ();
+
+ private:
+ optinfo m_optinfo;
+
+ static opt_problem *s_the_problem;
+};
+
+/* A base class for wrapper classes that track a success/failure value, while
+ optionally supporting propagating an opt_problem * describing any
+ failure back up the call stack. */
+
+template <typename T>
+class opt_wrapper
+{
+ public:
+ typedef T wrapped_t;
+
+ /* Be accessible as the wrapped type. */
+ operator wrapped_t () const { return m_result; }
+
+ /* No public ctor. */
+
+ wrapped_t get_result () const { return m_result; }
+ opt_problem *get_problem () const { return opt_problem::get_singleton (); }
+
+ protected:
+ opt_wrapper (wrapped_t result, opt_problem */*problem*/)
+ : m_result (result)
+ {
+ /* "problem" is ignored: although it looks like a field, we
+ actually just use the opt_problem singleton, so that
+ opt_wrapper<T> in memory is just a T. */
+ }
+
+ private:
+ wrapped_t m_result;
+};
+
+/* Subclass of opt_wrapper<T> for bool, where
+ - true signifies "success", and
+ - false signifies "failure"
+ whilst effectively propagating an opt_problem * describing any failure
+ back up the call stack. */
+
+class opt_result : public opt_wrapper <bool>
+{
+ public:
+ /* Generate a "success" value: a wrapper around "true". */
+
+ static opt_result success () { return opt_result (true, NULL); }
+
+ /* Generate a "failure" value: a wrapper around "false", and,
+ if dump_enabled_p, an opt_problem. */
+
+ static opt_result failure_at (const dump_location_t &loc,
+ const char *fmt, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (2, 3)
+ {
+ opt_problem *problem = NULL;
+ if (dump_enabled_p ())
+ {
+ va_list ap;
+ va_start (ap, fmt);
+ problem = new opt_problem (loc, fmt, &ap);
+ va_end (ap);
+ }
+ return opt_result (false, problem);
+ }
+
+ /* Given a failure wrapper of some other kind, make an opt_result failure
+ object, for propagating the opt_problem up the call stack. */
+
+ template <typename S>
+ static opt_result
+ propagate_failure (opt_wrapper <S> other)
+ {
+ return opt_result (false, other.get_problem ());
+ }
+
+ private:
+ /* Private ctor. Instances should be created by the success and failure
+ static member functions. */
+ opt_result (wrapped_t result, opt_problem *problem)
+ : opt_wrapper <bool> (result, problem)
+ {}
+};
+
+/* Subclass of opt_wrapper<T> where T is a pointer type, for tracking
+ success/failure, where:
+ - a non-NULL value signifies "success", and
+ - a NULL value signifies "failure",
+ whilst effectively propagating an opt_problem * describing any failure
+ back up the call stack. */
+
+template <typename PtrType_t>
+class opt_pointer_wrapper : public opt_wrapper <PtrType_t>
+{
+ public:
+ typedef PtrType_t wrapped_pointer_t;
+
+ /* Given a non-NULL pointer, make a success object wrapping it. */
+
+ static opt_pointer_wrapper <wrapped_pointer_t>
+ success (wrapped_pointer_t ptr)
+ {
+ return opt_pointer_wrapper <wrapped_pointer_t> (ptr, NULL);
+ }
+
+ /* Make a NULL pointer failure object, with the given message
+ (if dump_enabled_p). */
+
+ static opt_pointer_wrapper <wrapped_pointer_t>
+ failure_at (const dump_location_t &loc,
+ const char *fmt, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (2, 3)
+ {
+ opt_problem *problem = NULL;
+ if (dump_enabled_p ())
+ {
+ va_list ap;
+ va_start (ap, fmt);
+ problem = new opt_problem (loc, fmt, &ap);
+ va_end (ap);
+ }
+ return opt_pointer_wrapper <wrapped_pointer_t> (NULL, problem);
+ }
+
+ /* Given a failure wrapper of some other kind, make a NULL pointer
+ failure object, propagating the problem. */
+
+ template <typename S>
+ static opt_pointer_wrapper <wrapped_pointer_t>
+ propagate_failure (opt_wrapper <S> other)
+ {
+ return opt_pointer_wrapper <wrapped_pointer_t> (NULL,
+ other.get_problem ());
+ }
+
+ /* Support accessing the underlying pointer via ->. */
+
+ wrapped_pointer_t operator-> () const { return this->get_result (); }
+
+ private:
+ /* Private ctor. Instances should be built using the static member
+ functions "success" and "failure". */
+ opt_pointer_wrapper (wrapped_pointer_t result, opt_problem *problem)
+ : opt_wrapper<PtrType_t> (result, problem)
+ {}
+};
+
+/* A typedef for wrapping "tree" so that NULL_TREE can carry an
+ opt_problem describing the failure (if dump_enabled_p). */
+
+typedef opt_pointer_wrapper<tree> opt_tree;
+
+#endif /* #ifndef GCC_OPT_PROBLEM_H */