diff options
Diffstat (limited to 'libphobos/libdruntime/gcc/attributes.d')
-rw-r--r-- | libphobos/libdruntime/gcc/attributes.d | 605 |
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"); |