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