Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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