gallivm: Fix for dynamically linked LLVM 2.8 library.
[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 #include "lp_bld_init.h"
34
35
36 LLVMTypeRef
37 lp_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
58 LLVMTypeRef
59 lp_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 */
75 boolean
76 lp_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
113 boolean
114 lp_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
137 boolean
138 lp_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
152 LLVMTypeRef
153 lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type)
154 {
155 return LLVMIntTypeInContext(gallivm->context, type.width);
156 }
157
158
159 LLVMTypeRef
160 lp_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 */
173 LLVMTypeRef
174 lp_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 */
194 struct lp_type
195 lp_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 */
210 struct lp_type
211 lp_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 */
227 struct lp_type
228 lp_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 */
245 struct lp_type
246 lp_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 */
264 unsigned
265 lp_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 */
300 const char *
301 lp_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 case LLVMOpaqueTypeKind:
329 return "LLVMOpaqueTypeKind";
330 case LLVMVectorTypeKind:
331 return "LLVMVectorTypeKind";
332 case LLVMMetadataTypeKind:
333 return "LLVMMetadataTypeKind";
334 /* Only in LLVM 2.7 and later???
335 case LLVMUnionTypeKind:
336 return "LLVMUnionTypeKind";
337 */
338 default:
339 return "unknown LLVMTypeKind";
340 }
341 }
342
343
344 /**
345 * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging.
346 */
347 void
348 lp_dump_llvmtype(LLVMTypeRef t)
349 {
350 LLVMTypeKind k = LLVMGetTypeKind(t);
351
352 if (k == LLVMVectorTypeKind) {
353 LLVMTypeRef te = LLVMGetElementType(t);
354 LLVMTypeKind ke = LLVMGetTypeKind(te);
355 unsigned len = LLVMGetVectorSize(t);
356 if (ke == LLVMIntegerTypeKind) {
357 unsigned b = LLVMGetIntTypeWidth(te);
358 debug_printf("Vector [%u] of %u-bit Integer\n", len, b);
359 }
360 else {
361 debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke));
362 }
363 }
364 else if (k == LLVMArrayTypeKind) {
365 LLVMTypeRef te = LLVMGetElementType(t);
366 LLVMTypeKind ke = LLVMGetTypeKind(te);
367 unsigned len = LLVMGetArrayLength(t);
368 debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke));
369 }
370 else if (k == LLVMIntegerTypeKind) {
371 unsigned b = LLVMGetIntTypeWidth(t);
372 debug_printf("%u-bit Integer\n", b);
373 }
374 else if (k == LLVMPointerTypeKind) {
375 LLVMTypeRef te = LLVMGetElementType(t);
376 debug_printf("Pointer to ");
377 lp_dump_llvmtype(te);
378 }
379 else {
380 debug_printf("%s\n", lp_typekind_name(k));
381 }
382 }
383
384
385 void
386 lp_build_context_init(struct lp_build_context *bld,
387 struct gallivm_state *gallivm,
388 struct lp_type type)
389 {
390 bld->gallivm = gallivm;
391 bld->type = type;
392
393 bld->int_elem_type = lp_build_int_elem_type(gallivm, type);
394 if (type.floating)
395 bld->elem_type = lp_build_elem_type(gallivm, type);
396 else
397 bld->elem_type = bld->int_elem_type;
398
399 if (type.length == 1) {
400 bld->int_vec_type = bld->int_elem_type;
401 bld->vec_type = bld->elem_type;
402 }
403 else {
404 bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length);
405 bld->vec_type = LLVMVectorType(bld->elem_type, type.length);
406 }
407
408 bld->undef = LLVMGetUndef(bld->vec_type);
409 bld->zero = LLVMConstNull(bld->vec_type);
410 bld->one = lp_build_one(gallivm, type);
411 }