Path: blob/21.2-virgl/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.c
4565 views
/**************************************************************************1*2* Copyright 20133* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/262728/**29* @file30* Helper31*32* The functions in this file implement arthmetic operations with support33* for overflow detection and reporting.34*35*/3637#include "lp_bld_arit_overflow.h"3839#include "lp_bld_type.h"40#include "lp_bld_const.h"41#include "lp_bld_init.h"42#include "lp_bld_intr.h"43#include "lp_bld_logic.h"44#include "lp_bld_pack.h"45#include "lp_bld_debug.h"46#include "lp_bld_bitarit.h"4748#include "util/u_memory.h"49#include "util/u_debug.h"50#include "util/u_math.h"51#include "util/u_string.h"52#include "util/u_cpu_detect.h"5354#include <float.h>555657static LLVMValueRef58build_binary_int_overflow(struct gallivm_state *gallivm,59const char *intr_prefix,60LLVMValueRef a,61LLVMValueRef b,62LLVMValueRef *ofbit)63{64LLVMBuilderRef builder = gallivm->builder;65char intr_str[256];66LLVMTypeRef type_ref;67LLVMTypeKind type_kind;68unsigned type_width;69LLVMTypeRef oelems[2];70LLVMValueRef oresult;71LLVMTypeRef otype;7273debug_assert(LLVMTypeOf(a) == LLVMTypeOf(b));74type_ref = LLVMTypeOf(a);75type_kind = LLVMGetTypeKind(type_ref);7677debug_assert(type_kind == LLVMIntegerTypeKind);78type_width = LLVMGetIntTypeWidth(type_ref);7980debug_assert(type_width == 16 || type_width == 32 || type_width == 64);8182snprintf(intr_str, sizeof intr_str, "%s.i%u",83intr_prefix, type_width);8485oelems[0] = type_ref;86oelems[1] = LLVMInt1TypeInContext(gallivm->context);8788otype = LLVMStructTypeInContext(gallivm->context, oelems, 2, FALSE);89oresult = lp_build_intrinsic_binary(builder, intr_str,90otype, a, b);91if (ofbit) {92if (*ofbit) {93*ofbit = LLVMBuildOr(94builder, *ofbit,95LLVMBuildExtractValue(builder, oresult, 1, ""), "");96} else {97*ofbit = LLVMBuildExtractValue(builder, oresult, 1, "");98}99}100101return LLVMBuildExtractValue(builder, oresult, 0, "");102}103104/**105* Performs unsigned addition of two integers and reports106* overflow if detected.107*108* The values @a and @b must be of the same integer type. If109* an overflow is detected the IN/OUT @ofbit parameter is used:110* - if it's pointing to a null value, the overflow bit is simply111* stored inside the variable it's pointing to,112* - if it's pointing to a valid value, then that variable,113* which must be of i1 type, is ORed with the newly detected114* overflow bit. This is done to allow chaining of a number of115* overflow functions together without having to test the116* overflow bit after every single one.117*/118LLVMValueRef119lp_build_uadd_overflow(struct gallivm_state *gallivm,120LLVMValueRef a,121LLVMValueRef b,122LLVMValueRef *ofbit)123{124return build_binary_int_overflow(gallivm, "llvm.uadd.with.overflow",125a, b, ofbit);126}127128/**129* Performs unsigned subtraction of two integers and reports130* overflow if detected.131*132* The values @a and @b must be of the same integer type. If133* an overflow is detected the IN/OUT @ofbit parameter is used:134* - if it's pointing to a null value, the overflow bit is simply135* stored inside the variable it's pointing to,136* - if it's pointing to a valid value, then that variable,137* which must be of i1 type, is ORed with the newly detected138* overflow bit. This is done to allow chaining of a number of139* overflow functions together without having to test the140* overflow bit after every single one.141*/142LLVMValueRef143lp_build_usub_overflow(struct gallivm_state *gallivm,144LLVMValueRef a,145LLVMValueRef b,146LLVMValueRef *ofbit)147{148return build_binary_int_overflow(gallivm, "llvm.usub.with.overflow",149a, b, ofbit);150}151152/**153* Performs unsigned multiplication of two integers and154* reports overflow if detected.155*156* The values @a and @b must be of the same integer type. If157* an overflow is detected the IN/OUT @ofbit parameter is used:158* - if it's pointing to a null value, the overflow bit is simply159* stored inside the variable it's pointing to,160* - if it's pointing to a valid value, then that variable,161* which must be of i1 type, is ORed with the newly detected162* overflow bit. This is done to allow chaining of a number of163* overflow functions together without having to test the164* overflow bit after every single one.165*/166LLVMValueRef167lp_build_umul_overflow(struct gallivm_state *gallivm,168LLVMValueRef a,169LLVMValueRef b,170LLVMValueRef *ofbit)171{172return build_binary_int_overflow(gallivm, "llvm.umul.with.overflow",173a, b, ofbit);174}175176177