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 }