Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 Serge 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 
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
}