1 //          Copyright Guillaume Piolat 2017
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 module pfft.ldc_compat;
7 
8 version(LDC)
9 {
10     public import ldc.intrinsics;
11 
12     static if (__VERSION__ <= 2070) 
13     {
14         // Note for LDC 1.0: loadAligned is broken so we replace it.
15         //                   storeAligned so we provide it.
16         public import ldc.simd: extractelement, 
17                                 insertelement,
18                                 shufflevector,
19                                 inlineIR,
20                                 double2,
21                                 float4;
22 
23         private template BaseType(V)
24         {
25             alias typeof(V.array[0]) BaseType;
26         }
27 
28         private template numElements(V)
29         {
30             enum numElements = V.sizeof / BaseType!(V).sizeof;
31         }
32 
33         private template llvmType(T)
34         {
35             static if(is(T == float))
36                 enum llvmType = "float";
37             else static if(is(T == double))
38                 enum llvmType = "double";
39             else static if(is(T == byte) || is(T == ubyte) || is(T == void))
40                 enum llvmType = "i8";
41             else static if(is(T == short) || is(T == ushort))
42                 enum llvmType = "i16";
43             else static if(is(T == int) || is(T == uint))
44                 enum llvmType = "i32";
45             else static if(is(T == long) || is(T == ulong))
46                 enum llvmType = "i64";
47             else
48                 static assert(0,
49                     "Can't determine llvm type for D type " ~ T.stringof);
50         }
51 
52         private template llvmVecType(V)
53         {
54       /*      static if(is(V == void16))
55                 enum llvmVecType =  "<16 x i8>";
56             else static if(is(V == void32))
57                 enum llvmVecType =  "<32 x i8>";
58             else*/
59             //{
60                 alias BaseType!V T;
61                 enum int n = numElements!V;
62                 enum llvmT = llvmType!T;
63                 enum llvmVecType = "<"~n.stringof~" x "~llvmT~">";
64          //   }
65         }
66 
67         /**
68         loadUnaligned: Loads a vector from an unaligned pointer.
69         Example:
70         ---
71         int[4] a = [0, 10, 20, 30];
72         int4 v = loadUnaligned!int4(a.ptr);
73         assert(v.array == a);
74         ---
75         */
76         template loadUnaligned(V)
77         if(is(typeof(llvmVecType!V)))
78         {
79             alias BaseType!V T;
80             enum llvmT = llvmType!T;
81             enum llvmV = llvmVecType!V;
82             version (LDC_LLVM_PRE307)
83             {
84                 enum ir = `
85                     %p = bitcast `~llvmT~`* %0 to `~llvmV~`*
86                     %r = load `~llvmV~`* %p, align 1
87                     ret `~llvmV~` %r`;
88             }
89             else
90             {
91                 enum ir = `
92                     %p = bitcast `~llvmT~`* %0 to `~llvmV~`*
93                     %r = load `~llvmV~`, `~llvmV~`* %p, align 1
94                     ret `~llvmV~` %r`;
95             }
96 
97             alias inlineIR!(ir, V, const(T)*) loadUnaligned;
98         }
99 
100         /**
101         storeUnaligned: Stores a vector to an unaligned pointer.
102         Example:
103         ---
104         int[4] a;
105         int4 v = [0, 10, 20, 30];
106         storeUnaligned!int4(v, a.ptr);
107         assert(v.array == a);
108         ---
109         */
110         template storeUnaligned(V)
111        // if(is(typeof(llvmVecType!V)))
112         {
113           alias BaseType!V T;
114           enum llvmT = llvmType!T;
115           enum llvmV = llvmVecType!V;
116           enum ir = `
117               %p = bitcast `~llvmT~`* %1 to `~llvmV~`*
118               store `~llvmV~` %0, `~llvmV~`* %p, align 1`;
119           alias inlineIR!(ir, void, V, T*) storeUnaligned;
120         }
121 
122 
123     }
124     else
125     {
126         public import ldc.simd;
127     }
128 }