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