10
10
module core.internal.convert ;
11
11
import core.internal.traits : Unqual;
12
12
13
- @trusted pure nothrow
13
+ /+
14
+ A @nogc function can allocate memory during CTFE.
15
+ +/
16
+ @nogc nothrow pure @trusted
17
+ private ubyte [] ctfe_alloc ()(size_t n)
18
+ {
19
+ if (! __ctfe)
20
+ {
21
+ assert (0 , " CTFE only" );
22
+ }
23
+ else
24
+ {
25
+ static ubyte [] alloc (size_t x) nothrow pure
26
+ {
27
+ if (__ctfe) // Needed to prevent _d_newarray from appearing in compiled prorgam.
28
+ return new ubyte [x];
29
+ else
30
+ assert (0 );
31
+ }
32
+ return (cast (ubyte [] function (size_t ) @nogc nothrow pure ) &alloc)(n);
33
+ }
34
+ }
35
+
36
+ @trusted pure nothrow @nogc
14
37
const (ubyte )[] toUbyte (T)(ref T val) if (is (Unqual! T == float ) || is (Unqual! T == double ) || is (Unqual! T == real ) ||
15
38
is (Unqual! T == ifloat ) || is (Unqual! T == idouble ) || is (Unqual! T == ireal ))
16
39
{
17
40
static const (ubyte )[] reverse_ (const (ubyte )[] arr)
18
41
{
19
- ubyte [] buff = new ubyte [ arr.length] ;
42
+ ubyte [] buff = ctfe_alloc( arr.length) ;
20
43
foreach (k, v; arr)
21
44
{
22
45
buff[$- k- 1 ] = v;
@@ -31,7 +54,7 @@ const(ubyte)[] toUbyte(T)(ref T val) if(is(Unqual!T == float) || is(Unqual!T ==
31
54
uint exp = parsed.exponent;
32
55
uint sign = parsed.sign;
33
56
34
- ubyte [T.sizeof ] buff;
57
+ ubyte [] buff = ctfe_alloc(T.sizeof) ;
35
58
size_t off_bytes = 0 ;
36
59
size_t off_bits = 0 ;
37
60
@@ -60,7 +83,7 @@ const(ubyte)[] toUbyte(T)(ref T val) if(is(Unqual!T == float) || is(Unqual!T ==
60
83
61
84
version (LittleEndian )
62
85
{
63
- return buff. dup ;
86
+ return buff;
64
87
}
65
88
else
66
89
{
@@ -73,13 +96,13 @@ const(ubyte)[] toUbyte(T)(ref T val) if(is(Unqual!T == float) || is(Unqual!T ==
73
96
}
74
97
}
75
98
76
- @safe pure nothrow
99
+ @safe pure nothrow @nogc
77
100
private Float parse (bool is_denormalized = false , T)(T x) if (is (Unqual! T == ifloat ) || is (Unqual! T == idouble ) || is (Unqual! T == ireal ))
78
101
{
79
102
return parse (x.im);
80
103
}
81
104
82
- @safe pure nothrow
105
+ @safe pure nothrow @nogc
83
106
private Float parse (bool is_denormalized = false , T:real )(T x_) if (floatFormat! T != FloatFormat.Real80)
84
107
{
85
108
Unqual! T x = x_;
@@ -116,7 +139,7 @@ private Float parse(bool is_denormalized = false, T:real)(T x_) if(floatFormat!T
116
139
return Float (mant, exp, sign);
117
140
}
118
141
119
- @safe pure nothrow
142
+ @safe pure nothrow @nogc
120
143
private Float parse (bool _ = false , T:real )(T x_) if (floatFormat! T == FloatFormat.Real80)
121
144
{
122
145
Unqual! T x = x_;
@@ -228,10 +251,10 @@ private template FloatTraits(T) if(floatFormat!T == FloatFormat.Quadruple) //Uns
228
251
}
229
252
230
253
231
- @safe pure nothrow
254
+ @safe pure nothrow @nogc
232
255
private real binPow2 (int pow)
233
256
{
234
- static real binPosPow2 (int pow) @safe pure nothrow
257
+ static real binPosPow2 (int pow) @safe pure nothrow @nogc
235
258
{
236
259
assert (pow > 0 );
237
260
@@ -256,13 +279,13 @@ private real binPow2(int pow)
256
279
257
280
258
281
// Need in CTFE, because CTFE float and double expressions computed more precisely that run-time expressions.
259
- @safe pure nothrow
282
+ @safe pure nothrow @nogc
260
283
private ulong shiftrRound (ulong x)
261
284
{
262
285
return (x >> 1 ) + (x & 1 );
263
286
}
264
287
265
- @safe pure nothrow
288
+ @safe pure nothrow @nogc
266
289
private uint binLog2 (T)(T x)
267
290
{
268
291
assert (x > 0 );
@@ -290,7 +313,7 @@ private uint binLog2(T)(T x)
290
313
return max;
291
314
}
292
315
293
- @safe pure nothrow
316
+ @safe pure nothrow @nogc
294
317
private ulong denormalizedMantissa (T)(T x) if (floatFormat! T == FloatFormat.Real80)
295
318
{
296
319
x *= 2.0L ^^ FloatTraits! T.MANTISSA ;
@@ -299,7 +322,7 @@ private ulong denormalizedMantissa(T)(T x) if(floatFormat!T == FloatFormat.Real8
299
322
return fl.mantissa >> pow;
300
323
}
301
324
302
- @safe pure nothrow
325
+ @safe pure nothrow @nogc
303
326
private ulong denormalizedMantissa (T)(T x) if (floatFormat! T != FloatFormat.Real80)
304
327
{
305
328
x *= 2.0L ^^ FloatTraits! T.MANTISSA ;
@@ -475,21 +498,23 @@ template floatFormat(T) if(is(T:real) || is(T:ireal))
475
498
}
476
499
477
500
// all toUbyte functions must be evaluable at compile time
478
- @trusted pure nothrow
501
+ @trusted pure nothrow @nogc
479
502
const (ubyte )[] toUbyte (T)(T[] arr) if (T.sizeof == 1 )
480
503
{
481
504
return cast (const (ubyte )[])arr;
482
505
}
483
506
484
- @trusted pure nothrow
507
+ @trusted pure nothrow @nogc
485
508
const (ubyte )[] toUbyte (T)(T[] arr) if ((is (typeof (toUbyte(arr[0 ])) == const (ubyte )[])) && (T.sizeof > 1 ))
486
509
{
487
510
if (__ctfe)
488
511
{
489
- const (ubyte )[] ret;
512
+ ubyte [] ret = ctfe_alloc(T.sizeof * arr.length);
513
+ size_t offset = 0 ;
490
514
foreach (cur; arr)
491
515
{
492
- ret ~= toUbyte(cur);
516
+ ret[offset .. offset + T.sizeof] = toUbyte(cur)[0 .. T.sizeof];
517
+ offset += T.sizeof;
493
518
}
494
519
return ret;
495
520
}
@@ -499,14 +524,16 @@ const(ubyte)[] toUbyte(T)(T[] arr) if ((is(typeof(toUbyte(arr[0])) == const(ubyt
499
524
}
500
525
}
501
526
502
- @trusted pure nothrow
527
+ @trusted pure nothrow @nogc
503
528
const (ubyte )[] toUbyte (T)(ref T val) if (__traits(isIntegral, T) && ! is (T == enum ))
504
529
{
505
530
static if (T.sizeof == 1 )
506
531
{
507
532
if (__ctfe)
508
533
{
509
- return cast (const (ubyte )[])[val];
534
+ ubyte [] result = ctfe_alloc(1 );
535
+ result[0 ] = cast (ubyte ) val;
536
+ return result;
510
537
}
511
538
else
512
539
{
@@ -515,7 +542,7 @@ const(ubyte)[] toUbyte(T)(ref T val) if (__traits(isIntegral, T) && !is(T == enu
515
542
}
516
543
else if (__ctfe)
517
544
{
518
- ubyte [T.sizeof ] tmp;
545
+ ubyte [] tmp = ctfe_alloc(T.sizeof) ;
519
546
Unqual! T val_ = val;
520
547
for (size_t i = 0 ; i < T.sizeof; ++ i)
521
548
{
@@ -525,30 +552,35 @@ const(ubyte)[] toUbyte(T)(ref T val) if (__traits(isIntegral, T) && !is(T == enu
525
552
tmp[idx] = cast (ubyte )(val_&0xff );
526
553
val_ >>= 8 ;
527
554
}
528
- return tmp[]. dup ;
555
+ return tmp;
529
556
}
530
557
else
531
558
{
532
559
return (cast (const (ubyte )* )(&val))[0 .. T.sizeof];
533
560
}
534
561
}
535
562
536
- @trusted pure nothrow
563
+ @trusted pure nothrow @nogc
537
564
const (ubyte )[] toUbyte (T)(ref T val) if (is (Unqual! T == cfloat ) || is (Unqual! T == cdouble ) || is (Unqual! T == creal ))
538
565
{
539
566
if (__ctfe)
540
567
{
541
568
auto re = val.re;
542
569
auto im = val.im;
543
- return (re.toUbyte() ~ im.toUbyte());
570
+ auto a = re.toUbyte();
571
+ auto b = im.toUbyte();
572
+ ubyte [] result = ctfe_alloc(a.length + b.length);
573
+ result[0 .. a.length] = a[0 .. a.length];
574
+ result[a.length .. $] = b[0 .. b.length];
575
+ return result;
544
576
}
545
577
else
546
578
{
547
579
return (cast (const (ubyte )* )&val)[0 .. T.sizeof];
548
580
}
549
581
}
550
582
551
- @trusted pure nothrow
583
+ @trusted pure nothrow @nogc
552
584
const (ubyte )[] toUbyte (T)(ref T val) if (is (T == enum ) && is (typeof (toUbyte(cast (V)val)) == const (ubyte )[]))
553
585
{
554
586
if (__ctfe)
@@ -605,12 +637,12 @@ private bool isNonReferenceStruct(T)() if (is(T == struct) || is(T == union))
605
637
return true ;
606
638
}
607
639
608
- @trusted pure nothrow
640
+ @trusted pure nothrow @nogc
609
641
const (ubyte )[] toUbyte (T)(ref T val) if (is (T == struct ) || is (T == union ))
610
642
{
611
643
if (__ctfe)
612
644
{
613
- ubyte [T.sizeof ] bytes;
645
+ ubyte [] bytes = ctfe_alloc(T.sizeof) ;
614
646
foreach (key, cur; val.tupleof)
615
647
{
616
648
alias CUR_TYPE = typeof (cur);
@@ -629,7 +661,7 @@ const(ubyte)[] toUbyte(T)(ref T val) if (is(T == struct) || is(T == union))
629
661
assert (0 , " Unable to compute byte representation of " ~ typeof (CUR_TYPE ).stringof~ " field at compile time" );
630
662
}
631
663
}
632
- return bytes[]. dup ;
664
+ return bytes;
633
665
}
634
666
else
635
667
{
0 commit comments