Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2013
  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
  32.  *
  33.  * The functions in this file implement arthmetic operations with support
  34.  * for overflow detection and reporting.
  35.  *
  36.  */
  37.  
  38. #include "lp_bld_arit_overflow.h"
  39.  
  40. #include "lp_bld_type.h"
  41. #include "lp_bld_const.h"
  42. #include "lp_bld_init.h"
  43. #include "lp_bld_intr.h"
  44. #include "lp_bld_logic.h"
  45. #include "lp_bld_pack.h"
  46. #include "lp_bld_debug.h"
  47. #include "lp_bld_bitarit.h"
  48.  
  49. #include "util/u_memory.h"
  50. #include "util/u_debug.h"
  51. #include "util/u_math.h"
  52. #include "util/u_string.h"
  53. #include "util/u_cpu_detect.h"
  54.  
  55. #include <float.h>
  56.  
  57.  
  58. static LLVMValueRef
  59. build_binary_int_overflow(struct gallivm_state *gallivm,
  60.                           const char *intr_prefix,
  61.                           LLVMValueRef a,
  62.                           LLVMValueRef b,
  63.                           LLVMValueRef *ofbit)
  64. {
  65.    LLVMBuilderRef builder = gallivm->builder;
  66.    char intr_str[256];
  67.    LLVMTypeRef type_ref;
  68.    LLVMTypeKind type_kind;
  69.    unsigned type_width;
  70.    LLVMTypeRef oelems[2];
  71.    LLVMValueRef oresult;
  72.    LLVMTypeRef otype;
  73.  
  74.    debug_assert(LLVMTypeOf(a) == LLVMTypeOf(b));
  75.    type_ref = LLVMTypeOf(a);
  76.    type_kind = LLVMGetTypeKind(type_ref);
  77.  
  78.    debug_assert(type_kind == LLVMIntegerTypeKind);
  79.    type_width = LLVMGetIntTypeWidth(type_ref);
  80.  
  81.    debug_assert(type_width == 16 || type_width == 32 || type_width == 64);
  82.  
  83.    util_snprintf(intr_str, sizeof intr_str, "%s.i%u",
  84.                  intr_prefix, type_width);
  85.  
  86.    oelems[0] = type_ref;
  87.    oelems[1] = LLVMInt1TypeInContext(gallivm->context);
  88.  
  89.    otype = LLVMStructTypeInContext(gallivm->context, oelems, 2, FALSE);
  90.    oresult = lp_build_intrinsic_binary(builder, intr_str,
  91.                                        otype, a, b);
  92.    if (ofbit) {
  93.       if (*ofbit) {
  94.          *ofbit = LLVMBuildOr(
  95.             builder, *ofbit,
  96.             LLVMBuildExtractValue(builder, oresult, 1, ""), "");
  97.       } else {
  98.          *ofbit = LLVMBuildExtractValue(builder, oresult, 1, "");
  99.       }
  100.    }
  101.  
  102.    return LLVMBuildExtractValue(builder, oresult, 0, "");
  103. }
  104.  
  105. /**
  106.  * Performs unsigned addition of two integers and reports
  107.  * overflow if detected.
  108.  *
  109.  * The values @a and @b must be of the same integer type. If
  110.  * an overflow is detected the IN/OUT @ofbit parameter is used:
  111.  * - if it's pointing to a null value, the overflow bit is simply
  112.  *   stored inside the variable it's pointing to,
  113.  * - if it's pointing to a valid value, then that variable,
  114.  *   which must be of i1 type, is ORed with the newly detected
  115.  *   overflow bit. This is done to allow chaining of a number of
  116.  *   overflow functions together without having to test the
  117.  *   overflow bit after every single one.
  118.  */
  119. LLVMValueRef
  120. lp_build_uadd_overflow(struct gallivm_state *gallivm,
  121.                        LLVMValueRef a,
  122.                        LLVMValueRef b,
  123.                        LLVMValueRef *ofbit)
  124. {
  125.    return build_binary_int_overflow(gallivm, "llvm.uadd.with.overflow",
  126.                                     a, b, ofbit);
  127. }
  128.  
  129. /**
  130.  * Performs unsigned multiplication of  two integers and
  131.  * reports overflow if detected.
  132.  *
  133.  * The values @a and @b must be of the same integer type. If
  134.  * an overflow is detected the IN/OUT @ofbit parameter is used:
  135.  * - if it's pointing to a null value, the overflow bit is simply
  136.  *   stored inside the variable it's pointing to,
  137.  * - if it's pointing to a valid value, then that variable,
  138.  *   which must be of i1 type, is ORed with the newly detected
  139.  *   overflow bit. This is done to allow chaining of a number of
  140.  *   overflow functions together without having to test the
  141.  *   overflow bit after every single one.
  142.  */
  143. LLVMValueRef
  144. lp_build_umul_overflow(struct gallivm_state *gallivm,
  145.                        LLVMValueRef a,
  146.                        LLVMValueRef b,
  147.                        LLVMValueRef *ofbit)
  148. {
  149.    return build_binary_int_overflow(gallivm, "llvm.umul.with.overflow",
  150.                                     a, b, ofbit);
  151. }
  152.