aarch64: Fix sve/acle/general/ldff1_8.c failures
[gcc.git] / libphobos / libdruntime / core / internal / array / utils.d
blob03d414471ad695a5e8b213c178da28b4230ffbea
1 /**
2 This module contains utility functions to help the implementation of the runtime hook
4 Copyright: Copyright Digital Mars 2000 - 2019.
5 License: Distributed under the
6 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 (See accompanying file LICENSE)
8 Source: $(DRUNTIMESRC core/internal/_array/_utils.d)
9 */
10 module core.internal.array.utils;
12 import core.internal.traits : Parameters;
13 import core.memory : GC;
15 alias BlkAttr = GC.BlkAttr;
17 auto gcStatsPure() nothrow pure
19 import core.memory : GC;
20 auto impureBypass = cast(GC.Stats function() pure nothrow)&GC.stats;
21 return impureBypass();
24 ulong accumulatePure(string file, int line, string funcname, string name, ulong size) nothrow pure
26 static ulong impureBypass(string file, int line, string funcname, string name, ulong size) @nogc nothrow
28 import core.internal.traits : externDFunc;
30 alias accumulate = externDFunc!("rt.profilegc.accumulate", void function(string file, uint line, string funcname, string type, ulong sz) @nogc nothrow);
31 accumulate(file, line, funcname, name, size);
32 return size;
35 auto func = cast(ulong function(string file, int line, string funcname, string name, ulong size) @nogc nothrow pure)&impureBypass;
36 return func(file, line, funcname, name, size);
39 version (D_ProfileGC)
41 /**
42 * TraceGC wrapper generator around the runtime hook `Hook`.
43 * Params:
44 * Type = The type of hook to report to accumulate
45 * Hook = The name hook to wrap
47 template TraceHook(string Type, string Hook)
49 const char[] TraceHook = q{
50 import core.internal.array.utils : gcStatsPure, accumulatePure;
52 pragma(inline, false);
53 string name = } ~ "`" ~ Type ~ "`;" ~ q{
55 // FIXME: use rt.tracegc.accumulator when it is accessable in the future.
56 version (tracegc)
57 } ~ "{\n" ~ q{
58 import core.stdc.stdio;
60 printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n",
61 } ~ "\"" ~ Hook ~ "\".ptr," ~ q{
62 file.length, file.ptr,
63 line,
64 funcname.length, funcname.ptr,
65 name.length, name.ptr
67 } ~ "}\n" ~ q{
68 ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
70 scope(exit)
72 ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
73 if (size > 0)
74 if (!accumulatePure(file, line, funcname, name, size)) {
75 // This 'if' and 'assert' is needed to force the compiler to not remove the call to
76 // `accumulatePure`. It really want to do that while optimizing as the function is
77 // `pure` and it does not influence the result of this hook.
79 // `accumulatePure` returns the value of `size`, which can never be zero due to the
80 // previous 'if'. So this assert will never be triggered.
81 assert(0);
87 /**
88 * TraceGC wrapper around runtime hook `Hook`.
89 * Params:
90 * T = Type of hook to report to accumulate
91 * Hook = The hook to wrap
92 * errorMessage = The error message incase `version != D_TypeInfo`
93 * file = File that called `_d_HookTraceImpl`
94 * line = Line inside of `file` that called `_d_HookTraceImpl`
95 * funcname = Function that called `_d_HookTraceImpl`
96 * parameters = Parameters that will be used to call `Hook`
97 * Bugs:
98 * This function template needs be between the compiler and a much older runtime hook that bypassed safety,
99 * purity, and throwabilty checks. To prevent breaking existing code, this function template
100 * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
102 auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line, string funcname, Parameters!Hook parameters) @trusted pure
104 version (D_TypeInfo)
106 mixin(TraceHook!(T.stringof, __traits(identifier, Hook)));
107 return Hook(parameters);
109 else
110 assert(0, errorMessage);
115 * Check if the function `F` is calleable in a `nothrow` scope.
116 * Params:
117 * F = Function that does not take any parameters
118 * Returns:
119 * if the function is callable in a `nothrow` scope.
121 enum isNoThrow(alias F) = is(typeof(() nothrow { F(); }));
124 * Check if the type `T`'s postblit is called in nothrow, if it exist
125 * Params:
126 * T = Type to check
127 * Returns:
128 * if the postblit is callable in a `nothrow` scope, if it exist.
129 * if it does not exist, return true.
131 template isPostblitNoThrow(T) {
132 static if (__traits(isStaticArray, T))
133 enum isPostblitNoThrow = isPostblitNoThrow!(typeof(T.init[0]));
134 else static if (__traits(hasMember, T, "__xpostblit") &&
135 // Bugzilla 14746: Check that it's the exact member of S.
136 __traits(isSame, T, __traits(parent, T.init.__xpostblit)))
137 enum isPostblitNoThrow = isNoThrow!(T.init.__xpostblit);
138 else
139 enum isPostblitNoThrow = true;
143 * Allocate a memory block with appendable capabilities for array usage.
145 * Params:
146 * arrSize = size of the allocated array in bytes
147 * Returns:
148 * `void[]` matching requested size on success, `null` on failure.
150 void[] __arrayAlloc(T)(size_t arrSize) @trusted
152 import core.lifetime : TypeInfoSize;
153 import core.internal.traits : hasIndirections;
155 enum typeInfoSize = TypeInfoSize!T;
156 BlkAttr attr = BlkAttr.APPENDABLE;
158 /* `extern(C++)` classes don't have a classinfo pointer in their vtable,
159 * so the GC can't finalize them.
161 static if (typeInfoSize)
162 attr |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
163 static if (!hasIndirections!T)
164 attr |= BlkAttr.NO_SCAN;
166 auto ptr = GC.malloc(arrSize, attr, typeid(T));
167 if (ptr)
168 return ptr[0 .. arrSize];
169 return null;