aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime/gcc/attributes.d
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/libdruntime/gcc/attributes.d')
-rw-r--r--libphobos/libdruntime/gcc/attributes.d605
1 files changed, 605 insertions, 0 deletions
diff --git a/libphobos/libdruntime/gcc/attributes.d b/libphobos/libdruntime/gcc/attributes.d
new file mode 100644
index 0000000..58a4023
--- /dev/null
+++ b/libphobos/libdruntime/gcc/attributes.d
@@ -0,0 +1,605 @@
+// GNU D Compiler attribute support declarations.
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// 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.
+
+// 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
+// <http://www.gnu.org/licenses/>.
+
+module gcc.attributes;
+
+// Private helper templates.
+private struct Attribute(A...)
+{
+ A arguments;
+}
+
+private enum bool isStringValue(alias T) = is(typeof(T) == string);
+
+private enum bool isStringOrIntValue(alias T)
+ = is(typeof(T) == string) || is(typeof(T) == int);
+
+private template allSatisfy(alias F, T...)
+{
+ static if (T.length == 0)
+ enum allSatisfy = true;
+ else static if (T.length == 1)
+ enum allSatisfy = F!(T[0]);
+ else
+ {
+ enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2])
+ && allSatisfy!(F, T[$/2 .. $ ]);
+ }
+}
+
+/**
+ * Generic entrypoint for applying GCC attributes to a function or type.
+ * There is no type checking done, as well as no deprecation path for
+ * attributes removed from the compiler. So the recommendation is to use any
+ , of the other UDAs available unless it is a target-specific attribute.
+ *
+ * Function attributes introduced by the @attribute UDA are used in the
+ * declaration of a function, followed by an attribute name string and
+ * any arguments separated by commas enclosed in parentheses.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @attribute("regparm", 1) int func(int size);
+ * ---
+ */
+@system
+auto attribute(A...)(A arguments)
+ if (A.length > 0 && is(A[0] == string))
+{
+ return Attribute!A(arguments);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Supported common attributes exposed by GDC.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The `@alloc_size` attribute may be applied to a function that returns a
+ * pointer and takes at least one argument of an integer or enumerated type.
+ * It indicates that the returned pointer points to memory whose size is given
+ * by the function argument at `sizeArgIdx`, or by the product of the arguments
+ * at `sizeArgIdx` and `numArgIdx`. Meaningful sizes are positive values less
+ * than `ptrdiff_t.max`. Unless `zeroBasedNumbering` is true, argument
+ * numbering starts at one for ordinary functions, and at two for non-static
+ * member functions.
+ *
+ * If `numArgIdx` is less than `0`, it is taken to mean there is no argument
+ * specifying the element count.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @alloc_size(1) extern(C) void* malloc(size_t size);
+ * @alloc_size(3,2) extern(C) void* reallocarray(void *ptr, size_t nmemb,
+ * size_t size);
+ * @alloc_size(1,2) void* my_calloc(size_t element_size, size_t count,
+ * bool irrelevant);
+ * ---
+ */
+auto alloc_size(int sizeArgIdx)
+{
+ return attribute("alloc_size", sizeArgIdx);
+}
+
+/// ditto
+auto alloc_size(int sizeArgIdx, int numArgIdx)
+{
+ return attribute("alloc_size", sizeArgIdx, numArgIdx);
+}
+
+/// ditto
+auto alloc_size(int sizeArgIdx, int numArgIdx, bool zeroBasedNumbering)
+{
+ return attribute("alloc_size", sizeArgIdx, numArgIdx, zeroBasedNumbering);
+}
+
+auto alloc_size(A...)(A arguments)
+{
+ assert(false, "alloc_size attribute argument value is not an integer constant");
+}
+
+/**
+ * The `@always_inline` attribute inlines the function independent of any
+ * restrictions that otherwise apply to inlining. Failure to inline such a
+ * function is diagnosed as an error.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @always_inline int func();
+ * ---
+ */
+enum always_inline = attribute("always_inline");
+
+/**
+ * The `@cold` attribute on functions is used to inform the compiler that the
+ * function is unlikely to be executed. The function is optimized for size
+ * rather than speed and on many targets it is placed into a special subsection
+ * of the text section so all cold functions appear close together, improving
+ * code locality of non-cold parts of program. The paths leading to calls of
+ * cold functions within code are considered to be cold too.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @cold int func();
+ * ---
+ */
+enum cold = attribute("cold");
+
+/**
+ * The `@flatten` attribute is used to inform the compiler that every call
+ * inside this function should be inlined, if possible. Functions declared with
+ * attribute `@noinline` and similar are not inlined.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @flatten int func();
+ * ---
+ */
+enum flatten = attribute("flatten");
+
+/**
+ * The `@no_icf` attribute prevents a functions from being merged with another
+ * semantically equivalent function.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @no_icf int func();
+ * ---
+ */
+enum no_icf = attribute("no_icf");
+
+/**
+ * The `@noclone` attribute prevents a function from being considered for
+ * cloning - a mechanism that produces specialized copies of functions and
+ * which is (currently) performed by interprocedural constant propagation.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @noclone int func();
+ * ---
+ */
+enum noclone = attribute("noclone");
+
+/**
+ * The `@noinline` attribute prevents a function from being considered for
+ * inlining. If the function does not have side effects, there are
+ * optimizations other than inlining that cause function calls to be optimized
+ * away, although the function call is live. To keep such calls from being
+ * optimized away, put `asm { ""; }` in the called function, to serve as a
+ * special side effect.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @noinline int func();
+ * ---
+ */
+enum noinline = attribute("noinline");
+
+/**
+ * The `@noipa` attribute disables interprocedural optimizations between the
+ * function with this attribute and its callers, as if the body of the function
+ * is not available when optimizing callers and the callers are unavailable when
+ * optimizing the body. This attribute implies `@noinline`, `@noclone`, and
+ * `@no_icf` attributes. However, this attribute is not equivalent to a
+ * combination of other attributes, because its purpose is to suppress existing
+ * and future optimizations employing interprocedural analysis, including those
+ * that do not have an attribute suitable for disabling them individually.
+ *
+ * This attribute is supported mainly for the purpose of testing the compiler.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @noipa int func();
+ * ---
+ */
+enum noipa = attribute("noipa");
+
+/**
+ * The `@optimize` attribute is used to specify that a function is to be
+ * compiled with different optimization options than specified on the command
+ * line. Valid `arguments` are constant non-negative integers and strings.
+ * Multiple arguments can be provided, separated by commas to specify multiple
+ * options. Each numeric argument specifies an optimization level. Each string
+ * argument that begins with the letter O refers to an optimization option such
+ * as `-O0` or `-Os`. Other options are taken as suffixes to the `-f` prefix
+ * jointly forming the name of an optimization option.
+ *
+ * Not every optimization option that starts with the `-f` prefix specified by
+ * the attribute necessarily has an effect on the function. The `@optimize`
+ * attribute should be used for debugging purposes only. It is not suitable in
+ * production code.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @optimize(2) double fn0(double x);
+ * @optimize("2") double fn1(double x);
+ * @optimize("s") double fn2(double x);
+ * @optimize("Ofast") double fn3(double x);
+ * @optimize("-O2") double fn4(double x);
+ * @optimize("tree-vectorize") double fn5(double x);
+ * @optimize("-ftree-vectorize") double fn6(double x);
+ * @optimize("no-finite-math-only", 3) double fn7(double x);
+ * ---
+ */
+auto optimize(A...)(A arguments)
+ if (allSatisfy!(isStringOrIntValue, arguments))
+{
+ return attribute("optimize", arguments);
+}
+
+auto optimize(A...)(A arguments)
+ if (!allSatisfy!(isStringOrIntValue, arguments))
+{
+ assert(false, "optimize attribute argument not a string or integer constant");
+}
+
+/**
+ * The `@restrict` attribute specifies that a function parameter is to be
+ * restrict-qualified in the C99 sense of the term. The parameter needs to
+ * boil down to either a pointer or reference type, such as a D pointer,
+ * class reference, or a `ref` parameter.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * void func(@restrict ref const float[16] array);
+ * ---
+ */
+enum restrict = attribute("restrict");
+
+/**
+ * The `@section` attribute specifies that a function lives in a particular
+ * section. For when you need certain particular functions to appear in
+ * special sections.
+ *
+ * Some file formats do not support arbitrary sections so the section attribute
+ * is not available on all platforms. If you need to map the entire contents
+ * of a module to a particular section, consider using the facilities of the
+ * linker instead.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @section("bar") extern void func();
+ * ---
+ */
+auto section(string sectionName)
+{
+ return attribute("section", sectionName);
+}
+
+auto section(A...)(A arguments)
+{
+ assert(false, "section attribute argument not a string constant");
+}
+
+/**
+ * The `@symver` attribute creates a symbol version on ELF targets. The syntax
+ * of the string parameter is `name@nodename`. The `name` part of the parameter
+ * is the actual name of the symbol by which it will be externally referenced.
+ * The `nodename` portion should be the name of a node specified in the version
+ * script supplied to the linker when building a shared library. Versioned
+ * symbol must be defined and must be exported with default visibility.
+ *
+ * Finally if the parameter is `name@@nodename` then in addition to creating a
+ * symbol version (as if `name@nodename` was used) the version will be also used
+ * to resolve `name` by the linker.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @symver("foo@VERS_1") int foo_v1();
+ * ---
+ */
+auto symver(A...)(A arguments)
+ if (allSatisfy!(isStringValue, arguments))
+{
+ return attribute("symver", arguments);
+}
+
+auto symver(A...)(A arguments)
+ if (!allSatisfy!(isStringValue, arguments))
+{
+ assert(false, "symver attribute argument not a string constant");
+}
+
+/**
+ * The `@target` attribute is used to specify that a function is to be
+ * compiled with different target options than specified on the command line.
+ * One or more strings can be provided as arguments, separated by commas to
+ * specify multiple options. Each string consists of one or more
+ * comma-separated suffixes to the `-m` prefix jointly forming the name of a
+ * machine-dependent option.
+ *
+ * The target attribute can be used for instance to have a function compiled
+ * with a different ISA (instruction set architecture) than the default.
+ *
+ * The options supported are specific to each target.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @target("arch=core2") void core2_func();
+ * @target("sse3") void sse3_func();
+ * ---
+ */
+auto target(A...)(A arguments)
+ if (allSatisfy!(isStringValue, arguments))
+{
+ return attribute("target", arguments);
+}
+
+auto target(A...)(A arguments)
+ if (!allSatisfy!(isStringValue, arguments))
+{
+ assert(false, "target attribute argument not a string constant");
+}
+
+/**
+ * The `@target_clones` attribute is used to specify that a function be cloned
+ * into multiple versions compiled with different target `options` than
+ * specified on the command line. The supported options and restrictions are
+ * the same as for `@target` attribute.
+ *
+ * It also creates a resolver function that dynamically selects a clone suitable
+ * for current architecture. The resolver is created only if there is a usage
+ * of a function with `@target_clones` attribute.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @target_clones("sse4.1,avx,default") double func(double x);
+ * ---
+ */
+auto target_clones(A...)(A arguments)
+ if (allSatisfy!(isStringValue, arguments))
+{
+ return attribute("target_clones", arguments);
+}
+
+auto target_clones(A...)(A arguments)
+ if (!allSatisfy!(isStringValue, arguments))
+{
+ assert(false, "target attribute argument not a string constant");
+}
+
+/**
+ * The `@used` attribute, annotated to a function, means that code must be
+ * emitted for the function even if it appears that the function is not
+ * referenced. This is useful, for example, when the function is referenced
+ * only in inline assembly.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @used __gshared int var = 0x1000;
+ * ---
+ */
+enum used = attribute("used");
+
+/**
+ * The `@weak` attribute causes a declaration of an external symbol to be
+ * emitted as a weak symbol rather than a global. This is primarily useful in
+ * defining library functions that can be overridden in user code, though it can
+ * also be used with non-function declarations. The overriding symbol must have
+ * the same type as the weak symbol. In addition, if it designates a variable
+ * it must also have the same size and alignment as the weak symbol.
+ *
+ * Weak symbols are supported for ELF targets, and also for a.out targets when
+ * using the GNU assembler and linker.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @weak int func() { return 1; }
+ * ---
+ */
+enum weak = attribute("weak");
+
+/**
+ * The `@noplt` attribute is the counterpart to option `-fno-plt`. Calls to
+ * functions marked with this attribute in position-independent code do not use
+ * the PLT in position-independent code.
+ *
+ * In position-dependant code, a few targets also convert call to functions
+ * that are marked to not use the PLT to use the GOT instead.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @noplt int func();
+ *
+ * ---
+ */
+enum noplt = attribute("noplt");
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Attributes defined for compatibility with LDC.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Specifies that the function returns `null` or a pointer to at least a
+ * certain number of allocated bytes. `sizeArgIdx` and `numArgIdx` specify
+ * the 0-based index of the function arguments that should be used to calculate
+ * the number of bytes returned.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @allocSize(0) extern(C) void* malloc(size_t size);
+ * @allocSize(2,1) extern(C) void* reallocarray(void *ptr, size_t nmemb,
+ * size_t size);
+ * @allocSize(0,1) void* my_calloc(size_t element_size, size_t count,
+ * bool irrelevant);
+ * ---
+ */
+auto allocSize(int sizeArgIdx, int numArgIdx = int.min)
+{
+ return alloc_size(sizeArgIdx, numArgIdx, true);
+}
+
+auto allocSize(A...)(A arguments)
+{
+ assert(false, "allocSize attribute argument value is not an integer constant");
+}
+
+/**
+ * When applied to a global symbol, the compiler, assembler, and linker are
+ * required to treat the symbol as if there is a reference to the symbol that
+ * it cannot see (which is why they have to be named). For example, it
+ * prevents the deletion by the linker of an unreferenced symbol.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @assumeUsed __gshared int var = 0x1000;
+ * ---
+ */
+alias assumeUsed = used;
+
+/// This attribute has no effect.
+enum dynamicCompile = false;
+
+/// ditto
+enum dynamicCompileConst = false;
+
+/// ditto
+enum dynamicCompileEmit = false;
+
+/**
+ * Explicitly sets "fast-math" for a function, enabling aggressive math
+ * optimizations. These optimizations may dramatically change the outcome of
+ * floating point calculations (e.g. because of reassociation).
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @fastmath
+ * double dot(double[] a, double[] b) {
+ * double s = 0;
+ * foreach(size_t i; 0..a.length)
+ * {
+ * // will result in vectorized fused-multiply-add instructions
+ * s += a * b;
+ * }
+ * return s;
+ * }
+ * ---
+ */
+enum fastmath = optimize("Ofast");
+
+/**
+ * Adds GCC's "naked" attribute to a function, disabling function prologue /
+ * epilogue emission.
+ * Intended to be used in combination with basic `asm` statement. While using
+ * extended `asm` or a mixture of basic `asm` and D code may appear to work,
+ * they cannot be depended upon to work reliably and are not supported.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @naked void abort() {
+ * asm { "ud2"; }
+ * }
+ * ---
+ */
+enum naked = attribute("naked");
+
+/**
+ * Sets the optimization strategy for a function.
+ * Valid strategies are "none", "optsize", "minsize". The strategies are
+ * mutually exclusive.
+ *
+ * Example:
+ * ---
+ * import gcc.attributes;
+ *
+ * @optStrategy("none")
+ * int func() {
+ * return call();
+ * }
+ * ---
+ */
+auto optStrategy(string strategy)
+{
+ if (strategy == "none")
+ return optimize("O0");
+ else if (strategy == "optsize" || strategy == "minsize")
+ return optimize("Os");
+ else
+ {
+ assert(false, "unrecognized parameter `" ~ strategy
+ ~ "` for `gcc.attribute.optStrategy`");
+ }
+}
+
+auto optStrategy(A...)(A arguments)
+{
+ assert(false, "optStrategy attribute argument value is not a string constant");
+}
+
+/**
+ * When applied to a function, specifies that the function should be optimzed
+ * by Graphite, GCC's polyhedral optimizer. Useful for optimizing loops for
+ * data locality, vectorization and parallelism.
+ *
+ * Experimental!
+ *
+ * Only effective when GDC was built with ISL included.
+ */
+enum polly = optimize("loop-parallelize-all", "loop-nest-optimize");