]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/libdruntime/gcc/attributes.d
Update copyright years.
[thirdparty/gcc.git] / libphobos / libdruntime / gcc / attributes.d
1 // GNU D Compiler attribute support declarations.
2 // Copyright (C) 2021-2022 Free Software Foundation, Inc.
3
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
7 // version.
8
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
12 // for more details.
13
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.
17
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/>.
22
23 module gcc.attributes;
24
25 // Private helper templates.
26 private struct Attribute(A...)
27 {
28 A arguments;
29 }
30
31 private enum bool isStringValue(alias T) = is(typeof(T) == string);
32
33 private enum bool isStringOrIntValue(alias T)
34 = is(typeof(T) == string) || is(typeof(T) == int);
35
36 private template allSatisfy(alias F, T...)
37 {
38 static if (T.length == 0)
39 enum allSatisfy = true;
40 else static if (T.length == 1)
41 enum allSatisfy = F!(T[0]);
42 else
43 {
44 enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2])
45 && allSatisfy!(F, T[$/2 .. $ ]);
46 }
47 }
48
49 /**
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.
54 *
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.
58 *
59 * Example:
60 * ---
61 * import gcc.attributes;
62 *
63 * @attribute("regparm", 1) int func(int size);
64 * ---
65 */
66 @system
67 auto attribute(A...)(A arguments)
68 if (A.length > 0 && is(A[0] == string))
69 {
70 return Attribute!A(arguments);
71 }
72
73
74 ///////////////////////////////////////////////////////////////////////////////
75 //
76 // Supported common attributes exposed by GDC.
77 //
78 ///////////////////////////////////////////////////////////////////////////////
79
80 /**
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
88 * member functions.
89 *
90 * If `numArgIdx` is less than `0`, it is taken to mean there is no argument
91 * specifying the element count.
92 *
93 * Example:
94 * ---
95 * import gcc.attributes;
96 *
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,
99 * size_t size);
100 * @alloc_size(1,2) void* my_calloc(size_t element_size, size_t count,
101 * bool irrelevant);
102 * ---
103 */
104 auto alloc_size(int sizeArgIdx)
105 {
106 return attribute("alloc_size", sizeArgIdx);
107 }
108
109 /// ditto
110 auto alloc_size(int sizeArgIdx, int numArgIdx)
111 {
112 return attribute("alloc_size", sizeArgIdx, numArgIdx);
113 }
114
115 /// ditto
116 auto alloc_size(int sizeArgIdx, int numArgIdx, bool zeroBasedNumbering)
117 {
118 return attribute("alloc_size", sizeArgIdx, numArgIdx, zeroBasedNumbering);
119 }
120
121 auto alloc_size(A...)(A arguments)
122 {
123 assert(false, "alloc_size attribute argument value is not an integer constant");
124 }
125
126 /**
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.
130 *
131 * Example:
132 * ---
133 * import gcc.attributes;
134 *
135 * @always_inline int func();
136 * ---
137 */
138 enum always_inline = attribute("always_inline");
139
140 /**
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.
147 *
148 * Example:
149 * ---
150 * import gcc.attributes;
151 *
152 * @cold int func();
153 * ---
154 */
155 enum cold = attribute("cold");
156
157 /**
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.
161 *
162 * Example:
163 * ---
164 * import gcc.attributes;
165 *
166 * @flatten int func();
167 * ---
168 */
169 enum flatten = attribute("flatten");
170
171 /**
172 * The `@no_icf` attribute prevents a functions from being merged with another
173 * semantically equivalent function.
174 *
175 * Example:
176 * ---
177 * import gcc.attributes;
178 *
179 * @no_icf int func();
180 * ---
181 */
182 enum no_icf = attribute("no_icf");
183
184 /**
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.
188 *
189 * Example:
190 * ---
191 * import gcc.attributes;
192 *
193 * @noclone int func();
194 * ---
195 */
196 enum noclone = attribute("noclone");
197
198 /**
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.
205 *
206 * Example:
207 * ---
208 * import gcc.attributes;
209 *
210 * @noinline int func();
211 * ---
212 */
213 enum noinline = attribute("noinline");
214
215 /**
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.
224 *
225 * This attribute is supported mainly for the purpose of testing the compiler.
226 *
227 * Example:
228 * ---
229 * import gcc.attributes;
230 *
231 * @noipa int func();
232 * ---
233 */
234 enum noipa = attribute("noipa");
235
236 /**
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.
245 *
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
249 * production code.
250 *
251 * Example:
252 * ---
253 * import gcc.attributes;
254 *
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);
263 * ---
264 */
265 auto optimize(A...)(A arguments)
266 if (allSatisfy!(isStringOrIntValue, arguments))
267 {
268 return attribute("optimize", arguments);
269 }
270
271 auto optimize(A...)(A arguments)
272 if (!allSatisfy!(isStringOrIntValue, arguments))
273 {
274 assert(false, "optimize attribute argument not a string or integer constant");
275 }
276
277 /**
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.
282 *
283 * Example:
284 * ---
285 * import gcc.attributes;
286 *
287 * void func(@restrict ref const float[16] array);
288 * ---
289 */
290 enum restrict = attribute("restrict");
291
292 /**
293 * The `@section` attribute specifies that a function lives in a particular
294 * section. For when you need certain particular functions to appear in
295 * special sections.
296 *
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
300 * linker instead.
301 *
302 * Example:
303 * ---
304 * import gcc.attributes;
305 *
306 * @section("bar") extern void func();
307 * ---
308 */
309 auto section(string sectionName)
310 {
311 return attribute("section", sectionName);
312 }
313
314 auto section(A...)(A arguments)
315 {
316 assert(false, "section attribute argument not a string constant");
317 }
318
319 /**
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.
326 *
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.
330 *
331 * Example:
332 * ---
333 * import gcc.attributes;
334 *
335 * @symver("foo@VERS_1") int foo_v1();
336 * ---
337 */
338 auto symver(A...)(A arguments)
339 if (allSatisfy!(isStringValue, arguments))
340 {
341 return attribute("symver", arguments);
342 }
343
344 auto symver(A...)(A arguments)
345 if (!allSatisfy!(isStringValue, arguments))
346 {
347 assert(false, "symver attribute argument not a string constant");
348 }
349
350 /**
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.
357 *
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.
360 *
361 * The options supported are specific to each target.
362 *
363 * Example:
364 * ---
365 * import gcc.attributes;
366 *
367 * @target("arch=core2") void core2_func();
368 * @target("sse3") void sse3_func();
369 * ---
370 */
371 auto target(A...)(A arguments)
372 if (allSatisfy!(isStringValue, arguments))
373 {
374 return attribute("target", arguments);
375 }
376
377 auto target(A...)(A arguments)
378 if (!allSatisfy!(isStringValue, arguments))
379 {
380 assert(false, "target attribute argument not a string constant");
381 }
382
383 /**
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.
388 *
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.
392 *
393 * Example:
394 * ---
395 * import gcc.attributes;
396 *
397 * @target_clones("sse4.1,avx,default") double func(double x);
398 * ---
399 */
400 auto target_clones(A...)(A arguments)
401 if (allSatisfy!(isStringValue, arguments))
402 {
403 return attribute("target_clones", arguments);
404 }
405
406 auto target_clones(A...)(A arguments)
407 if (!allSatisfy!(isStringValue, arguments))
408 {
409 assert(false, "target attribute argument not a string constant");
410 }
411
412 /**
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.
417 *
418 * Example:
419 * ---
420 * import gcc.attributes;
421 *
422 * @used __gshared int var = 0x1000;
423 * ---
424 */
425 enum used = attribute("used");
426
427 /**
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.
434 *
435 * Weak symbols are supported for ELF targets, and also for a.out targets when
436 * using the GNU assembler and linker.
437 *
438 * Example:
439 * ---
440 * import gcc.attributes;
441 *
442 * @weak int func() { return 1; }
443 * ---
444 */
445 enum weak = attribute("weak");
446
447 /**
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.
451 *
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.
454 *
455 * Example:
456 * ---
457 * import gcc.attributes;
458 *
459 * @noplt int func();
460 *
461 * ---
462 */
463 enum noplt = attribute("noplt");
464
465 ///////////////////////////////////////////////////////////////////////////////
466 //
467 // Attributes defined for compatibility with LDC.
468 //
469 ///////////////////////////////////////////////////////////////////////////////
470
471 /**
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.
476 *
477 * Example:
478 * ---
479 * import gcc.attributes;
480 *
481 * @allocSize(0) extern(C) void* malloc(size_t size);
482 * @allocSize(2,1) extern(C) void* reallocarray(void *ptr, size_t nmemb,
483 * size_t size);
484 * @allocSize(0,1) void* my_calloc(size_t element_size, size_t count,
485 * bool irrelevant);
486 * ---
487 */
488 auto allocSize(int sizeArgIdx, int numArgIdx = int.min)
489 {
490 return alloc_size(sizeArgIdx, numArgIdx, true);
491 }
492
493 auto allocSize(A...)(A arguments)
494 {
495 assert(false, "allocSize attribute argument value is not an integer constant");
496 }
497
498 /**
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.
503 *
504 * Example:
505 * ---
506 * import gcc.attributes;
507 *
508 * @assumeUsed __gshared int var = 0x1000;
509 * ---
510 */
511 alias assumeUsed = used;
512
513 /// This attribute has no effect.
514 enum dynamicCompile = false;
515
516 /// ditto
517 enum dynamicCompileConst = false;
518
519 /// ditto
520 enum dynamicCompileEmit = false;
521
522 /**
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).
526 *
527 * Example:
528 * ---
529 * import gcc.attributes;
530 *
531 * @fastmath
532 * double dot(double[] a, double[] b) {
533 * double s = 0;
534 * foreach(size_t i; 0..a.length)
535 * {
536 * // will result in vectorized fused-multiply-add instructions
537 * s += a * b;
538 * }
539 * return s;
540 * }
541 * ---
542 */
543 enum fastmath = optimize("Ofast");
544
545 /**
546 * Adds GCC's "naked" attribute to a function, disabling function prologue /
547 * epilogue emission.
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.
551 *
552 * Example:
553 * ---
554 * import gcc.attributes;
555 *
556 * @naked void abort() {
557 * asm { "ud2"; }
558 * }
559 * ---
560 */
561 enum naked = attribute("naked");
562
563 /**
564 * Sets the optimization strategy for a function.
565 * Valid strategies are "none", "optsize", "minsize". The strategies are
566 * mutually exclusive.
567 *
568 * Example:
569 * ---
570 * import gcc.attributes;
571 *
572 * @optStrategy("none")
573 * int func() {
574 * return call();
575 * }
576 * ---
577 */
578 auto optStrategy(string strategy)
579 {
580 if (strategy == "none")
581 return optimize("O0");
582 else if (strategy == "optsize" || strategy == "minsize")
583 return optimize("Os");
584 else
585 {
586 assert(false, "unrecognized parameter `" ~ strategy
587 ~ "` for `gcc.attribute.optStrategy`");
588 }
589 }
590
591 auto optStrategy(A...)(A arguments)
592 {
593 assert(false, "optStrategy attribute argument value is not a string constant");
594 }
595
596 /**
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.
600 *
601 * Experimental!
602 *
603 * Only effective when GDC was built with ISL included.
604 */
605 enum polly = optimize("loop-parallelize-all", "loop-nest-optimize");