lp_bld_type.c revision 1844ae7e7e2285f52dc0ecd42194ccc47e3137ef
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29#include "util/u_debug.h" 30 31#include "lp_bld_type.h" 32#include "lp_bld_const.h" 33#include "lp_bld_init.h" 34 35 36LLVMTypeRef 37lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type) 38{ 39 if (type.floating) { 40 switch(type.width) { 41 case 32: 42 return LLVMFloatTypeInContext(gallivm->context); 43 break; 44 case 64: 45 return LLVMDoubleTypeInContext(gallivm->context); 46 break; 47 default: 48 assert(0); 49 return LLVMFloatTypeInContext(gallivm->context); 50 } 51 } 52 else { 53 return LLVMIntTypeInContext(gallivm->context, type.width); 54 } 55} 56 57 58LLVMTypeRef 59lp_build_vec_type(struct gallivm_state *gallivm,struct lp_type type) 60{ 61 LLVMTypeRef elem_type = lp_build_elem_type(gallivm, type); 62 if (type.length == 1) 63 return elem_type; 64 else 65 return LLVMVectorType(elem_type, type.length); 66} 67 68 69/** 70 * This function is a mirror of lp_build_elem_type() above. 71 * 72 * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the 73 * type and check for identity. 74 */ 75boolean 76lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type) 77{ 78 LLVMTypeKind elem_kind; 79 80 assert(elem_type); 81 if(!elem_type) 82 return FALSE; 83 84 elem_kind = LLVMGetTypeKind(elem_type); 85 86 if (type.floating) { 87 switch(type.width) { 88 case 32: 89 if(elem_kind != LLVMFloatTypeKind) 90 return FALSE; 91 break; 92 case 64: 93 if(elem_kind != LLVMDoubleTypeKind) 94 return FALSE; 95 break; 96 default: 97 assert(0); 98 return FALSE; 99 } 100 } 101 else { 102 if(elem_kind != LLVMIntegerTypeKind) 103 return FALSE; 104 105 if(LLVMGetIntTypeWidth(elem_type) != type.width) 106 return FALSE; 107 } 108 109 return TRUE; 110} 111 112 113boolean 114lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type) 115{ 116 LLVMTypeRef elem_type; 117 118 assert(vec_type); 119 if(!vec_type) 120 return FALSE; 121 122 if (type.length == 1) 123 return lp_check_elem_type(type, vec_type); 124 125 if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) 126 return FALSE; 127 128 if(LLVMGetVectorSize(vec_type) != type.length) 129 return FALSE; 130 131 elem_type = LLVMGetElementType(vec_type); 132 133 return lp_check_elem_type(type, elem_type); 134} 135 136 137boolean 138lp_check_value(struct lp_type type, LLVMValueRef val) 139{ 140 LLVMTypeRef vec_type; 141 142 assert(val); 143 if(!val) 144 return FALSE; 145 146 vec_type = LLVMTypeOf(val); 147 148 return lp_check_vec_type(type, vec_type); 149} 150 151 152LLVMTypeRef 153lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type) 154{ 155 return LLVMIntTypeInContext(gallivm->context, type.width); 156} 157 158 159LLVMTypeRef 160lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type) 161{ 162 LLVMTypeRef elem_type = lp_build_int_elem_type(gallivm, type); 163 if (type.length == 1) 164 return elem_type; 165 else 166 return LLVMVectorType(elem_type, type.length); 167} 168 169 170/** 171 * Build int32[4] vector type 172 */ 173LLVMTypeRef 174lp_build_int32_vec4_type(struct gallivm_state *gallivm) 175{ 176 struct lp_type t; 177 LLVMTypeRef type; 178 179 memset(&t, 0, sizeof(t)); 180 t.floating = FALSE; /* floating point values */ 181 t.sign = TRUE; /* values are signed */ 182 t.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ 183 t.width = 32; /* 32-bit int */ 184 t.length = 4; /* 4 elements per vector */ 185 186 type = lp_build_int_elem_type(gallivm, t); 187 return LLVMVectorType(type, t.length); 188} 189 190 191/** 192 * Create element of vector type 193 */ 194struct lp_type 195lp_elem_type(struct lp_type type) 196{ 197 struct lp_type res_type; 198 199 assert(type.length > 1); 200 res_type = type; 201 res_type.length = 1; 202 203 return res_type; 204} 205 206 207/** 208 * Create unsigned integer type variation of given type. 209 */ 210struct lp_type 211lp_uint_type(struct lp_type type) 212{ 213 struct lp_type res_type; 214 215 assert(type.length <= LP_MAX_VECTOR_LENGTH); 216 memset(&res_type, 0, sizeof res_type); 217 res_type.width = type.width; 218 res_type.length = type.length; 219 220 return res_type; 221} 222 223 224/** 225 * Create signed integer type variation of given type. 226 */ 227struct lp_type 228lp_int_type(struct lp_type type) 229{ 230 struct lp_type res_type; 231 232 assert(type.length <= LP_MAX_VECTOR_LENGTH); 233 memset(&res_type, 0, sizeof res_type); 234 res_type.width = type.width; 235 res_type.length = type.length; 236 res_type.sign = 1; 237 238 return res_type; 239} 240 241 242/** 243 * Return the type with twice the bit width (hence half the number of elements). 244 */ 245struct lp_type 246lp_wider_type(struct lp_type type) 247{ 248 struct lp_type res_type; 249 250 memcpy(&res_type, &type, sizeof res_type); 251 res_type.width *= 2; 252 res_type.length /= 2; 253 254 assert(res_type.length); 255 256 return res_type; 257} 258 259 260/** 261 * Return the size of the LLVMType in bits. 262 * XXX this function doesn't necessarily handle all LLVM types. 263 */ 264unsigned 265lp_sizeof_llvm_type(LLVMTypeRef t) 266{ 267 LLVMTypeKind k = LLVMGetTypeKind(t); 268 269 switch (k) { 270 case LLVMIntegerTypeKind: 271 return LLVMGetIntTypeWidth(t); 272 case LLVMFloatTypeKind: 273 return 8 * sizeof(float); 274 case LLVMDoubleTypeKind: 275 return 8 * sizeof(double); 276 case LLVMVectorTypeKind: 277 { 278 LLVMTypeRef elem = LLVMGetElementType(t); 279 unsigned len = LLVMGetVectorSize(t); 280 return len * lp_sizeof_llvm_type(elem); 281 } 282 break; 283 case LLVMArrayTypeKind: 284 { 285 LLVMTypeRef elem = LLVMGetElementType(t); 286 unsigned len = LLVMGetArrayLength(t); 287 return len * lp_sizeof_llvm_type(elem); 288 } 289 break; 290 default: 291 assert(0 && "Unexpected type in lp_get_llvm_type_size()"); 292 return 0; 293 } 294} 295 296 297/** 298 * Return string name for a LLVMTypeKind. Useful for debugging. 299 */ 300const char * 301lp_typekind_name(LLVMTypeKind t) 302{ 303 switch (t) { 304 case LLVMVoidTypeKind: 305 return "LLVMVoidTypeKind"; 306 case LLVMFloatTypeKind: 307 return "LLVMFloatTypeKind"; 308 case LLVMDoubleTypeKind: 309 return "LLVMDoubleTypeKind"; 310 case LLVMX86_FP80TypeKind: 311 return "LLVMX86_FP80TypeKind"; 312 case LLVMFP128TypeKind: 313 return "LLVMFP128TypeKind"; 314 case LLVMPPC_FP128TypeKind: 315 return "LLVMPPC_FP128TypeKind"; 316 case LLVMLabelTypeKind: 317 return "LLVMLabelTypeKind"; 318 case LLVMIntegerTypeKind: 319 return "LLVMIntegerTypeKind"; 320 case LLVMFunctionTypeKind: 321 return "LLVMFunctionTypeKind"; 322 case LLVMStructTypeKind: 323 return "LLVMStructTypeKind"; 324 case LLVMArrayTypeKind: 325 return "LLVMArrayTypeKind"; 326 case LLVMPointerTypeKind: 327 return "LLVMPointerTypeKind"; 328#if HAVE_LLVM < 0x0300 329 case LLVMOpaqueTypeKind: 330 return "LLVMOpaqueTypeKind"; 331#endif 332 case LLVMVectorTypeKind: 333 return "LLVMVectorTypeKind"; 334 case LLVMMetadataTypeKind: 335 return "LLVMMetadataTypeKind"; 336#if HAVE_LLVM == 0x0207 337 case LLVMUnionTypeKind: 338 return "LLVMUnionTypeKind"; 339#endif 340 default: 341 return "unknown LLVMTypeKind"; 342 } 343} 344 345 346/** 347 * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging. 348 */ 349void 350lp_dump_llvmtype(LLVMTypeRef t) 351{ 352 LLVMTypeKind k = LLVMGetTypeKind(t); 353 354 if (k == LLVMVectorTypeKind) { 355 LLVMTypeRef te = LLVMGetElementType(t); 356 LLVMTypeKind ke = LLVMGetTypeKind(te); 357 unsigned len = LLVMGetVectorSize(t); 358 if (ke == LLVMIntegerTypeKind) { 359 unsigned b = LLVMGetIntTypeWidth(te); 360 debug_printf("Vector [%u] of %u-bit Integer\n", len, b); 361 } 362 else { 363 debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke)); 364 } 365 } 366 else if (k == LLVMArrayTypeKind) { 367 LLVMTypeRef te = LLVMGetElementType(t); 368 LLVMTypeKind ke = LLVMGetTypeKind(te); 369 unsigned len = LLVMGetArrayLength(t); 370 debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke)); 371 } 372 else if (k == LLVMIntegerTypeKind) { 373 unsigned b = LLVMGetIntTypeWidth(t); 374 debug_printf("%u-bit Integer\n", b); 375 } 376 else if (k == LLVMPointerTypeKind) { 377 LLVMTypeRef te = LLVMGetElementType(t); 378 debug_printf("Pointer to "); 379 lp_dump_llvmtype(te); 380 } 381 else { 382 debug_printf("%s\n", lp_typekind_name(k)); 383 } 384} 385 386 387void 388lp_build_context_init(struct lp_build_context *bld, 389 struct gallivm_state *gallivm, 390 struct lp_type type) 391{ 392 bld->gallivm = gallivm; 393 bld->type = type; 394 395 bld->int_elem_type = lp_build_int_elem_type(gallivm, type); 396 if (type.floating) 397 bld->elem_type = lp_build_elem_type(gallivm, type); 398 else 399 bld->elem_type = bld->int_elem_type; 400 401 if (type.length == 1) { 402 bld->int_vec_type = bld->int_elem_type; 403 bld->vec_type = bld->elem_type; 404 } 405 else { 406 bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length); 407 bld->vec_type = LLVMVectorType(bld->elem_type, type.length); 408 } 409 410 bld->undef = LLVMGetUndef(bld->vec_type); 411 bld->zero = LLVMConstNull(bld->vec_type); 412 bld->one = lp_build_one(gallivm, type); 413} 414