| /********************************************** | |
| To provide access to features that would be otherwise counterproductive or | |
| difficult to implement, compilers provide an interface consisting of a set | |
| of builtins (also called intrinsics) which can be called like normal functions. | |
| This module exposes builtins both common to all D compilers | |
| (those provided by the frontend) and specific to the host compiler i.e. those | |
| specific to either LLVM or GCC (`ldc.intrinsics` and `gcc.builtins` are publicly imported, respectively). | |
| Host-specific intrinsics cannot be reliably listed here, however listings can be found | |
| at the documentation for the relevant backends, i.e. | |
| $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html, GCC) and | |
| $(LINK2 https://llvm.org/docs/LangRef.html, LLVM). It should be noted that not all | |
| builtins listed are necessarily supported by the host compiler, please file a bug | |
| if this is the case for your workload. | |
| Use of this module reduces the amount of conditional compilation needed | |
| to use a given builtin. For example, to write a target independent function | |
| that uses prefetching we can write the following: | |
| --- | |
| float usePrefetch(float[] x) | |
| { | |
| // There is only one import statement required rather than two (versioned) imports | |
| import core.builtins; | |
| version (GNU) | |
| __builtin_prefetch(x.ptr); | |
| version (LDC) | |
| /+ | |
| For the curious: 0, 3, 1 mean `x` will only be read-from (0), it will be used | |
| very often (3), and it should be fetched to the data-cache (1). | |
| +/ | |
| llvm_prefetch(x.ptr, 0, 3, 1); | |
| const doMath = blahBlahBlah; | |
| return doMath; | |
| } | |
| --- | |
| Copyright: Copyright © 2021, The D Language Foundation | |
| License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) | |
| Authors: Walter Bright | |
| Source: $(DRUNTIMESRC core/builtins.d) | |
| */ | |
| module core.builtins; | |
| version (GNU) | |
| public import gcc.builtins; | |
| version (LDC) | |
| public import ldc.intrinsics; | |
| /// Writes `s` to `stderr` during CTFE (does nothing at runtime). | |
| void __ctfeWrite(scope const(char)[] s) @nogc @safe pure nothrow {} | |
| version (GNU) | |
| { | |
| /// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fexpect | |
| alias expect = __builtin_expect; | |
| /// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005ftrap | |
| alias trap = __builtin_trap; | |
| } | |
| else version (LDC) | |
| { | |
| /// https://llvm.org/docs/LangRef.html#llvm-expect-intrinsic | |
| alias expect = llvm_expect; | |
| debug | |
| /// https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic | |
| alias trap = llvm_debugtrap; | |
| else | |
| /// https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic | |
| alias trap = llvm_trap; | |
| } | |
| else version (DigitalMars) | |
| { | |
| pragma(inline, true) | |
| T expect(T)(T val, T expected) if (__traits(isIntegral, T)) | |
| { | |
| return val; | |
| } | |
| /// Execute target dependent trap instruction, if supported. | |
| /// Otherwise, abort execution. | |
| pragma(inline, true) | |
| void trap() | |
| { | |
| debug | |
| { | |
| version(D_InlineAsm_X86) | |
| asm nothrow @nogc pure @trusted { int 3; } | |
| } | |
| assert(0); | |
| } | |
| } | |
| /// Provide static branch and value hints for the LDC/GDC compilers. | |
| /// DMD ignores these hints. | |
| pragma(inline, true) bool likely()(bool b) { return !!expect(b, true); } | |
| /// ditto | |
| pragma(inline, true) bool unlikely()(bool b) { return !!expect(b, false); } | |
| /// | |
| @nogc nothrow pure @safe unittest | |
| { | |
| int x = 12; | |
| expect(x, 12); | |
| if (likely(x > 0)) | |
| { | |
| // ... | |
| } | |
| else if (unlikely(x == int.min)) | |
| { | |
| // ... | |
| } | |
| } |