Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. /**
  30.  * @file
  31.  * Helper functions for constant building.
  32.  *
  33.  * @author Jose Fonseca <jfonseca@vmware.com>
  34.  */
  35.  
  36. #include <float.h>
  37.  
  38. #include "util/u_debug.h"
  39. #include "util/u_math.h"
  40. #include "util/u_half.h"
  41.  
  42. #include "lp_bld_type.h"
  43. #include "lp_bld_const.h"
  44. #include "lp_bld_init.h"
  45.  
  46.  
  47. unsigned
  48. lp_mantissa(struct lp_type type)
  49. {
  50.    assert(type.floating);
  51.  
  52.    if(type.floating) {
  53.       switch(type.width) {
  54.       case 16:
  55.          return 10;
  56.       case 32:
  57.          return 23;
  58.       case 64:
  59.          return 52;
  60.       default:
  61.          assert(0);
  62.          return 0;
  63.       }
  64.    }
  65.    else {
  66.       if(type.sign)
  67.          return type.width - 1;
  68.       else
  69.          return type.width;
  70.    }
  71. }
  72.  
  73.  
  74. /**
  75.  * Shift of the unity.
  76.  *
  77.  * Same as lp_const_scale(), but in terms of shifts.
  78.  */
  79. unsigned
  80. lp_const_shift(struct lp_type type)
  81. {
  82.    if(type.floating)
  83.       return 0;
  84.    else if(type.fixed)
  85.       return type.width/2;
  86.    else if(type.norm)
  87.       return type.sign ? type.width - 1 : type.width;
  88.    else
  89.       return 0;
  90. }
  91.  
  92.  
  93. unsigned
  94. lp_const_offset(struct lp_type type)
  95. {
  96.    if(type.floating || type.fixed)
  97.       return 0;
  98.    else if(type.norm)
  99.       return 1;
  100.    else
  101.       return 0;
  102. }
  103.  
  104.  
  105. /**
  106.  * Scaling factor between the LLVM native value and its interpretation.
  107.  *
  108.  * This is 1.0 for all floating types and unnormalized integers, and something
  109.  * else for the fixed points types and normalized integers.
  110.  */
  111. double
  112. lp_const_scale(struct lp_type type)
  113. {
  114.    unsigned long long llscale;
  115.    double dscale;
  116.  
  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);
  121.  
  122.    return dscale;
  123. }
  124.  
  125.  
  126. /**
  127.  * Minimum value representable by the type.
  128.  */
  129. double
  130. lp_const_min(struct lp_type type)
  131. {
  132.    unsigned bits;
  133.  
  134.    if(!type.sign)
  135.       return 0.0;
  136.  
  137.    if(type.norm)
  138.       return -1.0;
  139.  
  140.    if (type.floating) {
  141.       switch(type.width) {
  142.       case 16:
  143.          return -65504;
  144.       case 32:
  145.          return -FLT_MAX;
  146.       case 64:
  147.          return -DBL_MAX;
  148.       default:
  149.          assert(0);
  150.          return 0.0;
  151.       }
  152.    }
  153.  
  154.    if(type.fixed)
  155.       /* FIXME: consider the fractional bits? */
  156.       bits = type.width / 2 - 1;
  157.    else
  158.       bits = type.width - 1;
  159.  
  160.    return (double)-((long long)1 << bits);
  161. }
  162.  
  163.  
  164. /**
  165.  * Maximum value representable by the type.
  166.  */
  167. double
  168. lp_const_max(struct lp_type type)
  169. {
  170.    unsigned bits;
  171.  
  172.    if(type.norm)
  173.       return 1.0;
  174.  
  175.    if (type.floating) {
  176.       switch(type.width) {
  177.       case 16:
  178.          return 65504;
  179.       case 32:
  180.          return FLT_MAX;
  181.       case 64:
  182.          return DBL_MAX;
  183.       default:
  184.          assert(0);
  185.          return 0.0;
  186.       }
  187.    }
  188.  
  189.    if(type.fixed)
  190.       bits = type.width / 2;
  191.    else
  192.       bits = type.width;
  193.  
  194.    if(type.sign)
  195.       bits -= 1;
  196.  
  197.    return (double)(((unsigned long long)1 << bits) - 1);
  198. }
  199.  
  200.  
  201. double
  202. lp_const_eps(struct lp_type type)
  203. {
  204.    if (type.floating) {
  205.       switch(type.width) {
  206.       case 16:
  207.          return 2E-10;
  208.       case 32:
  209.          return FLT_EPSILON;
  210.       case 64:
  211.          return DBL_EPSILON;
  212.       default:
  213.          assert(0);
  214.          return 0.0;
  215.       }
  216.    }
  217.    else {
  218.       double scale = lp_const_scale(type);
  219.       return 1.0/scale;
  220.    }
  221. }
  222.  
  223.  
  224. LLVMValueRef
  225. lp_build_undef(struct gallivm_state *gallivm, struct lp_type type)
  226. {
  227.    LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
  228.    return LLVMGetUndef(vec_type);
  229. }
  230.                
  231.  
  232. LLVMValueRef
  233. lp_build_zero(struct gallivm_state *gallivm, struct lp_type type)
  234. {
  235.    if (type.length == 1) {
  236.       if (type.floating)
  237.          return lp_build_const_float(gallivm, 0.0);
  238.       else
  239.          return LLVMConstInt(LLVMIntTypeInContext(gallivm->context, type.width), 0, 0);
  240.    }
  241.    else {
  242.       LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
  243.       return LLVMConstNull(vec_type);
  244.    }
  245. }
  246.                
  247.  
  248. LLVMValueRef
  249. lp_build_one(struct gallivm_state *gallivm, struct lp_type type)
  250. {
  251.    LLVMTypeRef elem_type;
  252.    LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
  253.    unsigned i;
  254.  
  255.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  256.  
  257.    elem_type = lp_build_elem_type(gallivm, type);
  258.  
  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);
  263.    else if(type.fixed)
  264.       elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0);
  265.    else if(!type.norm)
  266.       elems[0] = LLVMConstInt(elem_type, 1, 0);
  267.    else if(type.sign)
  268.       elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0);
  269.    else {
  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);
  274.  
  275. #if 0
  276.       if(type.sign)
  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));
  280. #endif
  281.  
  282.       return vec;
  283.    }
  284.  
  285.    for(i = 1; i < type.length; ++i)
  286.       elems[i] = elems[0];
  287.  
  288.    if (type.length == 1)
  289.       return elems[0];
  290.    else
  291.       return LLVMConstVector(elems, type.length);
  292. }
  293.                
  294.  
  295. /**
  296.  * Build constant-valued element from a scalar value.
  297.  */
  298. LLVMValueRef
  299. lp_build_const_elem(struct gallivm_state *gallivm,
  300.                     struct lp_type type,
  301.                     double val)
  302. {
  303.    LLVMTypeRef elem_type = lp_build_elem_type(gallivm, type);
  304.    LLVMValueRef elem;
  305.  
  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);
  310.    }
  311.    else {
  312.       double dscale = lp_const_scale(type);
  313.  
  314.       elem = LLVMConstInt(elem_type, round(val*dscale), 0);
  315.    }
  316.  
  317.    return elem;
  318. }
  319.  
  320.  
  321. /**
  322.  * Build constant-valued vector from a scalar value.
  323.  */
  324. LLVMValueRef
  325. lp_build_const_vec(struct gallivm_state *gallivm, struct lp_type type,
  326.                    double val)
  327. {
  328.    if (type.length == 1) {
  329.       return lp_build_const_elem(gallivm, type, val);
  330.    } else {
  331.       LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
  332.       unsigned i;
  333.       elems[0] = lp_build_const_elem(gallivm, type, val);
  334.       for(i = 1; i < type.length; ++i)
  335.          elems[i] = elems[0];
  336.       return LLVMConstVector(elems, type.length);
  337.    }
  338. }
  339.  
  340.  
  341. LLVMValueRef
  342. lp_build_const_int_vec(struct gallivm_state *gallivm, struct lp_type type,
  343.                        long long val)
  344. {
  345.    LLVMTypeRef elem_type = lp_build_int_elem_type(gallivm, type);
  346.    LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
  347.    unsigned i;
  348.  
  349.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  350.  
  351.    for(i = 0; i < type.length; ++i)
  352.       elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0);
  353.  
  354.    if (type.length == 1)
  355.       return elems[0];
  356.  
  357.    return LLVMConstVector(elems, type.length);
  358. }
  359.  
  360.  
  361. LLVMValueRef
  362. lp_build_const_aos(struct gallivm_state *gallivm,
  363.                    struct lp_type type,
  364.                    double r, double g, double b, double a,
  365.                    const unsigned char *swizzle)
  366. {
  367.    const unsigned char default_swizzle[4] = {0, 1, 2, 3};
  368.    LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
  369.    unsigned i;
  370.  
  371.    assert(type.length % 4 == 0);
  372.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  373.  
  374.    lp_build_elem_type(gallivm, type);
  375.  
  376.    if(swizzle == NULL)
  377.       swizzle = default_swizzle;
  378.  
  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);
  383.  
  384.    for(i = 4; i < type.length; ++i)
  385.       elems[i] = elems[i % 4];
  386.  
  387.    return LLVMConstVector(elems, type.length);
  388. }
  389.  
  390.  
  391. /**
  392.  * @param mask TGSI_WRITEMASK_xxx
  393.  */
  394. LLVMValueRef
  395. lp_build_const_mask_aos(struct gallivm_state *gallivm,
  396.                         struct lp_type type,
  397.                         unsigned mask,
  398.                         unsigned channels)
  399. {
  400.    LLVMTypeRef elem_type = LLVMIntTypeInContext(gallivm->context, type.width);
  401.    LLVMValueRef masks[LP_MAX_VECTOR_LENGTH];
  402.    unsigned i, j;
  403.  
  404.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  405.  
  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,
  410.                                      1);
  411.       }
  412.    }
  413.  
  414.    return LLVMConstVector(masks, type.length);
  415. }
  416.  
  417.  
  418. /**
  419.  * Performs lp_build_const_mask_aos, but first swizzles the mask
  420.  */
  421. LLVMValueRef
  422. lp_build_const_mask_aos_swizzled(struct gallivm_state *gallivm,
  423.                                  struct lp_type type,
  424.                                  unsigned mask,
  425.                                  unsigned channels,
  426.                                  const unsigned char *swizzle)
  427. {
  428.    unsigned i, mask_swizzled;
  429.    mask_swizzled = 0;
  430.  
  431.    for (i = 0; i < channels; ++i) {
  432.       if (swizzle[i] < 4) {
  433.          mask_swizzled |= ((mask & (1 << swizzle[i])) >> swizzle[i]) << i;
  434.       }
  435.    }
  436.  
  437.    return lp_build_const_mask_aos(gallivm, type, mask_swizzled, channels);
  438. }
  439.  
  440.  
  441. /**
  442.  * Build a zero-terminated constant string.
  443.  */
  444. LLVMValueRef
  445. lp_build_const_string(struct gallivm_state *gallivm,
  446.                       const char *str)
  447. {
  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));
  455.    return string;
  456. }
  457.  
  458.  
  459. /**
  460.  * Build a callable function pointer.
  461.  *
  462.  * We use function pointer constants instead of LLVMAddGlobalMapping()
  463.  * to work around a bug in LLVM 2.6, and for efficiency/simplicity.
  464.  */
  465. LLVMValueRef
  466. lp_build_const_func_pointer(struct gallivm_state *gallivm,
  467.                             const void *ptr,
  468.                             LLVMTypeRef ret_type,
  469.                             LLVMTypeRef *arg_types,
  470.                             unsigned num_args,
  471.                             const char *name)
  472. {
  473.    LLVMTypeRef function_type;
  474.    LLVMValueRef function;
  475.  
  476.    function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0);
  477.  
  478.    function = lp_build_const_int_pointer(gallivm, ptr);
  479.  
  480.    function = LLVMBuildBitCast(gallivm->builder, function,
  481.                                LLVMPointerType(function_type, 0),
  482.                                name);
  483.  
  484.    return function;
  485. }
  486.