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 } 43 catch (Exception e) { 44 } 45 46 return r; 47 } 48 49 bool isPrimitive() { 50 import std.algorithm : among; 51 52 with (LxTypeKind) { 53 return kind.among(Void, Half, Float, Double, X86_FP80, FP128, PPC_FP128, Integer) != 0; 54 } 55 } 56 57 bool isLabel() { 58 return kind == LxTypeKind.Label; 59 } 60 61 bool isFunction() { 62 return kind == LxTypeKind.Function; 63 } 64 65 bool isStruct() { 66 return kind == LxTypeKind.Struct; 67 } 68 69 bool isArray() { 70 return kind == LxTypeKind.Array; 71 } 72 73 bool isPointer() { 74 return kind == LxTypeKind.Pointer; 75 } 76 77 bool isVector() { 78 return kind == LxTypeKind.Vector; 79 } 80 81 bool isMetadata() { 82 return kind == LxTypeKind.Metadata; 83 } 84 85 bool isToken() { 86 return kind == LxTypeKind.Token; 87 } 88 89 bool isSequential() { 90 import std.algorithm : among; 91 92 with (LxTypeKind) { 93 return kind.among(Array, Vector, Pointer) != 0; 94 } 95 } 96 97 auto func() { 98 assert(isFunction); 99 import llvm_hiwrap.type.function_; 100 101 return FunctionType(this); 102 } 103 104 auto struct_() { 105 assert(isStruct); 106 import llvm_hiwrap.type.struct_; 107 108 return StructType(this); 109 } 110 111 // Note: exposing the specifics to make it easier to use correctly. 112 // Some function are only valid to use for array types. 113 LxArrayType array() { 114 return LxArrayType(asSequential); 115 } 116 117 // Note: exposing the specifics to make it easier to use correctly. 118 // Some function are only valid to use for array types. 119 LxPointerType pointer() { 120 return LxPointerType(asSequential); 121 } 122 123 // Note: exposing the specifics to make it easier to use correctly. 124 // Some function are only valid to use for array types. 125 LxVectorType vector() { 126 return LxVectorType(asSequential); 127 } 128 129 private: 130 LxSequential asSequential() { 131 import llvm : LLVMGetElementType; 132 133 assert(isSequential); 134 auto t = LLVMGetElementType(rawPtr); 135 return LxSequential(LxType(t)); 136 } 137 } 138 139 /** 140 * Sequential types represents "arrays" of types. This is a super class 141 * for array, vector, and pointer types. 142 * 143 * All elements in a sequential type have the same type. 144 */ 145 struct LxSequentialImpl(LxTypeKind Kind) { 146 import llvm; 147 148 LxType type; 149 alias type this; 150 151 static if (Kind == LxTypeKind.Array) { 152 /** Obtain the length of an array type. 153 * 154 * This only works on types that represent arrays. 155 * 156 * TODO I am unsure if the LLVM documentation mean sequential or array 157 * when it states "only works for arrays". Test what happens when the 158 * type is a pointer or vector. 159 */ 160 @property size_t length() { 161 import std.traits : ReturnType; 162 163 enum llvm_max_length = (ReturnType!LLVMGetArrayLength).max; 164 static assert(llvm_max_length <= size_t.max, 165 "mismatch between LLVM API and the D length type"); 166 167 auto s = LLVMGetArrayLength(type); 168 return s; 169 } 170 } else static if (Kind == LxTypeKind.Pointer) { 171 /** Obtain the address space of a pointer type. 172 * 173 * This only works on types that represent pointers. 174 */ 175 @property auto addressSpace() { 176 return LLVMGetPointerAddressSpace(type); 177 } 178 } else static if (Kind == LxTypeKind.Vector) { 179 /** Obtain the number of elements in a vector type. 180 * 181 * This only works on types that represent vectors. 182 */ 183 @property size_t length() { 184 import std.traits : ReturnType; 185 186 enum llvm_max_length = (ReturnType!LLVMGetVectorSize).max; 187 static assert(llvm_max_length <= size_t.max, 188 "mismatch between LLVM API and the D length type"); 189 190 auto s = LLVMGetVectorSize(type); 191 return s; 192 } 193 } 194 } 195 196 alias LxSequential = LxSequentialImpl!(LxTypeKind.Unknown); 197 alias LxArrayType = LxSequentialImpl!(LxTypeKind.Array); 198 alias LxPointerType = LxSequentialImpl!(LxTypeKind.Pointer); 199 alias LxVectorType = LxSequentialImpl!(LxTypeKind.Vector);