gallivm: fix lp_build_sample_offset() crash when indexing a 1-D texture
[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 unsigned integer type variation of given type.
192 */
193 struct lp_type
194 lp_uint_type(struct lp_type type)
195 {
196 struct lp_type res_type;
197
198 assert(type.length <= LP_MAX_VECTOR_LENGTH);
199 memset(&res_type, 0, sizeof res_type);
200 res_type.width = type.width;
201 res_type.length = type.length;
202
203 return res_type;
204 }
205
206
207 /**
208 * Create signed integer type variation of given type.
209 */
210 struct lp_type
211 lp_int_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 res_type.sign = 1;
220
221 return res_type;
222 }
223
224
225 /**
226 * Return the type with twice the bit width (hence half the number of elements).
227 */
228 struct lp_type
229 lp_wider_type(struct lp_type type)
230 {
231 struct lp_type res_type;
232
233 memcpy(&res_type, &type, sizeof res_type);
234 res_type.width *= 2;
235 res_type.length /= 2;
236
237 assert(res_type.length);
238
239 return res_type;
240 }
241
242
243 /**
244 * Return the size of the LLVMType in bits.
245 * XXX this function doesn't necessarily handle all LLVM types.
246 */
247 unsigned
248 lp_sizeof_llvm_type(LLVMTypeRef t)
249 {
250 LLVMTypeKind k = LLVMGetTypeKind(t);
251
252 switch (k) {
253 case LLVMIntegerTypeKind:
254 return LLVMGetIntTypeWidth(t);
255 case LLVMFloatTypeKind:
256 return 8 * sizeof(float);
257 case LLVMDoubleTypeKind:
258 return 8 * sizeof(double);
259 case LLVMVectorTypeKind:
260 {
261 LLVMTypeRef elem = LLVMGetElementType(t);
262 unsigned len = LLVMGetVectorSize(t);
263 return len * lp_sizeof_llvm_type(elem);
264 }
265 break;
266 case LLVMArrayTypeKind:
267 {
268 LLVMTypeRef elem = LLVMGetElementType(t);
269 unsigned len = LLVMGetArrayLength(t);
270 return len * lp_sizeof_llvm_type(elem);
271 }
272 break;
273 default:
274 assert(0 && "Unexpected type in lp_get_llvm_type_size()");
275 return 0;
276 }
277 }
278
279
280 /**
281 * Return string name for a LLVMTypeKind. Useful for debugging.
282 */
283 const char *
284 lp_typekind_name(LLVMTypeKind t)
285 {
286 switch (t) {
287 case LLVMVoidTypeKind:
288 return "LLVMVoidTypeKind";
289 case LLVMFloatTypeKind:
290 return "LLVMFloatTypeKind";
291 case LLVMDoubleTypeKind:
292 return "LLVMDoubleTypeKind";
293 case LLVMX86_FP80TypeKind:
294 return "LLVMX86_FP80TypeKind";
295 case LLVMFP128TypeKind:
296 return "LLVMFP128TypeKind";
297 case LLVMPPC_FP128TypeKind:
298 return "LLVMPPC_FP128TypeKind";
299 case LLVMLabelTypeKind:
300 return "LLVMLabelTypeKind";
301 case LLVMIntegerTypeKind:
302 return "LLVMIntegerTypeKind";
303 case LLVMFunctionTypeKind:
304 return "LLVMFunctionTypeKind";
305 case LLVMStructTypeKind:
306 return "LLVMStructTypeKind";
307 case LLVMArrayTypeKind:
308 return "LLVMArrayTypeKind";
309 case LLVMPointerTypeKind:
310 return "LLVMPointerTypeKind";
311 case LLVMOpaqueTypeKind:
312 return "LLVMOpaqueTypeKind";
313 case LLVMVectorTypeKind:
314 return "LLVMVectorTypeKind";
315 case LLVMMetadataTypeKind:
316 return "LLVMMetadataTypeKind";
317 /* Only in LLVM 2.7 and later???
318 case LLVMUnionTypeKind:
319 return "LLVMUnionTypeKind";
320 */
321 default:
322 return "unknown LLVMTypeKind";
323 }
324 }
325
326
327 /**
328 * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging.
329 */
330 void
331 lp_dump_llvmtype(LLVMTypeRef t)
332 {
333 LLVMTypeKind k = LLVMGetTypeKind(t);
334
335 if (k == LLVMVectorTypeKind) {
336 LLVMTypeRef te = LLVMGetElementType(t);
337 LLVMTypeKind ke = LLVMGetTypeKind(te);
338 unsigned len = LLVMGetVectorSize(t);
339 if (ke == LLVMIntegerTypeKind) {
340 unsigned b = LLVMGetIntTypeWidth(te);
341 debug_printf("Vector [%u] of %u-bit Integer\n", len, b);
342 }
343 else {
344 debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke));
345 }
346 }
347 else if (k == LLVMArrayTypeKind) {
348 LLVMTypeRef te = LLVMGetElementType(t);
349 LLVMTypeKind ke = LLVMGetTypeKind(te);
350 unsigned len = LLVMGetArrayLength(t);
351 debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke));
352 }
353 else if (k == LLVMIntegerTypeKind) {
354 unsigned b = LLVMGetIntTypeWidth(t);
355 debug_printf("%u-bit Integer\n", b);
356 }
357 else if (k == LLVMPointerTypeKind) {
358 LLVMTypeRef te = LLVMGetElementType(t);
359 debug_printf("Pointer to ");
360 lp_dump_llvmtype(te);
361 }
362 else {
363 debug_printf("%s\n", lp_typekind_name(k));
364 }
365 }
366
367
368 void
369 lp_build_context_init(struct lp_build_context *bld,
370 LLVMBuilderRef builder,
371 struct lp_type type)
372 {
373 bld->builder = builder;
374 bld->type = type;
375
376 bld->int_elem_type = lp_build_int_elem_type(type);
377 if (type.floating)
378 bld->elem_type = lp_build_elem_type(type);
379 else
380 bld->elem_type = bld->int_elem_type;
381
382 if (type.length == 1) {
383 bld->int_vec_type = bld->int_elem_type;
384 bld->vec_type = bld->elem_type;
385 }
386 else {
387 bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length);
388 bld->vec_type = LLVMVectorType(bld->elem_type, type.length);
389 }
390
391 bld->undef = LLVMGetUndef(bld->vec_type);
392 bld->zero = LLVMConstNull(bld->vec_type);
393 bld->one = lp_build_one(type);
394 }