Changeset View
Changeset View
Standalone View
Standalone View
include/llvm/Support/CheckedArithmetic.h
- This file was added.
1 | //==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ // | ||||
---|---|---|---|---|---|
2 | // | ||||
3 | // The LLVM Compiler Infrastructure | ||||
4 | // | ||||
5 | // This file is distributed under the University of Illinois Open Source | ||||
6 | // License. See LICENSE.TXT for details. | ||||
7 | // | ||||
8 | //===----------------------------------------------------------------------===// | ||||
9 | // | ||||
10 | // This file contains generic functions for operating on integers which | ||||
11 | // give the indication on whether the operation has overflown. | ||||
12 | // | ||||
13 | //===----------------------------------------------------------------------===// | ||||
14 | | ||||
15 | #ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H | ||||
16 | #define LLVM_SUPPORT_CHECKEDARITHMETIC_H | ||||
17 | | ||||
18 | #include "llvm/ADT/APInt.h" | ||||
19 | | ||||
20 | #include <functional> | ||||
vsk: This include can go away now. | |||||
21 | #include <type_traits> | ||||
22 | | ||||
23 | namespace { | ||||
24 | | ||||
25 | /// Utility function to apply a given method of \c APInt \p F to \p LHS and | ||||
26 | /// \p RHS, and write the output into \p Res. | ||||
27 | /// \return Whether the operation overflows. | ||||
28 | template <typename T, typename F> | ||||
29 | typename std::enable_if<std::is_integral<T>::value && sizeof(T) * 8 <= 64, | ||||
30 | bool>::type | ||||
31 | checkedOp(T LHS, T RHS, F Op, T *Res = nullptr, bool Signed = true) { | ||||
32 | llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed); | ||||
Done ReplyCan you move this out of the llvm namespace, into an anonymous namespace? vsk: Can you move this out of the llvm namespace, into an anonymous namespace? | |||||
33 | llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed); | ||||
34 | bool Overflow; | ||||
Not Done ReplyI'd rather just have the type of the function be some free template parameter, then, so it's clear the object isn't copied. vsk: I'd rather just have the type of the function be some free template parameter, then, so it's… | |||||
Done ReplyCould you elaborate? george.karpenkov: Could you elaborate? | |||||
Not Done ReplyI'm suggesting adding 'typename F' to the template parameter list and using F as the type of Op. It's shorter, and since there's no std::function, it signals to the reader that there are no unnecessary copies happening. Taken together this makes the code easier to read. vsk: I'm suggesting adding 'typename F' to the template parameter list and using F as the type of Op. | |||||
35 | llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow); | ||||
36 | if (!Overflow && Res) | ||||
37 | *Res = Out.getSExtValue(); | ||||
38 | return Overflow; | ||||
39 | } | ||||
40 | } | ||||
41 | | ||||
42 | namespace llvm { | ||||
43 | | ||||
44 | /// Add two signed integers \p LHS and \p RHS, write into \p Res if non-null | ||||
45 | /// and the operation does not oveflow. | ||||
46 | /// Does not guarantee saturating arithmetic. | ||||
47 | /// \return Whether the result overflows. | ||||
48 | template <typename T> | ||||
49 | typename std::enable_if<std::is_signed<T>::value, bool>::type | ||||
50 | checkedAdd(T LHS, T RHS, T *Res = nullptr) { | ||||
51 | return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov, Res); | ||||
52 | } | ||||
53 | | ||||
54 | /// Multiply two signed integers \p LHS and \p RHS, write into \p Res if | ||||
55 | /// non-null and the operation does not oveflow. | ||||
56 | /// Does not guarantee saturating arithmetic. | ||||
57 | /// \return Whether the result overflows. | ||||
58 | template <typename T> | ||||
59 | typename std::enable_if<std::is_signed<T>::value, bool>::type | ||||
60 | checkedMul(T LHS, T RHS, T *Res = nullptr) { | ||||
61 | return checkedOp(LHS, RHS, &llvm::APInt::smul_ov, Res); | ||||
62 | } | ||||
63 | | ||||
64 | /// Add two unsigned integers \p LHS and \p RHS, write into \p Res if non-null | ||||
65 | /// and the operation does not oveflow. | ||||
66 | /// Does not guarantee saturating arithmetic. | ||||
67 | /// \return Whether the result overflows. | ||||
68 | template <typename T> | ||||
69 | typename std::enable_if<std::is_unsigned<T>::value, bool>::type | ||||
70 | checkedAddUnsigned(T LHS, T RHS, T *Res = nullptr) { | ||||
71 | return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, Res, /*Signed=*/false); | ||||
72 | } | ||||
73 | | ||||
74 | /// Multiply two unsigned integers \p LHS and \p RHS, write into \p Res if | ||||
75 | /// non-null and the operation does not oveflow. | ||||
76 | /// Does not guarantee saturating arithmetic. | ||||
77 | /// \return Whether the result overflows. | ||||
78 | template <typename T> | ||||
79 | typename std::enable_if<std::is_unsigned<T>::value, bool>::type | ||||
80 | checkedMulUnsigned(T LHS, T RHS, T *Res = nullptr) { | ||||
81 | return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, Res, /*Signed=*/false); | ||||
82 | } | ||||
83 | | ||||
84 | } // End llvm namespace | ||||
85 | | ||||
86 | #endif |
This include can go away now.