1 // GNU D Compiler attribute support declarations.
2 // Copyright (C) 2021-2022 Free Software Foundation, Inc.
4 // GCC is free software; you can redistribute it and/or modify it under
5 // the terms of the GNU General Public License as published by the Free
6 // Software Foundation; either version 3, or (at your option) any later
9 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
10 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 // Under Section 7 of GPL version 3, you are granted additional
15 // permissions described in the GCC Runtime Library Exception, version
16 // 3.1, as published by the Free Software Foundation.
18 // You should have received a copy of the GNU General Public License and
19 // a copy of the GCC Runtime Library Exception along with this program;
20 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
21 // <http://www.gnu.org/licenses/>.
23 module gcc.attributes;
25 // Private helper templates.
26 private struct Attribute(A...)
31 private enum bool isStringValue(alias T) = is(typeof(T) == string);
33 private enum bool isStringOrIntValue(alias T)
34 = is(typeof(T) == string) || is(typeof(T) == int);
36 private template allSatisfy(alias F, T...)
38 static if (T.length == 0)
39 enum allSatisfy = true;
40 else static if (T.length == 1)
41 enum allSatisfy = F!(T[0]);
44 enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2])
45 && allSatisfy!(F, T[$/2 .. $ ]);
50 * Generic entrypoint for applying GCC attributes to a function or type.
51 * There is no type checking done, as well as no deprecation path for
52 * attributes removed from the compiler. So the recommendation is to use any
53 , of the other UDAs available unless it is a target-specific attribute.
55 * Function attributes introduced by the @attribute UDA are used in the
56 * declaration of a function, followed by an attribute name string and
57 * any arguments separated by commas enclosed in parentheses.
61 * import gcc.attributes;
63 * @attribute("regparm", 1) int func(int size);
67 auto attribute(A...)(A arguments)
68 if (A.length > 0 && is(A[0] == string))
70 return Attribute!A(arguments);
74 ///////////////////////////////////////////////////////////////////////////////
76 // Supported common attributes exposed by GDC.
78 ///////////////////////////////////////////////////////////////////////////////
81 * The `@alloc_size` attribute may be applied to a function that returns a
82 * pointer and takes at least one argument of an integer or enumerated type.
83 * It indicates that the returned pointer points to memory whose size is given
84 * by the function argument at `sizeArgIdx`, or by the product of the arguments
85 * at `sizeArgIdx` and `numArgIdx`. Meaningful sizes are positive values less
86 * than `ptrdiff_t.max`. Unless `zeroBasedNumbering` is true, argument
87 * numbering starts at one for ordinary functions, and at two for non-static
90 * If `numArgIdx` is less than `0`, it is taken to mean there is no argument
91 * specifying the element count.
95 * import gcc.attributes;
97 * @alloc_size(1) extern(C) void* malloc(size_t size);
98 * @alloc_size(3,2) extern(C) void* reallocarray(void *ptr, size_t nmemb,
100 * @alloc_size(1,2) void* my_calloc(size_t element_size, size_t count,
104 auto alloc_size(int sizeArgIdx)
106 return attribute("alloc_size", sizeArgIdx);
110 auto alloc_size(int sizeArgIdx, int numArgIdx)
112 return attribute("alloc_size", sizeArgIdx, numArgIdx);
116 auto alloc_size(int sizeArgIdx, int numArgIdx, bool zeroBasedNumbering)
118 return attribute("alloc_size", sizeArgIdx, numArgIdx, zeroBasedNumbering);
121 auto alloc_size(A...)(A arguments)
123 assert(false, "alloc_size attribute argument value is not an integer constant");
127 * The `@always_inline` attribute inlines the function independent of any
128 * restrictions that otherwise apply to inlining. Failure to inline such a
129 * function is diagnosed as an error.
133 * import gcc.attributes;
135 * @always_inline int func();
138 enum always_inline = attribute("always_inline");
141 * The `@cold` attribute on functions is used to inform the compiler that the
142 * function is unlikely to be executed. The function is optimized for size
143 * rather than speed and on many targets it is placed into a special subsection
144 * of the text section so all cold functions appear close together, improving
145 * code locality of non-cold parts of program. The paths leading to calls of
146 * cold functions within code are considered to be cold too.
150 * import gcc.attributes;
155 enum cold = attribute("cold");
158 * The `@flatten` attribute is used to inform the compiler that every call
159 * inside this function should be inlined, if possible. Functions declared with
160 * attribute `@noinline` and similar are not inlined.
164 * import gcc.attributes;
166 * @flatten int func();
169 enum flatten = attribute("flatten");
172 * The `@no_icf` attribute prevents a functions from being merged with another
173 * semantically equivalent function.
177 * import gcc.attributes;
179 * @no_icf int func();
182 enum no_icf = attribute("no_icf");
185 * The `@noclone` attribute prevents a function from being considered for
186 * cloning - a mechanism that produces specialized copies of functions and
187 * which is (currently) performed by interprocedural constant propagation.
191 * import gcc.attributes;
193 * @noclone int func();
196 enum noclone = attribute("noclone");
199 * The `@noinline` attribute prevents a function from being considered for
200 * inlining. If the function does not have side effects, there are
201 * optimizations other than inlining that cause function calls to be optimized
202 * away, although the function call is live. To keep such calls from being
203 * optimized away, put `asm { ""; }` in the called function, to serve as a
204 * special side effect.
208 * import gcc.attributes;
210 * @noinline int func();
213 enum noinline = attribute("noinline");
216 * The `@noipa` attribute disables interprocedural optimizations between the
217 * function with this attribute and its callers, as if the body of the function
218 * is not available when optimizing callers and the callers are unavailable when
219 * optimizing the body. This attribute implies `@noinline`, `@noclone`, and
220 * `@no_icf` attributes. However, this attribute is not equivalent to a
221 * combination of other attributes, because its purpose is to suppress existing
222 * and future optimizations employing interprocedural analysis, including those
223 * that do not have an attribute suitable for disabling them individually.
225 * This attribute is supported mainly for the purpose of testing the compiler.
229 * import gcc.attributes;
234 enum noipa = attribute("noipa");
237 * The `@optimize` attribute is used to specify that a function is to be
238 * compiled with different optimization options than specified on the command
239 * line. Valid `arguments` are constant non-negative integers and strings.
240 * Multiple arguments can be provided, separated by commas to specify multiple
241 * options. Each numeric argument specifies an optimization level. Each string
242 * argument that begins with the letter O refers to an optimization option such
243 * as `-O0` or `-Os`. Other options are taken as suffixes to the `-f` prefix
244 * jointly forming the name of an optimization option.
246 * Not every optimization option that starts with the `-f` prefix specified by
247 * the attribute necessarily has an effect on the function. The `@optimize`
248 * attribute should be used for debugging purposes only. It is not suitable in
253 * import gcc.attributes;
255 * @optimize(2) double fn0(double x);
256 * @optimize("2") double fn1(double x);
257 * @optimize("s") double fn2(double x);
258 * @optimize("Ofast") double fn3(double x);
259 * @optimize("-O2") double fn4(double x);
260 * @optimize("tree-vectorize") double fn5(double x);
261 * @optimize("-ftree-vectorize") double fn6(double x);
262 * @optimize("no-finite-math-only", 3) double fn7(double x);
265 auto optimize(A...)(A arguments)
266 if (allSatisfy!(isStringOrIntValue, arguments))
268 return attribute("optimize", arguments);
271 auto optimize(A...)(A arguments)
272 if (!allSatisfy!(isStringOrIntValue, arguments))
274 assert(false, "optimize attribute argument not a string or integer constant");
278 * The `@restrict` attribute specifies that a function parameter is to be
279 * restrict-qualified in the C99 sense of the term. The parameter needs to
280 * boil down to either a pointer or reference type, such as a D pointer,
281 * class reference, or a `ref` parameter.
285 * import gcc.attributes;
287 * void func(@restrict ref const float[16] array);
290 enum restrict = attribute("restrict");
293 * The `@section` attribute specifies that a function lives in a particular
294 * section. For when you need certain particular functions to appear in
297 * Some file formats do not support arbitrary sections so the section attribute
298 * is not available on all platforms. If you need to map the entire contents
299 * of a module to a particular section, consider using the facilities of the
304 * import gcc.attributes;
306 * @section("bar") extern void func();
309 auto section(string sectionName)
311 return attribute("section", sectionName);
314 auto section(A...)(A arguments)
316 assert(false, "section attribute argument not a string constant");
320 * The `@symver` attribute creates a symbol version on ELF targets. The syntax
321 * of the string parameter is `name@nodename`. The `name` part of the parameter
322 * is the actual name of the symbol by which it will be externally referenced.
323 * The `nodename` portion should be the name of a node specified in the version
324 * script supplied to the linker when building a shared library. Versioned
325 * symbol must be defined and must be exported with default visibility.
327 * Finally if the parameter is `name@@nodename` then in addition to creating a
328 * symbol version (as if `name@nodename` was used) the version will be also used
329 * to resolve `name` by the linker.
333 * import gcc.attributes;
335 * @symver("foo@VERS_1") int foo_v1();
338 auto symver(A...)(A arguments)
339 if (allSatisfy!(isStringValue, arguments))
341 return attribute("symver", arguments);
344 auto symver(A...)(A arguments)
345 if (!allSatisfy!(isStringValue, arguments))
347 assert(false, "symver attribute argument not a string constant");
351 * The `@target` attribute is used to specify that a function is to be
352 * compiled with different target options than specified on the command line.
353 * One or more strings can be provided as arguments, separated by commas to
354 * specify multiple options. Each string consists of one or more
355 * comma-separated suffixes to the `-m` prefix jointly forming the name of a
356 * machine-dependent option.
358 * The target attribute can be used for instance to have a function compiled
359 * with a different ISA (instruction set architecture) than the default.
361 * The options supported are specific to each target.
365 * import gcc.attributes;
367 * @target("arch=core2") void core2_func();
368 * @target("sse3") void sse3_func();
371 auto target(A...)(A arguments)
372 if (allSatisfy!(isStringValue, arguments))
374 return attribute("target", arguments);
377 auto target(A...)(A arguments)
378 if (!allSatisfy!(isStringValue, arguments))
380 assert(false, "target attribute argument not a string constant");
384 * The `@target_clones` attribute is used to specify that a function be cloned
385 * into multiple versions compiled with different target `options` than
386 * specified on the command line. The supported options and restrictions are
387 * the same as for `@target` attribute.
389 * It also creates a resolver function that dynamically selects a clone suitable
390 * for current architecture. The resolver is created only if there is a usage
391 * of a function with `@target_clones` attribute.
395 * import gcc.attributes;
397 * @target_clones("sse4.1,avx,default") double func(double x);
400 auto target_clones(A...)(A arguments)
401 if (allSatisfy!(isStringValue, arguments))
403 return attribute("target_clones", arguments);
406 auto target_clones(A...)(A arguments)
407 if (!allSatisfy!(isStringValue, arguments))
409 assert(false, "target attribute argument not a string constant");
413 * The `@used` attribute, annotated to a function, means that code must be
414 * emitted for the function even if it appears that the function is not
415 * referenced. This is useful, for example, when the function is referenced
416 * only in inline assembly.
420 * import gcc.attributes;
422 * @used __gshared int var = 0x1000;
425 enum used = attribute("used");
428 * The `@weak` attribute causes a declaration of an external symbol to be
429 * emitted as a weak symbol rather than a global. This is primarily useful in
430 * defining library functions that can be overridden in user code, though it can
431 * also be used with non-function declarations. The overriding symbol must have
432 * the same type as the weak symbol. In addition, if it designates a variable
433 * it must also have the same size and alignment as the weak symbol.
435 * Weak symbols are supported for ELF targets, and also for a.out targets when
436 * using the GNU assembler and linker.
440 * import gcc.attributes;
442 * @weak int func() { return 1; }
445 enum weak = attribute("weak");
448 * The `@noplt` attribute is the counterpart to option `-fno-plt`. Calls to
449 * functions marked with this attribute in position-independent code do not use
450 * the PLT in position-independent code.
452 * In position-dependant code, a few targets also convert call to functions
453 * that are marked to not use the PLT to use the GOT instead.
457 * import gcc.attributes;
463 enum noplt = attribute("noplt");
465 ///////////////////////////////////////////////////////////////////////////////
467 // Attributes defined for compatibility with LDC.
469 ///////////////////////////////////////////////////////////////////////////////
472 * Specifies that the function returns `null` or a pointer to at least a
473 * certain number of allocated bytes. `sizeArgIdx` and `numArgIdx` specify
474 * the 0-based index of the function arguments that should be used to calculate
475 * the number of bytes returned.
479 * import gcc.attributes;
481 * @allocSize(0) extern(C) void* malloc(size_t size);
482 * @allocSize(2,1) extern(C) void* reallocarray(void *ptr, size_t nmemb,
484 * @allocSize(0,1) void* my_calloc(size_t element_size, size_t count,
488 auto allocSize(int sizeArgIdx, int numArgIdx = int.min)
490 return alloc_size(sizeArgIdx, numArgIdx, true);
493 auto allocSize(A...)(A arguments)
495 assert(false, "allocSize attribute argument value is not an integer constant");
499 * When applied to a global symbol, the compiler, assembler, and linker are
500 * required to treat the symbol as if there is a reference to the symbol that
501 * it cannot see (which is why they have to be named). For example, it
502 * prevents the deletion by the linker of an unreferenced symbol.
506 * import gcc.attributes;
508 * @assumeUsed __gshared int var = 0x1000;
511 alias assumeUsed = used;
513 /// This attribute has no effect.
514 enum dynamicCompile = false;
517 enum dynamicCompileConst = false;
520 enum dynamicCompileEmit = false;
523 * Explicitly sets "fast-math" for a function, enabling aggressive math
524 * optimizations. These optimizations may dramatically change the outcome of
525 * floating point calculations (e.g. because of reassociation).
529 * import gcc.attributes;
532 * double dot(double[] a, double[] b) {
534 * foreach(size_t i; 0..a.length)
536 * // will result in vectorized fused-multiply-add instructions
543 enum fastmath = optimize("Ofast");
546 * Adds GCC's "naked" attribute to a function, disabling function prologue /
548 * Intended to be used in combination with basic `asm` statement. While using
549 * extended `asm` or a mixture of basic `asm` and D code may appear to work,
550 * they cannot be depended upon to work reliably and are not supported.
554 * import gcc.attributes;
556 * @naked void abort() {
561 enum naked = attribute("naked");
564 * Sets the optimization strategy for a function.
565 * Valid strategies are "none", "optsize", "minsize". The strategies are
566 * mutually exclusive.
570 * import gcc.attributes;
572 * @optStrategy("none")
578 auto optStrategy(string strategy)
580 if (strategy == "none")
581 return optimize("O0");
582 else if (strategy == "optsize" || strategy == "minsize")
583 return optimize("Os");
586 assert(false, "unrecognized parameter `" ~ strategy
587 ~ "` for `gcc.attribute.optStrategy`");
591 auto optStrategy(A...)(A arguments)
593 assert(false, "optStrategy attribute argument value is not a string constant");
597 * When applied to a function, specifies that the function should be optimzed
598 * by Graphite, GCC's polyhedral optimizer. Useful for optimizing loops for
599 * data locality, vectorization and parallelism.
603 * Only effective when GDC was built with ISL included.
605 enum polly = optimize("loop-parallelize-all", "loop-nest-optimize");