1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 * Helper functions for constant building.
33 * @author Jose Fonseca <jfonseca@vmware.com>
38 #include "util/u_debug.h"
39 #include "util/u_math.h"
40 #include "util/u_half.h"
42 #include "lp_bld_type.h"
43 #include "lp_bld_const.h"
44 #include "lp_bld_init.h"
48 lp_mantissa(struct lp_type type
)
50 assert(type
.floating
);
67 return type
.width
- 1;
77 * Same as lp_const_scale(), but in terms of shifts.
80 lp_const_shift(struct lp_type type
)
87 return type
.sign
? type
.width
- 1 : type
.width
;
94 lp_const_offset(struct lp_type type
)
96 if(type
.floating
|| type
.fixed
)
106 * Scaling factor between the LLVM native value and its interpretation.
108 * This is 1.0 for all floating types and unnormalized integers, and something
109 * else for the fixed points types and normalized integers.
112 lp_const_scale(struct lp_type type
)
114 unsigned long long llscale
;
117 llscale
= (unsigned long long)1 << lp_const_shift(type
);
118 llscale
-= lp_const_offset(type
);
119 dscale
= (double)llscale
;
120 assert((unsigned long long)dscale
== llscale
);
127 * Minimum value representable by the type.
130 lp_const_min(struct lp_type type
)
155 /* FIXME: consider the fractional bits? */
156 bits
= type
.width
/ 2 - 1;
158 bits
= type
.width
- 1;
160 return (double)-((long long)1 << bits
);
165 * Maximum value representable by the type.
168 lp_const_max(struct lp_type type
)
190 bits
= type
.width
/ 2;
197 return (double)(((unsigned long long)1 << bits
) - 1);
202 lp_const_eps(struct lp_type type
)
218 double scale
= lp_const_scale(type
);
225 lp_build_undef(struct gallivm_state
*gallivm
, struct lp_type type
)
227 LLVMTypeRef vec_type
= lp_build_vec_type(gallivm
, type
);
228 return LLVMGetUndef(vec_type
);
233 lp_build_zero(struct gallivm_state
*gallivm
, struct lp_type type
)
235 if (type
.length
== 1) {
237 return lp_build_const_float(gallivm
, 0.0);
239 return LLVMConstInt(LLVMIntTypeInContext(gallivm
->context
, type
.width
), 0, 0);
242 LLVMTypeRef vec_type
= lp_build_vec_type(gallivm
, type
);
243 return LLVMConstNull(vec_type
);
249 lp_build_one(struct gallivm_state
*gallivm
, struct lp_type type
)
251 LLVMTypeRef elem_type
;
252 LLVMValueRef elems
[LP_MAX_VECTOR_LENGTH
];
255 assert(type
.length
<= LP_MAX_VECTOR_LENGTH
);
257 elem_type
= lp_build_elem_type(gallivm
, type
);
259 if(type
.floating
&& type
.width
== 16)
260 elems
[0] = LLVMConstInt(elem_type
, util_float_to_half(1.0f
), 0);
261 else if(type
.floating
)
262 elems
[0] = LLVMConstReal(elem_type
, 1.0);
264 elems
[0] = LLVMConstInt(elem_type
, 1LL << (type
.width
/2), 0);
266 elems
[0] = LLVMConstInt(elem_type
, 1, 0);
268 elems
[0] = LLVMConstInt(elem_type
, (1LL << (type
.width
- 1)) - 1, 0);
270 /* special case' -- 1.0 for normalized types is more easily attained if
271 * we start with a vector consisting of all bits set */
272 LLVMTypeRef vec_type
= lp_build_vec_type(gallivm
, type
);
273 LLVMValueRef vec
= LLVMConstAllOnes(vec_type
);
277 /* TODO: Unfortunately this caused "Tried to create a shift operation
278 * on a non-integer type!" */
279 vec
= LLVMConstLShr(vec
, lp_build_const_int_vec(type
, 1));
285 for(i
= 1; i
< type
.length
; ++i
)
288 if (type
.length
== 1)
291 return LLVMConstVector(elems
, type
.length
);
296 * Build constant-valued element from a scalar value.
299 lp_build_const_elem(struct gallivm_state
*gallivm
,
303 LLVMTypeRef elem_type
= lp_build_elem_type(gallivm
, type
);
306 if(type
.floating
&& type
.width
== 16) {
307 elem
= LLVMConstInt(elem_type
, util_float_to_half((float)val
), 0);
308 } else if(type
.floating
) {
309 elem
= LLVMConstReal(elem_type
, val
);
312 double dscale
= lp_const_scale(type
);
314 elem
= LLVMConstInt(elem_type
, round(val
*dscale
), 0);
322 * Build constant-valued vector from a scalar value.
325 lp_build_const_vec(struct gallivm_state
*gallivm
, struct lp_type type
,
328 if (type
.length
== 1) {
329 return lp_build_const_elem(gallivm
, type
, val
);
331 LLVMValueRef elems
[LP_MAX_VECTOR_LENGTH
];
333 elems
[0] = lp_build_const_elem(gallivm
, type
, val
);
334 for(i
= 1; i
< type
.length
; ++i
)
336 return LLVMConstVector(elems
, type
.length
);
342 lp_build_const_int_vec(struct gallivm_state
*gallivm
, struct lp_type type
,
345 LLVMTypeRef elem_type
= lp_build_int_elem_type(gallivm
, type
);
346 LLVMValueRef elems
[LP_MAX_VECTOR_LENGTH
];
349 assert(type
.length
<= LP_MAX_VECTOR_LENGTH
);
351 for(i
= 0; i
< type
.length
; ++i
)
352 elems
[i
] = LLVMConstInt(elem_type
, val
, type
.sign
? 1 : 0);
354 if (type
.length
== 1)
357 return LLVMConstVector(elems
, type
.length
);
362 lp_build_const_aos(struct gallivm_state
*gallivm
,
364 double r
, double g
, double b
, double a
,
365 const unsigned char *swizzle
)
367 const unsigned char default_swizzle
[4] = {0, 1, 2, 3};
368 LLVMValueRef elems
[LP_MAX_VECTOR_LENGTH
];
371 assert(type
.length
% 4 == 0);
372 assert(type
.length
<= LP_MAX_VECTOR_LENGTH
);
374 lp_build_elem_type(gallivm
, type
);
377 swizzle
= default_swizzle
;
379 elems
[swizzle
[0]] = lp_build_const_elem(gallivm
, type
, r
);
380 elems
[swizzle
[1]] = lp_build_const_elem(gallivm
, type
, g
);
381 elems
[swizzle
[2]] = lp_build_const_elem(gallivm
, type
, b
);
382 elems
[swizzle
[3]] = lp_build_const_elem(gallivm
, type
, a
);
384 for(i
= 4; i
< type
.length
; ++i
)
385 elems
[i
] = elems
[i
% 4];
387 return LLVMConstVector(elems
, type
.length
);
392 * @param mask TGSI_WRITEMASK_xxx
395 lp_build_const_mask_aos(struct gallivm_state
*gallivm
,
400 LLVMTypeRef elem_type
= LLVMIntTypeInContext(gallivm
->context
, type
.width
);
401 LLVMValueRef masks
[LP_MAX_VECTOR_LENGTH
];
404 assert(type
.length
<= LP_MAX_VECTOR_LENGTH
);
406 for (j
= 0; j
< type
.length
; j
+= channels
) {
407 for( i
= 0; i
< channels
; ++i
) {
408 masks
[j
+ i
] = LLVMConstInt(elem_type
,
409 mask
& (1 << i
) ? ~0ULL : 0,
414 return LLVMConstVector(masks
, type
.length
);
419 * Performs lp_build_const_mask_aos, but first swizzles the mask
422 lp_build_const_mask_aos_swizzled(struct gallivm_state
*gallivm
,
426 const unsigned char *swizzle
)
428 unsigned i
, mask_swizzled
;
431 for (i
= 0; i
< channels
; ++i
) {
432 if (swizzle
[i
] < 4) {
433 mask_swizzled
|= ((mask
& (1 << swizzle
[i
])) >> swizzle
[i
]) << i
;
437 return lp_build_const_mask_aos(gallivm
, type
, mask_swizzled
, channels
);
442 * Build a zero-terminated constant string.
445 lp_build_const_string(struct gallivm_state
*gallivm
,
448 unsigned len
= strlen(str
) + 1;
449 LLVMTypeRef i8
= LLVMInt8TypeInContext(gallivm
->context
);
450 LLVMValueRef string
= LLVMAddGlobal(gallivm
->module
, LLVMArrayType(i8
, len
), "");
451 LLVMSetGlobalConstant(string
, TRUE
);
452 LLVMSetLinkage(string
, LLVMInternalLinkage
);
453 LLVMSetInitializer(string
, LLVMConstStringInContext(gallivm
->context
, str
, len
, TRUE
));
454 string
= LLVMConstBitCast(string
, LLVMPointerType(i8
, 0));
460 * Build a callable function pointer.
462 * We use function pointer constants instead of LLVMAddGlobalMapping()
463 * to work around a bug in LLVM 2.6, and for efficiency/simplicity.
466 lp_build_const_func_pointer(struct gallivm_state
*gallivm
,
468 LLVMTypeRef ret_type
,
469 LLVMTypeRef
*arg_types
,
473 LLVMTypeRef function_type
;
474 LLVMValueRef function
;
476 function_type
= LLVMFunctionType(ret_type
, arg_types
, num_args
, 0);
478 function
= lp_build_const_int_pointer(gallivm
, ptr
);
480 function
= LLVMBuildBitCast(gallivm
->builder
, function
,
481 LLVMPointerType(function_type
, 0),