1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/**
30bf215546Sopenharmony_ci * @file
31bf215546Sopenharmony_ci * Helper functions for constant building.
32bf215546Sopenharmony_ci *
33bf215546Sopenharmony_ci * @author Jose Fonseca <jfonseca@vmware.com>
34bf215546Sopenharmony_ci */
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include <float.h>
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "util/u_debug.h"
39bf215546Sopenharmony_ci#include "util/u_math.h"
40bf215546Sopenharmony_ci#include "util/half_float.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#include "lp_bld_type.h"
43bf215546Sopenharmony_ci#include "lp_bld_const.h"
44bf215546Sopenharmony_ci#include "lp_bld_init.h"
45bf215546Sopenharmony_ci#include "lp_bld_limits.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ciunsigned
49bf215546Sopenharmony_cilp_mantissa(struct lp_type type)
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   assert(type.floating);
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci   if (type.floating) {
54bf215546Sopenharmony_ci      switch (type.width) {
55bf215546Sopenharmony_ci      case 16:
56bf215546Sopenharmony_ci         return 10;
57bf215546Sopenharmony_ci      case 32:
58bf215546Sopenharmony_ci         return 23;
59bf215546Sopenharmony_ci      case 64:
60bf215546Sopenharmony_ci         return 52;
61bf215546Sopenharmony_ci      default:
62bf215546Sopenharmony_ci         assert(0);
63bf215546Sopenharmony_ci         return 0;
64bf215546Sopenharmony_ci      }
65bf215546Sopenharmony_ci   } else {
66bf215546Sopenharmony_ci      if (type.sign)
67bf215546Sopenharmony_ci         return type.width - 1;
68bf215546Sopenharmony_ci      else
69bf215546Sopenharmony_ci         return type.width;
70bf215546Sopenharmony_ci   }
71bf215546Sopenharmony_ci}
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci/**
75bf215546Sopenharmony_ci * Shift of the unity.
76bf215546Sopenharmony_ci *
77bf215546Sopenharmony_ci * Same as lp_const_scale(), but in terms of shifts.
78bf215546Sopenharmony_ci */
79bf215546Sopenharmony_ciunsigned
80bf215546Sopenharmony_cilp_const_shift(struct lp_type type)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci   if (type.floating)
83bf215546Sopenharmony_ci      return 0;
84bf215546Sopenharmony_ci   else if (type.fixed)
85bf215546Sopenharmony_ci      return type.width/2;
86bf215546Sopenharmony_ci   else if (type.norm)
87bf215546Sopenharmony_ci      return type.sign ? type.width - 1 : type.width;
88bf215546Sopenharmony_ci   else
89bf215546Sopenharmony_ci      return 0;
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ciunsigned
94bf215546Sopenharmony_cilp_const_offset(struct lp_type type)
95bf215546Sopenharmony_ci{
96bf215546Sopenharmony_ci   if (type.floating || type.fixed)
97bf215546Sopenharmony_ci      return 0;
98bf215546Sopenharmony_ci   else if (type.norm)
99bf215546Sopenharmony_ci      return 1;
100bf215546Sopenharmony_ci   else
101bf215546Sopenharmony_ci      return 0;
102bf215546Sopenharmony_ci}
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci/**
106bf215546Sopenharmony_ci * Scaling factor between the LLVM native value and its interpretation.
107bf215546Sopenharmony_ci *
108bf215546Sopenharmony_ci * This is 1.0 for all floating types and unnormalized integers, and something
109bf215546Sopenharmony_ci * else for the fixed points types and normalized integers.
110bf215546Sopenharmony_ci */
111bf215546Sopenharmony_cidouble
112bf215546Sopenharmony_cilp_const_scale(struct lp_type type)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   unsigned long long llscale;
115bf215546Sopenharmony_ci   double dscale;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   llscale = (unsigned long long)1 << lp_const_shift(type);
118bf215546Sopenharmony_ci   llscale -= lp_const_offset(type);
119bf215546Sopenharmony_ci   dscale = (double)llscale;
120bf215546Sopenharmony_ci   assert((unsigned long long)dscale == llscale);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   return dscale;
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci/**
127bf215546Sopenharmony_ci * Minimum value representable by the type.
128bf215546Sopenharmony_ci */
129bf215546Sopenharmony_cidouble
130bf215546Sopenharmony_cilp_const_min(struct lp_type type)
131bf215546Sopenharmony_ci{
132bf215546Sopenharmony_ci   if (!type.sign)
133bf215546Sopenharmony_ci      return 0.0;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   if (type.norm)
136bf215546Sopenharmony_ci      return -1.0;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   if (type.floating) {
139bf215546Sopenharmony_ci      switch (type.width) {
140bf215546Sopenharmony_ci      case 16:
141bf215546Sopenharmony_ci         return -65504;
142bf215546Sopenharmony_ci      case 32:
143bf215546Sopenharmony_ci         return -FLT_MAX;
144bf215546Sopenharmony_ci      case 64:
145bf215546Sopenharmony_ci         return -DBL_MAX;
146bf215546Sopenharmony_ci      default:
147bf215546Sopenharmony_ci         assert(0);
148bf215546Sopenharmony_ci         return 0.0;
149bf215546Sopenharmony_ci      }
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   unsigned bits;
153bf215546Sopenharmony_ci   if (type.fixed)
154bf215546Sopenharmony_ci      /* FIXME: consider the fractional bits? */
155bf215546Sopenharmony_ci      bits = type.width / 2 - 1;
156bf215546Sopenharmony_ci   else
157bf215546Sopenharmony_ci      bits = type.width - 1;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   return (double)-((long long)1 << bits);
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci/**
164bf215546Sopenharmony_ci * Maximum value representable by the type.
165bf215546Sopenharmony_ci */
166bf215546Sopenharmony_cidouble
167bf215546Sopenharmony_cilp_const_max(struct lp_type type)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   if (type.norm)
170bf215546Sopenharmony_ci      return 1.0;
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   if (type.floating) {
173bf215546Sopenharmony_ci      switch (type.width) {
174bf215546Sopenharmony_ci      case 16:
175bf215546Sopenharmony_ci         return 65504;
176bf215546Sopenharmony_ci      case 32:
177bf215546Sopenharmony_ci         return FLT_MAX;
178bf215546Sopenharmony_ci      case 64:
179bf215546Sopenharmony_ci         return DBL_MAX;
180bf215546Sopenharmony_ci      default:
181bf215546Sopenharmony_ci         assert(0);
182bf215546Sopenharmony_ci         return 0.0;
183bf215546Sopenharmony_ci      }
184bf215546Sopenharmony_ci   }
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   unsigned bits;
187bf215546Sopenharmony_ci   if (type.fixed)
188bf215546Sopenharmony_ci      bits = type.width / 2;
189bf215546Sopenharmony_ci   else
190bf215546Sopenharmony_ci      bits = type.width;
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   if (type.sign)
193bf215546Sopenharmony_ci      bits -= 1;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   return (double)(((unsigned long long)1 << bits) - 1);
196bf215546Sopenharmony_ci}
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_cidouble
200bf215546Sopenharmony_cilp_const_eps(struct lp_type type)
201bf215546Sopenharmony_ci{
202bf215546Sopenharmony_ci   if (type.floating) {
203bf215546Sopenharmony_ci      switch (type.width) {
204bf215546Sopenharmony_ci      case 16:
205bf215546Sopenharmony_ci         return 2E-10;
206bf215546Sopenharmony_ci      case 32:
207bf215546Sopenharmony_ci         return FLT_EPSILON;
208bf215546Sopenharmony_ci      case 64:
209bf215546Sopenharmony_ci         return DBL_EPSILON;
210bf215546Sopenharmony_ci      default:
211bf215546Sopenharmony_ci         assert(0);
212bf215546Sopenharmony_ci         return 0.0;
213bf215546Sopenharmony_ci      }
214bf215546Sopenharmony_ci   } else {
215bf215546Sopenharmony_ci      double scale = lp_const_scale(type);
216bf215546Sopenharmony_ci      return 1.0/scale;
217bf215546Sopenharmony_ci   }
218bf215546Sopenharmony_ci}
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ciLLVMValueRef
222bf215546Sopenharmony_cilp_build_undef(struct gallivm_state *gallivm, struct lp_type type)
223bf215546Sopenharmony_ci{
224bf215546Sopenharmony_ci   LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
225bf215546Sopenharmony_ci   return LLVMGetUndef(vec_type);
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ciLLVMValueRef
230bf215546Sopenharmony_cilp_build_zero(struct gallivm_state *gallivm, struct lp_type type)
231bf215546Sopenharmony_ci{
232bf215546Sopenharmony_ci   if (type.length == 1) {
233bf215546Sopenharmony_ci      if (type.floating)
234bf215546Sopenharmony_ci         return lp_build_const_float(gallivm, 0.0);
235bf215546Sopenharmony_ci      else
236bf215546Sopenharmony_ci         return LLVMConstInt(LLVMIntTypeInContext(gallivm->context, type.width), 0, 0);
237bf215546Sopenharmony_ci   } else {
238bf215546Sopenharmony_ci      LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
239bf215546Sopenharmony_ci      return LLVMConstNull(vec_type);
240bf215546Sopenharmony_ci   }
241bf215546Sopenharmony_ci}
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ciLLVMValueRef
245bf215546Sopenharmony_cilp_build_one(struct gallivm_state *gallivm, struct lp_type type)
246bf215546Sopenharmony_ci{
247bf215546Sopenharmony_ci   LLVMTypeRef elem_type;
248bf215546Sopenharmony_ci   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   assert(type.length <= LP_MAX_VECTOR_LENGTH);
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci   elem_type = lp_build_elem_type(gallivm, type);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   if (!lp_has_fp16() && type.floating && type.width == 16)
255bf215546Sopenharmony_ci      elems[0] = LLVMConstInt(elem_type, _mesa_float_to_half(1.0f), 0);
256bf215546Sopenharmony_ci   else if (type.floating)
257bf215546Sopenharmony_ci      elems[0] = LLVMConstReal(elem_type, 1.0);
258bf215546Sopenharmony_ci   else if (type.fixed)
259bf215546Sopenharmony_ci      elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0);
260bf215546Sopenharmony_ci   else if (!type.norm)
261bf215546Sopenharmony_ci      elems[0] = LLVMConstInt(elem_type, 1, 0);
262bf215546Sopenharmony_ci   else if (type.sign)
263bf215546Sopenharmony_ci      elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0);
264bf215546Sopenharmony_ci   else {
265bf215546Sopenharmony_ci      /* special case' -- 1.0 for normalized types is more easily attained if
266bf215546Sopenharmony_ci       * we start with a vector consisting of all bits set */
267bf215546Sopenharmony_ci      LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
268bf215546Sopenharmony_ci      LLVMValueRef vec = LLVMConstAllOnes(vec_type);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci#if 0
271bf215546Sopenharmony_ci      if (type.sign)
272bf215546Sopenharmony_ci         /* TODO: Unfortunately this caused "Tried to create a shift operation
273bf215546Sopenharmony_ci          * on a non-integer type!" */
274bf215546Sopenharmony_ci         vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1));
275bf215546Sopenharmony_ci#endif
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci      return vec;
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   for (unsigned i = 1; i < type.length; ++i)
281bf215546Sopenharmony_ci      elems[i] = elems[0];
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   if (type.length == 1)
284bf215546Sopenharmony_ci      return elems[0];
285bf215546Sopenharmony_ci   else
286bf215546Sopenharmony_ci      return LLVMConstVector(elems, type.length);
287bf215546Sopenharmony_ci}
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci/**
291bf215546Sopenharmony_ci * Build constant-valued element from a scalar value.
292bf215546Sopenharmony_ci */
293bf215546Sopenharmony_ciLLVMValueRef
294bf215546Sopenharmony_cilp_build_const_elem(struct gallivm_state *gallivm,
295bf215546Sopenharmony_ci                    struct lp_type type,
296bf215546Sopenharmony_ci                    double val)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   LLVMTypeRef elem_type = lp_build_elem_type(gallivm, type);
299bf215546Sopenharmony_ci   LLVMValueRef elem;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   if (!lp_has_fp16() && type.floating && type.width == 16) {
302bf215546Sopenharmony_ci      elem = LLVMConstInt(elem_type, _mesa_float_to_half((float)val), 0);
303bf215546Sopenharmony_ci   } else if (type.floating) {
304bf215546Sopenharmony_ci      elem = LLVMConstReal(elem_type, val);
305bf215546Sopenharmony_ci   } else {
306bf215546Sopenharmony_ci      double dscale = lp_const_scale(type);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci      elem = LLVMConstInt(elem_type, (long long) round(val*dscale), 0);
309bf215546Sopenharmony_ci   }
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   return elem;
312bf215546Sopenharmony_ci}
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci/**
316bf215546Sopenharmony_ci * Build constant-valued vector from a scalar value.
317bf215546Sopenharmony_ci */
318bf215546Sopenharmony_ciLLVMValueRef
319bf215546Sopenharmony_cilp_build_const_vec(struct gallivm_state *gallivm, struct lp_type type,
320bf215546Sopenharmony_ci                   double val)
321bf215546Sopenharmony_ci{
322bf215546Sopenharmony_ci   if (type.length == 1) {
323bf215546Sopenharmony_ci      return lp_build_const_elem(gallivm, type, val);
324bf215546Sopenharmony_ci   } else {
325bf215546Sopenharmony_ci      LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
326bf215546Sopenharmony_ci      elems[0] = lp_build_const_elem(gallivm, type, val);
327bf215546Sopenharmony_ci      for (unsigned i = 1; i < type.length; ++i)
328bf215546Sopenharmony_ci         elems[i] = elems[0];
329bf215546Sopenharmony_ci      return LLVMConstVector(elems, type.length);
330bf215546Sopenharmony_ci   }
331bf215546Sopenharmony_ci}
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ciLLVMValueRef
335bf215546Sopenharmony_cilp_build_const_int_vec(struct gallivm_state *gallivm, struct lp_type type,
336bf215546Sopenharmony_ci                       long long val)
337bf215546Sopenharmony_ci{
338bf215546Sopenharmony_ci   LLVMTypeRef elem_type = lp_build_int_elem_type(gallivm, type);
339bf215546Sopenharmony_ci   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   assert(type.length <= LP_MAX_VECTOR_LENGTH);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   for (unsigned i = 0; i < type.length; ++i)
344bf215546Sopenharmony_ci      elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0);
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   if (type.length == 1)
347bf215546Sopenharmony_ci      return elems[0];
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   return LLVMConstVector(elems, type.length);
350bf215546Sopenharmony_ci}
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ciLLVMValueRef
354bf215546Sopenharmony_cilp_build_const_aos(struct gallivm_state *gallivm,
355bf215546Sopenharmony_ci                   struct lp_type type,
356bf215546Sopenharmony_ci                   double r, double g, double b, double a,
357bf215546Sopenharmony_ci                   const unsigned char *swizzle)
358bf215546Sopenharmony_ci{
359bf215546Sopenharmony_ci   const unsigned char default_swizzle[4] = {0, 1, 2, 3};
360bf215546Sopenharmony_ci   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   assert(type.length % 4 == 0);
363bf215546Sopenharmony_ci   assert(type.length <= LP_MAX_VECTOR_LENGTH);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   lp_build_elem_type(gallivm, type);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   if (!swizzle)
368bf215546Sopenharmony_ci      swizzle = default_swizzle;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   elems[swizzle[0]] = lp_build_const_elem(gallivm, type, r);
371bf215546Sopenharmony_ci   elems[swizzle[1]] = lp_build_const_elem(gallivm, type, g);
372bf215546Sopenharmony_ci   elems[swizzle[2]] = lp_build_const_elem(gallivm, type, b);
373bf215546Sopenharmony_ci   elems[swizzle[3]] = lp_build_const_elem(gallivm, type, a);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   for (unsigned i = 4; i < type.length; ++i)
376bf215546Sopenharmony_ci      elems[i] = elems[i % 4];
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   return LLVMConstVector(elems, type.length);
379bf215546Sopenharmony_ci}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci/**
383bf215546Sopenharmony_ci * @param mask TGSI_WRITEMASK_xxx
384bf215546Sopenharmony_ci */
385bf215546Sopenharmony_ciLLVMValueRef
386bf215546Sopenharmony_cilp_build_const_mask_aos(struct gallivm_state *gallivm,
387bf215546Sopenharmony_ci                        struct lp_type type,
388bf215546Sopenharmony_ci                        unsigned mask,
389bf215546Sopenharmony_ci                        unsigned channels)
390bf215546Sopenharmony_ci{
391bf215546Sopenharmony_ci   LLVMTypeRef elem_type = LLVMIntTypeInContext(gallivm->context, type.width);
392bf215546Sopenharmony_ci   LLVMValueRef masks[LP_MAX_VECTOR_LENGTH];
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   assert(type.length <= LP_MAX_VECTOR_LENGTH);
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   for (unsigned j = 0; j < type.length; j += channels) {
397bf215546Sopenharmony_ci      for (unsigned i = 0; i < channels; ++i) {
398bf215546Sopenharmony_ci         masks[j + i] = LLVMConstInt(elem_type,
399bf215546Sopenharmony_ci                                     mask & (1 << i) ? ~0ULL : 0,
400bf215546Sopenharmony_ci                                     1);
401bf215546Sopenharmony_ci      }
402bf215546Sopenharmony_ci   }
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci   return LLVMConstVector(masks, type.length);
405bf215546Sopenharmony_ci}
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci/**
409bf215546Sopenharmony_ci * Performs lp_build_const_mask_aos, but first swizzles the mask
410bf215546Sopenharmony_ci */
411bf215546Sopenharmony_ciLLVMValueRef
412bf215546Sopenharmony_cilp_build_const_mask_aos_swizzled(struct gallivm_state *gallivm,
413bf215546Sopenharmony_ci                                 struct lp_type type,
414bf215546Sopenharmony_ci                                 unsigned mask,
415bf215546Sopenharmony_ci                                 unsigned channels,
416bf215546Sopenharmony_ci                                 const unsigned char *swizzle)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   unsigned mask_swizzled = 0;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   for (unsigned i = 0; i < channels; ++i) {
421bf215546Sopenharmony_ci      if (swizzle[i] < 4) {
422bf215546Sopenharmony_ci         mask_swizzled |= ((mask & (1 << swizzle[i])) >> swizzle[i]) << i;
423bf215546Sopenharmony_ci      }
424bf215546Sopenharmony_ci   }
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   return lp_build_const_mask_aos(gallivm, type, mask_swizzled, channels);
427bf215546Sopenharmony_ci}
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci/**
431bf215546Sopenharmony_ci * Build a zero-terminated constant string.
432bf215546Sopenharmony_ci */
433bf215546Sopenharmony_ciLLVMValueRef
434bf215546Sopenharmony_cilp_build_const_string(struct gallivm_state *gallivm,
435bf215546Sopenharmony_ci                      const char *str)
436bf215546Sopenharmony_ci{
437bf215546Sopenharmony_ci   unsigned len = strlen(str) + 1;
438bf215546Sopenharmony_ci   LLVMTypeRef i8 = LLVMInt8TypeInContext(gallivm->context);
439bf215546Sopenharmony_ci   LLVMValueRef string = LLVMAddGlobal(gallivm->module, LLVMArrayType(i8, len), "");
440bf215546Sopenharmony_ci   LLVMSetGlobalConstant(string, TRUE);
441bf215546Sopenharmony_ci   LLVMSetLinkage(string, LLVMInternalLinkage);
442bf215546Sopenharmony_ci   LLVMSetInitializer(string, LLVMConstStringInContext(gallivm->context, str, len, TRUE));
443bf215546Sopenharmony_ci   string = LLVMConstBitCast(string, LLVMPointerType(i8, 0));
444bf215546Sopenharmony_ci   return string;
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ciLLVMValueRef
449bf215546Sopenharmony_cilp_build_const_func_pointer_from_type(struct gallivm_state *gallivm,
450bf215546Sopenharmony_ci                                      const void *ptr,
451bf215546Sopenharmony_ci                                      LLVMTypeRef function_type,
452bf215546Sopenharmony_ci                                      const char *name)
453bf215546Sopenharmony_ci{
454bf215546Sopenharmony_ci   return LLVMBuildBitCast(gallivm->builder,
455bf215546Sopenharmony_ci                           lp_build_const_int_pointer(gallivm, ptr),
456bf215546Sopenharmony_ci                           LLVMPointerType(function_type, 0),
457bf215546Sopenharmony_ci                           name);
458bf215546Sopenharmony_ci}
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci/**
462bf215546Sopenharmony_ci * Build a callable function pointer.
463bf215546Sopenharmony_ci *
464bf215546Sopenharmony_ci * We use function pointer constants instead of LLVMAddGlobalMapping()
465bf215546Sopenharmony_ci * to work around a bug in LLVM 2.6, and for efficiency/simplicity.
466bf215546Sopenharmony_ci */
467bf215546Sopenharmony_ciLLVMValueRef
468bf215546Sopenharmony_cilp_build_const_func_pointer(struct gallivm_state *gallivm,
469bf215546Sopenharmony_ci                            const void *ptr,
470bf215546Sopenharmony_ci                            LLVMTypeRef ret_type,
471bf215546Sopenharmony_ci                            LLVMTypeRef *arg_types,
472bf215546Sopenharmony_ci                            unsigned num_args,
473bf215546Sopenharmony_ci                            const char *name)
474bf215546Sopenharmony_ci{
475bf215546Sopenharmony_ci   LLVMTypeRef function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0);
476bf215546Sopenharmony_ci   return lp_build_const_func_pointer_from_type(gallivm, ptr, function_type, name);
477bf215546Sopenharmony_ci}
478