1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 See: llvm-c/Core.h 7 8 * Types have the following hierarchy: 9 * 10 * types: 11 * integer type 12 * real type 13 * function type 14 * sequence types: 15 * array type 16 * pointer type 17 * vector type 18 * void type 19 * label type 20 * opaque type 21 */ 22 module llvm_hiwrap.type.type; 23 24 import llvm_hiwrap.types; 25 26 struct Type { 27 import llvm : LLVMTypeRef, LLVMTypeKind, LLVMGetTypeKind; 28 29 LxType type; 30 alias type this; 31 32 /** Obtain the enumerated type of a Type instance. 33 * 34 * See: llvm-c/Core.h 35 */ 36 LxTypeKind kind() nothrow { 37 auto r = LxTypeKind.Unknown; 38 try { 39 LLVMTypeKind tmp = LLVMGetTypeKind(rawPtr); 40 if (tmp >= LxTypeKind.min && tmp <= LxTypeKind.max) 41 r = cast(LxTypeKind) tmp; 42 } catch (Exception e) { 43 } 44 45 return r; 46 } 47 48 bool isPrimitive() { 49 import std.algorithm : among; 50 51 with (LxTypeKind) { 52 return kind.among(Void, Half, Float, Double, X86_FP80, FP128, PPC_FP128, Integer) != 0; 53 } 54 } 55 56 bool isLabel() { 57 return kind == LxTypeKind.Label; 58 } 59 60 bool isFunction() { 61 return kind == LxTypeKind.Function; 62 } 63 64 bool isStruct() { 65 return kind == LxTypeKind.Struct; 66 } 67 68 bool isArray() { 69 return kind == LxTypeKind.Array; 70 } 71 72 bool isPointer() { 73 return kind == LxTypeKind.Pointer; 74 } 75 76 bool isVector() { 77 return kind == LxTypeKind.Vector; 78 } 79 80 bool isMetadata() { 81 return kind == LxTypeKind.Metadata; 82 } 83 84 bool isToken() { 85 return kind == LxTypeKind.Token; 86 } 87 88 bool isSequential() { 89 import std.algorithm : among; 90 91 with (LxTypeKind) { 92 return kind.among(Array, Vector, Pointer) != 0; 93 } 94 } 95 96 auto func() { 97 assert(isFunction); 98 import llvm_hiwrap.type.function_; 99 100 return FunctionType(this); 101 } 102 103 auto struct_() { 104 assert(isStruct); 105 import llvm_hiwrap.type.struct_; 106 107 return StructType(this); 108 } 109 110 // Note: exposing the specifics to make it easier to use correctly. 111 // Some function are only valid to use for array types. 112 LxArrayType array() { 113 return LxArrayType(asSequential); 114 } 115 116 // Note: exposing the specifics to make it easier to use correctly. 117 // Some function are only valid to use for array types. 118 LxPointerType pointer() { 119 return LxPointerType(asSequential); 120 } 121 122 // Note: exposing the specifics to make it easier to use correctly. 123 // Some function are only valid to use for array types. 124 LxVectorType vector() { 125 return LxVectorType(asSequential); 126 } 127 128 private: 129 LxSequential asSequential() { 130 import llvm : LLVMGetElementType; 131 132 assert(isSequential); 133 auto t = LLVMGetElementType(rawPtr); 134 return LxSequential(LxType(t)); 135 } 136 } 137 138 /** 139 * Sequential types represents "arrays" of types. This is a super class 140 * for array, vector, and pointer types. 141 * 142 * All elements in a sequential type have the same type. 143 */ 144 struct LxSequentialImpl(LxTypeKind Kind) { 145 import llvm; 146 147 LxType type; 148 alias type this; 149 150 static if (Kind == LxTypeKind.Array) { 151 /** Obtain the length of an array type. 152 * 153 * This only works on types that represent arrays. 154 * 155 * TODO I am unsure if the LLVM documentation mean sequential or array 156 * when it states "only works for arrays". Test what happens when the 157 * type is a pointer or vector. 158 */ 159 @property size_t length() { 160 import std.traits : ReturnType; 161 162 enum llvm_max_length = (ReturnType!LLVMGetArrayLength).max; 163 static assert(llvm_max_length <= size_t.max, 164 "mismatch between LLVM API and the D length type"); 165 166 auto s = LLVMGetArrayLength(type); 167 return s; 168 } 169 } else static if (Kind == LxTypeKind.Pointer) { 170 /** Obtain the address space of a pointer type. 171 * 172 * This only works on types that represent pointers. 173 */ 174 @property auto addressSpace() { 175 return LLVMGetPointerAddressSpace(type); 176 } 177 } else static if (Kind == LxTypeKind.Vector) { 178 /** Obtain the number of elements in a vector type. 179 * 180 * This only works on types that represent vectors. 181 */ 182 @property size_t length() { 183 import std.traits : ReturnType; 184 185 enum llvm_max_length = (ReturnType!LLVMGetVectorSize).max; 186 static assert(llvm_max_length <= size_t.max, 187 "mismatch between LLVM API and the D length type"); 188 189 auto s = LLVMGetVectorSize(type); 190 return s; 191 } 192 } 193 } 194 195 alias LxSequential = LxSequentialImpl!(LxTypeKind.Unknown); 196 alias LxArrayType = LxSequentialImpl!(LxTypeKind.Array); 197 alias LxPointerType = LxSequentialImpl!(LxTypeKind.Pointer); 198 alias LxVectorType = LxSequentialImpl!(LxTypeKind.Vector);