lp_bld_type.c revision fb94747b6639ba976aaaaba5a37aa2fe56999310
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 34 35LLVMTypeRef 36lp_build_elem_type(struct lp_type type) 37{ 38 if (type.floating) { 39 switch(type.width) { 40 case 32: 41 return LLVMFloatType(); 42 break; 43 case 64: 44 return LLVMDoubleType(); 45 break; 46 default: 47 assert(0); 48 return LLVMFloatType(); 49 } 50 } 51 else { 52 return LLVMIntType(type.width); 53 } 54} 55 56 57LLVMTypeRef 58lp_build_vec_type(struct lp_type type) 59{ 60 LLVMTypeRef elem_type = lp_build_elem_type(type); 61 if (type.length == 1) 62 return elem_type; 63 else 64 return LLVMVectorType(elem_type, type.length); 65} 66 67 68/** 69 * This function is a mirror of lp_build_elem_type() above. 70 * 71 * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the 72 * type and check for identity. 73 */ 74boolean 75lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type) 76{ 77 LLVMTypeKind elem_kind; 78 79 assert(elem_type); 80 if(!elem_type) 81 return FALSE; 82 83 elem_kind = LLVMGetTypeKind(elem_type); 84 85 if (type.floating) { 86 switch(type.width) { 87 case 32: 88 if(elem_kind != LLVMFloatTypeKind) 89 return FALSE; 90 break; 91 case 64: 92 if(elem_kind != LLVMDoubleTypeKind) 93 return FALSE; 94 break; 95 default: 96 assert(0); 97 return FALSE; 98 } 99 } 100 else { 101 if(elem_kind != LLVMIntegerTypeKind) 102 return FALSE; 103 104 if(LLVMGetIntTypeWidth(elem_type) != type.width) 105 return FALSE; 106 } 107 108 return TRUE; 109} 110 111 112boolean 113lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type) 114{ 115 LLVMTypeRef elem_type; 116 117 assert(vec_type); 118 if(!vec_type) 119 return FALSE; 120 121 if (type.length == 1) 122 return lp_check_elem_type(type, vec_type); 123 124 if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) 125 return FALSE; 126 127 if(LLVMGetVectorSize(vec_type) != type.length) 128 return FALSE; 129 130 elem_type = LLVMGetElementType(vec_type); 131 132 return lp_check_elem_type(type, elem_type); 133} 134 135 136boolean 137lp_check_value(struct lp_type type, LLVMValueRef val) 138{ 139 LLVMTypeRef vec_type; 140 141 assert(val); 142 if(!val) 143 return FALSE; 144 145 vec_type = LLVMTypeOf(val); 146 147 return lp_check_vec_type(type, vec_type); 148} 149 150 151LLVMTypeRef 152lp_build_int_elem_type(struct lp_type type) 153{ 154 return LLVMIntType(type.width); 155} 156 157 158LLVMTypeRef 159lp_build_int_vec_type(struct lp_type type) 160{ 161 LLVMTypeRef elem_type = lp_build_int_elem_type(type); 162 if (type.length == 1) 163 return elem_type; 164 else 165 return LLVMVectorType(elem_type, type.length); 166} 167 168 169/** 170 * Build int32[4] vector type 171 */ 172LLVMTypeRef 173lp_build_int32_vec4_type(void) 174{ 175 struct lp_type t; 176 LLVMTypeRef type; 177 178 memset(&t, 0, sizeof(t)); 179 t.floating = FALSE; /* floating point values */ 180 t.sign = TRUE; /* values are signed */ 181 t.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ 182 t.width = 32; /* 32-bit int */ 183 t.length = 4; /* 4 elements per vector */ 184 185 type = lp_build_int_elem_type(t); 186 return LLVMVectorType(type, t.length); 187} 188 189 190/** 191 * Create element of vector type 192 */ 193struct lp_type 194lp_elem_type(struct lp_type type) 195{ 196 struct lp_type res_type; 197 198 assert(type.length > 1); 199 res_type = type; 200 res_type.length = 1; 201 202 return res_type; 203} 204 205 206/** 207 * Create unsigned integer type variation of given type. 208 */ 209struct lp_type 210lp_uint_type(struct lp_type type) 211{ 212 struct lp_type res_type; 213 214 assert(type.length <= LP_MAX_VECTOR_LENGTH); 215 memset(&res_type, 0, sizeof res_type); 216 res_type.width = type.width; 217 res_type.length = type.length; 218 219 return res_type; 220} 221 222 223/** 224 * Create signed integer type variation of given type. 225 */ 226struct lp_type 227lp_int_type(struct lp_type type) 228{ 229 struct lp_type res_type; 230 231 assert(type.length <= LP_MAX_VECTOR_LENGTH); 232 memset(&res_type, 0, sizeof res_type); 233 res_type.width = type.width; 234 res_type.length = type.length; 235 res_type.sign = 1; 236 237 return res_type; 238} 239 240 241/** 242 * Return the type with twice the bit width (hence half the number of elements). 243 */ 244struct lp_type 245lp_wider_type(struct lp_type type) 246{ 247 struct lp_type res_type; 248 249 memcpy(&res_type, &type, sizeof res_type); 250 res_type.width *= 2; 251 res_type.length /= 2; 252 253 assert(res_type.length); 254 255 return res_type; 256} 257 258 259/** 260 * Return the size of the LLVMType in bits. 261 * XXX this function doesn't necessarily handle all LLVM types. 262 */ 263unsigned 264lp_sizeof_llvm_type(LLVMTypeRef t) 265{ 266 LLVMTypeKind k = LLVMGetTypeKind(t); 267 268 switch (k) { 269 case LLVMIntegerTypeKind: 270 return LLVMGetIntTypeWidth(t); 271 case LLVMFloatTypeKind: 272 return 8 * sizeof(float); 273 case LLVMDoubleTypeKind: 274 return 8 * sizeof(double); 275 case LLVMVectorTypeKind: 276 { 277 LLVMTypeRef elem = LLVMGetElementType(t); 278 unsigned len = LLVMGetVectorSize(t); 279 return len * lp_sizeof_llvm_type(elem); 280 } 281 break; 282 case LLVMArrayTypeKind: 283 { 284 LLVMTypeRef elem = LLVMGetElementType(t); 285 unsigned len = LLVMGetArrayLength(t); 286 return len * lp_sizeof_llvm_type(elem); 287 } 288 break; 289 default: 290 assert(0 && "Unexpected type in lp_get_llvm_type_size()"); 291 return 0; 292 } 293} 294 295 296/** 297 * Return string name for a LLVMTypeKind. Useful for debugging. 298 */ 299const char * 300lp_typekind_name(LLVMTypeKind t) 301{ 302 switch (t) { 303 case LLVMVoidTypeKind: 304 return "LLVMVoidTypeKind"; 305 case LLVMFloatTypeKind: 306 return "LLVMFloatTypeKind"; 307 case LLVMDoubleTypeKind: 308 return "LLVMDoubleTypeKind"; 309 case LLVMX86_FP80TypeKind: 310 return "LLVMX86_FP80TypeKind"; 311 case LLVMFP128TypeKind: 312 return "LLVMFP128TypeKind"; 313 case LLVMPPC_FP128TypeKind: 314 return "LLVMPPC_FP128TypeKind"; 315 case LLVMLabelTypeKind: 316 return "LLVMLabelTypeKind"; 317 case LLVMIntegerTypeKind: 318 return "LLVMIntegerTypeKind"; 319 case LLVMFunctionTypeKind: 320 return "LLVMFunctionTypeKind"; 321 case LLVMStructTypeKind: 322 return "LLVMStructTypeKind"; 323 case LLVMArrayTypeKind: 324 return "LLVMArrayTypeKind"; 325 case LLVMPointerTypeKind: 326 return "LLVMPointerTypeKind"; 327 case LLVMOpaqueTypeKind: 328 return "LLVMOpaqueTypeKind"; 329 case LLVMVectorTypeKind: 330 return "LLVMVectorTypeKind"; 331 case LLVMMetadataTypeKind: 332 return "LLVMMetadataTypeKind"; 333 /* Only in LLVM 2.7 and later??? 334 case LLVMUnionTypeKind: 335 return "LLVMUnionTypeKind"; 336 */ 337 default: 338 return "unknown LLVMTypeKind"; 339 } 340} 341 342 343/** 344 * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging. 345 */ 346void 347lp_dump_llvmtype(LLVMTypeRef t) 348{ 349 LLVMTypeKind k = LLVMGetTypeKind(t); 350 351 if (k == LLVMVectorTypeKind) { 352 LLVMTypeRef te = LLVMGetElementType(t); 353 LLVMTypeKind ke = LLVMGetTypeKind(te); 354 unsigned len = LLVMGetVectorSize(t); 355 if (ke == LLVMIntegerTypeKind) { 356 unsigned b = LLVMGetIntTypeWidth(te); 357 debug_printf("Vector [%u] of %u-bit Integer\n", len, b); 358 } 359 else { 360 debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke)); 361 } 362 } 363 else if (k == LLVMArrayTypeKind) { 364 LLVMTypeRef te = LLVMGetElementType(t); 365 LLVMTypeKind ke = LLVMGetTypeKind(te); 366 unsigned len = LLVMGetArrayLength(t); 367 debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke)); 368 } 369 else if (k == LLVMIntegerTypeKind) { 370 unsigned b = LLVMGetIntTypeWidth(t); 371 debug_printf("%u-bit Integer\n", b); 372 } 373 else if (k == LLVMPointerTypeKind) { 374 LLVMTypeRef te = LLVMGetElementType(t); 375 debug_printf("Pointer to "); 376 lp_dump_llvmtype(te); 377 } 378 else { 379 debug_printf("%s\n", lp_typekind_name(k)); 380 } 381} 382 383 384void 385lp_build_context_init(struct lp_build_context *bld, 386 LLVMBuilderRef builder, 387 struct lp_type type) 388{ 389 bld->builder = builder; 390 bld->type = type; 391 392 bld->int_elem_type = lp_build_int_elem_type(type); 393 if (type.floating) 394 bld->elem_type = lp_build_elem_type(type); 395 else 396 bld->elem_type = bld->int_elem_type; 397 398 if (type.length == 1) { 399 bld->int_vec_type = bld->int_elem_type; 400 bld->vec_type = bld->elem_type; 401 } 402 else { 403 bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length); 404 bld->vec_type = LLVMVectorType(bld->elem_type, type.length); 405 } 406 407 bld->undef = LLVMGetUndef(bld->vec_type); 408 bld->zero = LLVMConstNull(bld->vec_type); 409 bld->one = lp_build_one(type); 410} 411