Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_type.c
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
35 LLVMTypeRef
36 lp_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
57 LLVMTypeRef
58 lp_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 */
74 boolean
75 lp_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
112 boolean
113 lp_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
136 boolean
137 lp_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
151 LLVMTypeRef
152 lp_build_int_elem_type(struct lp_type type)
153 {
154 return LLVMIntType(type.width);
155 }
156
157
158 LLVMTypeRef
159 lp_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 */
172 LLVMTypeRef
173 lp_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 */
193 struct lp_type
194 lp_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 */
209 struct lp_type
210 lp_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 */
226 struct lp_type
227 lp_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 */
244 struct lp_type
245 lp_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 */
263 unsigned
264 lp_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 */
299 const char *
300 lp_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 */
346 void
347 lp_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
384 void
385 lp_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 }