LLVM 23.0.0git
CheckedArithmetic.h
Go to the documentation of this file.
1//==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ //
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains generic functions for operating on integers which
10// give the indication on whether the operation has overflown.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H
15#define LLVM_SUPPORT_CHECKEDARITHMETIC_H
16
17#include "llvm/ADT/APInt.h"
18
19#include <optional>
20#include <type_traits>
21
22namespace llvm {
23namespace detail {
24
25/// Utility function to apply a given method of \c APInt \p F to \p LHS and
26/// \p RHS.
27/// \return Empty optional if the operation overflows, or result otherwise.
28template <typename T, typename F>
29std::enable_if_t<std::is_integral_v<T> && sizeof(T) * 8 <= 64, std::optional<T>>
30checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
31 llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
32 llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
33 bool Overflow;
34 llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow);
35 if (Overflow)
36 return std::nullopt;
37 return Signed ? Out.getSExtValue() : Out.getZExtValue();
38}
39} // namespace detail
40} // namespace llvm
41
42namespace llvm {
43
44/// Add two signed integers \p LHS and \p RHS.
45/// \return Optional of sum if no signed overflow occurred,
46/// \c std::nullopt otherwise.
47template <typename T>
48std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedAdd(T LHS,
49 T RHS) {
51}
52
53/// Subtract two signed integers \p LHS and \p RHS.
54/// \return Optional of sum if no signed overflow occurred,
55/// \c std::nullopt otherwise.
56template <typename T>
57std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedSub(T LHS,
58 T RHS) {
60}
61
62/// Multiply two signed integers \p LHS and \p RHS.
63/// \return Optional of product if no signed overflow occurred,
64/// \c std::nullopt otherwise.
65template <typename T>
66std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedMul(T LHS,
67 T RHS) {
69}
70
71/// Multiply A and B, and add C to the resulting product.
72/// \return Optional of result if no signed overflow occurred,
73/// \c std::nullopt otherwise.
74template <typename T>
75std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedMulAdd(T A, T B,
76 T C) {
77 if (auto Product = checkedMul(A, B))
78 return checkedAdd(*Product, C);
79 return std::nullopt;
80}
81
82/// Add two unsigned integers \p LHS and \p RHS.
83/// \return Optional of sum if no unsigned overflow occurred,
84/// \c std::nullopt otherwise.
85template <typename T>
86std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
88 return detail::checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
89}
90
91/// Multiply two unsigned integers \p LHS and \p RHS.
92/// \return Optional of product if no unsigned overflow occurred,
93/// \c std::nullopt otherwise.
94template <typename T>
95std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
97 return detail::checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
98}
99
100/// Multiply unsigned integers A and B, and add C to the resulting product.
101/// \return Optional of result if no unsigned overflow occurred,
102/// \c std::nullopt otherwise.
103template <typename T>
104std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
106 if (auto Product = checkedMulUnsigned(A, B))
107 return checkedAddUnsigned(*Product, C);
108 return std::nullopt;
109}
110
111} // End llvm namespace
112
113#endif
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define F(x, y, z)
Definition MD5.cpp:54
#define T
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt umul_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:2006
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1563
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1963
LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1970
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1995
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1976
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1585
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
std::enable_if_t< std::is_integral_v< T > &&sizeof(T) *8<=64, std::optional< T > > checkedOp(T LHS, T RHS, F Op, bool Signed=true)
Utility function to apply a given method of APInt F to LHS and RHS.
This is an optimization pass for GlobalISel generic memory operations.
std::enable_if_t< std::is_unsigned_v< T >, std::optional< T > > checkedMulUnsigned(T LHS, T RHS)
Multiply two unsigned integers LHS and RHS.
DWARFExpression::Operation Op
std::enable_if_t< std::is_unsigned_v< T >, std::optional< T > > checkedAddUnsigned(T LHS, T RHS)
Add two unsigned integers LHS and RHS.
std::enable_if_t< std::is_unsigned_v< T >, std::optional< T > > checkedMulAddUnsigned(T A, T B, T C)
Multiply unsigned integers A and B, and add C to the resulting product.
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedSub(T LHS, T RHS)
Subtract two signed integers LHS and RHS.
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedAdd(T LHS, T RHS)
Add two signed integers LHS and RHS.
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedMulAdd(T A, T B, T C)
Multiply A and B, and add C to the resulting product.
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedMul(T LHS, T RHS)
Multiply two signed integers LHS and RHS.