1*700637cbSDimitry Andric //===--- Integral.h - Wrapper for numeric types for the VM ------*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // Defines the VM types and helpers operating on types.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric
13*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H
14*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H
15*700637cbSDimitry Andric
16*700637cbSDimitry Andric #include "clang/AST/APValue.h"
17*700637cbSDimitry Andric #include "clang/AST/ComparisonCategories.h"
18*700637cbSDimitry Andric #include "llvm/ADT/APSInt.h"
19*700637cbSDimitry Andric #include "llvm/Support/MathExtras.h"
20*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h"
21*700637cbSDimitry Andric #include <cstddef>
22*700637cbSDimitry Andric #include <cstdint>
23*700637cbSDimitry Andric
24*700637cbSDimitry Andric #include "Primitives.h"
25*700637cbSDimitry Andric
26*700637cbSDimitry Andric namespace clang {
27*700637cbSDimitry Andric namespace interp {
28*700637cbSDimitry Andric
29*700637cbSDimitry Andric using APInt = llvm::APInt;
30*700637cbSDimitry Andric using APSInt = llvm::APSInt;
31*700637cbSDimitry Andric
32*700637cbSDimitry Andric /// If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
33*700637cbSDimitry Andric /// It will NOT copy the memory (unless, of course, copy() is called) and it
34*700637cbSDimitry Andric /// won't alllocate anything. The allocation should happen via InterpState or
35*700637cbSDimitry Andric /// Program.
36*700637cbSDimitry Andric template <bool Signed> class IntegralAP final {
37*700637cbSDimitry Andric public:
38*700637cbSDimitry Andric union {
39*700637cbSDimitry Andric uint64_t *Memory = nullptr;
40*700637cbSDimitry Andric uint64_t Val;
41*700637cbSDimitry Andric };
42*700637cbSDimitry Andric uint32_t BitWidth = 0;
43*700637cbSDimitry Andric friend IntegralAP<!Signed>;
44*700637cbSDimitry Andric
45*700637cbSDimitry Andric template <typename T, bool InputSigned>
truncateCast(const APInt & V)46*700637cbSDimitry Andric static T truncateCast(const APInt &V) {
47*700637cbSDimitry Andric constexpr unsigned BitSize = sizeof(T) * 8;
48*700637cbSDimitry Andric if (BitSize >= V.getBitWidth()) {
49*700637cbSDimitry Andric APInt Extended;
50*700637cbSDimitry Andric if constexpr (InputSigned)
51*700637cbSDimitry Andric Extended = V.sext(BitSize);
52*700637cbSDimitry Andric else
53*700637cbSDimitry Andric Extended = V.zext(BitSize);
54*700637cbSDimitry Andric return std::is_signed_v<T> ? Extended.getSExtValue()
55*700637cbSDimitry Andric : Extended.getZExtValue();
56*700637cbSDimitry Andric }
57*700637cbSDimitry Andric
58*700637cbSDimitry Andric return std::is_signed_v<T> ? V.trunc(BitSize).getSExtValue()
59*700637cbSDimitry Andric : V.trunc(BitSize).getZExtValue();
60*700637cbSDimitry Andric }
61*700637cbSDimitry Andric
getValue()62*700637cbSDimitry Andric APInt getValue() const {
63*700637cbSDimitry Andric if (singleWord())
64*700637cbSDimitry Andric return APInt(BitWidth, Val, Signed);
65*700637cbSDimitry Andric unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
66*700637cbSDimitry Andric return llvm::APInt(BitWidth, NumWords, Memory);
67*700637cbSDimitry Andric }
68*700637cbSDimitry Andric
69*700637cbSDimitry Andric public:
70*700637cbSDimitry Andric using AsUnsigned = IntegralAP<false>;
71*700637cbSDimitry Andric
take(uint64_t * NewMemory)72*700637cbSDimitry Andric void take(uint64_t *NewMemory) {
73*700637cbSDimitry Andric assert(!singleWord());
74*700637cbSDimitry Andric std::memcpy(NewMemory, Memory, numWords() * sizeof(uint64_t));
75*700637cbSDimitry Andric Memory = NewMemory;
76*700637cbSDimitry Andric }
77*700637cbSDimitry Andric
copy(const APInt & V)78*700637cbSDimitry Andric void copy(const APInt &V) {
79*700637cbSDimitry Andric assert(BitWidth == V.getBitWidth());
80*700637cbSDimitry Andric assert(numWords() == V.getNumWords());
81*700637cbSDimitry Andric
82*700637cbSDimitry Andric if (V.isSingleWord()) {
83*700637cbSDimitry Andric if constexpr (Signed)
84*700637cbSDimitry Andric Val = V.getSExtValue();
85*700637cbSDimitry Andric else
86*700637cbSDimitry Andric Val = V.getZExtValue();
87*700637cbSDimitry Andric return;
88*700637cbSDimitry Andric }
89*700637cbSDimitry Andric assert(Memory);
90*700637cbSDimitry Andric std::memcpy(Memory, V.getRawData(), V.getNumWords() * sizeof(uint64_t));
91*700637cbSDimitry Andric }
92*700637cbSDimitry Andric
93*700637cbSDimitry Andric IntegralAP() = default;
94*700637cbSDimitry Andric /// Zeroed, single-word IntegralAP of the given bitwidth.
IntegralAP(unsigned BitWidth)95*700637cbSDimitry Andric IntegralAP(unsigned BitWidth) : Val(0), BitWidth(BitWidth) {
96*700637cbSDimitry Andric assert(singleWord());
97*700637cbSDimitry Andric }
IntegralAP(uint64_t * Memory,unsigned BitWidth)98*700637cbSDimitry Andric IntegralAP(uint64_t *Memory, unsigned BitWidth)
99*700637cbSDimitry Andric : Memory(Memory), BitWidth(BitWidth) {}
IntegralAP(const APInt & V)100*700637cbSDimitry Andric IntegralAP(const APInt &V) : BitWidth(V.getBitWidth()) {
101*700637cbSDimitry Andric if (V.isSingleWord()) {
102*700637cbSDimitry Andric Val = Signed ? V.getSExtValue() : V.getZExtValue();
103*700637cbSDimitry Andric } else {
104*700637cbSDimitry Andric Memory = const_cast<uint64_t *>(V.getRawData());
105*700637cbSDimitry Andric }
106*700637cbSDimitry Andric }
107*700637cbSDimitry Andric
108*700637cbSDimitry Andric IntegralAP operator-() const { return IntegralAP(-getValue()); }
109*700637cbSDimitry Andric bool operator>(const IntegralAP &RHS) const {
110*700637cbSDimitry Andric if constexpr (Signed)
111*700637cbSDimitry Andric return getValue().sgt(RHS.getValue());
112*700637cbSDimitry Andric return getValue().ugt(RHS.getValue());
113*700637cbSDimitry Andric }
114*700637cbSDimitry Andric bool operator>=(unsigned RHS) const {
115*700637cbSDimitry Andric if constexpr (Signed)
116*700637cbSDimitry Andric return getValue().sge(RHS);
117*700637cbSDimitry Andric return getValue().uge(RHS);
118*700637cbSDimitry Andric }
119*700637cbSDimitry Andric bool operator<(IntegralAP RHS) const {
120*700637cbSDimitry Andric if constexpr (Signed)
121*700637cbSDimitry Andric return getValue().slt(RHS.getValue());
122*700637cbSDimitry Andric return getValue().ult(RHS.getValue());
123*700637cbSDimitry Andric }
124*700637cbSDimitry Andric
125*700637cbSDimitry Andric template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
Ty()126*700637cbSDimitry Andric explicit operator Ty() const {
127*700637cbSDimitry Andric return truncateCast<Ty, Signed>(getValue());
128*700637cbSDimitry Andric }
129*700637cbSDimitry Andric
130*700637cbSDimitry Andric template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
131*700637cbSDimitry Andric if (NumBits == 0)
132*700637cbSDimitry Andric NumBits = sizeof(T) * 8;
133*700637cbSDimitry Andric assert(NumBits > 0);
134*700637cbSDimitry Andric assert(APInt::getNumWords(NumBits) == 1);
135*700637cbSDimitry Andric APInt Copy = APInt(NumBits, static_cast<uint64_t>(Value), Signed);
136*700637cbSDimitry Andric return IntegralAP<Signed>(Copy);
137*700637cbSDimitry Andric }
138*700637cbSDimitry Andric
bitWidth()139*700637cbSDimitry Andric constexpr uint32_t bitWidth() const { return BitWidth; }
numWords()140*700637cbSDimitry Andric constexpr unsigned numWords() const { return APInt::getNumWords(BitWidth); }
singleWord()141*700637cbSDimitry Andric constexpr bool singleWord() const { return numWords() == 1; }
142*700637cbSDimitry Andric
143*700637cbSDimitry Andric APSInt toAPSInt(unsigned Bits = 0) const {
144*700637cbSDimitry Andric if (Bits == 0)
145*700637cbSDimitry Andric Bits = bitWidth();
146*700637cbSDimitry Andric
147*700637cbSDimitry Andric APInt V = getValue();
148*700637cbSDimitry Andric if constexpr (Signed)
149*700637cbSDimitry Andric return APSInt(getValue().sext(Bits), !Signed);
150*700637cbSDimitry Andric else
151*700637cbSDimitry Andric return APSInt(getValue().zext(Bits), !Signed);
152*700637cbSDimitry Andric }
toAPValue(const ASTContext &)153*700637cbSDimitry Andric APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); }
154*700637cbSDimitry Andric
isZero()155*700637cbSDimitry Andric bool isZero() const { return getValue().isZero(); }
isPositive()156*700637cbSDimitry Andric bool isPositive() const {
157*700637cbSDimitry Andric if constexpr (Signed)
158*700637cbSDimitry Andric return getValue().isNonNegative();
159*700637cbSDimitry Andric return true;
160*700637cbSDimitry Andric }
isNegative()161*700637cbSDimitry Andric bool isNegative() const {
162*700637cbSDimitry Andric if constexpr (Signed)
163*700637cbSDimitry Andric return !getValue().isNonNegative();
164*700637cbSDimitry Andric return false;
165*700637cbSDimitry Andric }
isMin()166*700637cbSDimitry Andric bool isMin() const {
167*700637cbSDimitry Andric if constexpr (Signed)
168*700637cbSDimitry Andric return getValue().isMinSignedValue();
169*700637cbSDimitry Andric return getValue().isMinValue();
170*700637cbSDimitry Andric }
isMax()171*700637cbSDimitry Andric bool isMax() const {
172*700637cbSDimitry Andric if constexpr (Signed)
173*700637cbSDimitry Andric return getValue().isMaxSignedValue();
174*700637cbSDimitry Andric return getValue().isMaxValue();
175*700637cbSDimitry Andric }
isSigned()176*700637cbSDimitry Andric static constexpr bool isSigned() { return Signed; }
isMinusOne()177*700637cbSDimitry Andric bool isMinusOne() const { return Signed && getValue().isAllOnes(); }
178*700637cbSDimitry Andric
countLeadingZeros()179*700637cbSDimitry Andric unsigned countLeadingZeros() const { return getValue().countl_zero(); }
180*700637cbSDimitry Andric
print(llvm::raw_ostream & OS)181*700637cbSDimitry Andric void print(llvm::raw_ostream &OS) const { getValue().print(OS, Signed); }
toDiagnosticString(const ASTContext & Ctx)182*700637cbSDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const {
183*700637cbSDimitry Andric std::string NameStr;
184*700637cbSDimitry Andric llvm::raw_string_ostream OS(NameStr);
185*700637cbSDimitry Andric print(OS);
186*700637cbSDimitry Andric return NameStr;
187*700637cbSDimitry Andric }
188*700637cbSDimitry Andric
truncate(unsigned BitWidth)189*700637cbSDimitry Andric IntegralAP truncate(unsigned BitWidth) const {
190*700637cbSDimitry Andric if constexpr (Signed)
191*700637cbSDimitry Andric return IntegralAP(
192*700637cbSDimitry Andric getValue().trunc(BitWidth).sextOrTrunc(this->bitWidth()));
193*700637cbSDimitry Andric else
194*700637cbSDimitry Andric return IntegralAP(
195*700637cbSDimitry Andric getValue().trunc(BitWidth).zextOrTrunc(this->bitWidth()));
196*700637cbSDimitry Andric }
197*700637cbSDimitry Andric
toUnsigned()198*700637cbSDimitry Andric IntegralAP<false> toUnsigned() const {
199*700637cbSDimitry Andric return IntegralAP<false>(Memory, BitWidth);
200*700637cbSDimitry Andric }
201*700637cbSDimitry Andric
bitcastToMemory(std::byte * Dest)202*700637cbSDimitry Andric void bitcastToMemory(std::byte *Dest) const {
203*700637cbSDimitry Andric llvm::StoreIntToMemory(getValue(), (uint8_t *)Dest, bitWidth() / 8);
204*700637cbSDimitry Andric }
205*700637cbSDimitry Andric
bitcastFromMemory(const std::byte * Src,unsigned BitWidth,IntegralAP * Result)206*700637cbSDimitry Andric static void bitcastFromMemory(const std::byte *Src, unsigned BitWidth,
207*700637cbSDimitry Andric IntegralAP *Result) {
208*700637cbSDimitry Andric APInt V(BitWidth, static_cast<uint64_t>(0), Signed);
209*700637cbSDimitry Andric llvm::LoadIntFromMemory(V, (const uint8_t *)Src, BitWidth / 8);
210*700637cbSDimitry Andric Result->copy(V);
211*700637cbSDimitry Andric }
212*700637cbSDimitry Andric
compare(const IntegralAP & RHS)213*700637cbSDimitry Andric ComparisonCategoryResult compare(const IntegralAP &RHS) const {
214*700637cbSDimitry Andric assert(Signed == RHS.isSigned());
215*700637cbSDimitry Andric assert(bitWidth() == RHS.bitWidth());
216*700637cbSDimitry Andric APInt V1 = getValue();
217*700637cbSDimitry Andric APInt V2 = RHS.getValue();
218*700637cbSDimitry Andric if constexpr (Signed) {
219*700637cbSDimitry Andric if (V1.slt(V2))
220*700637cbSDimitry Andric return ComparisonCategoryResult::Less;
221*700637cbSDimitry Andric if (V1.sgt(V2))
222*700637cbSDimitry Andric return ComparisonCategoryResult::Greater;
223*700637cbSDimitry Andric return ComparisonCategoryResult::Equal;
224*700637cbSDimitry Andric }
225*700637cbSDimitry Andric
226*700637cbSDimitry Andric assert(!Signed);
227*700637cbSDimitry Andric if (V1.ult(V2))
228*700637cbSDimitry Andric return ComparisonCategoryResult::Less;
229*700637cbSDimitry Andric if (V1.ugt(V2))
230*700637cbSDimitry Andric return ComparisonCategoryResult::Greater;
231*700637cbSDimitry Andric return ComparisonCategoryResult::Equal;
232*700637cbSDimitry Andric }
233*700637cbSDimitry Andric
increment(IntegralAP A,IntegralAP * R)234*700637cbSDimitry Andric static bool increment(IntegralAP A, IntegralAP *R) {
235*700637cbSDimitry Andric APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
236*700637cbSDimitry Andric return add(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
237*700637cbSDimitry Andric }
238*700637cbSDimitry Andric
decrement(IntegralAP A,IntegralAP * R)239*700637cbSDimitry Andric static bool decrement(IntegralAP A, IntegralAP *R) {
240*700637cbSDimitry Andric APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
241*700637cbSDimitry Andric return sub(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
242*700637cbSDimitry Andric }
243*700637cbSDimitry Andric
add(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)244*700637cbSDimitry Andric static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
245*700637cbSDimitry Andric return CheckAddSubMulUB<std::plus>(A, B, OpBits, R);
246*700637cbSDimitry Andric }
247*700637cbSDimitry Andric
sub(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)248*700637cbSDimitry Andric static bool sub(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
249*700637cbSDimitry Andric return CheckAddSubMulUB<std::minus>(A, B, OpBits, R);
250*700637cbSDimitry Andric }
251*700637cbSDimitry Andric
mul(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)252*700637cbSDimitry Andric static bool mul(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
253*700637cbSDimitry Andric return CheckAddSubMulUB<std::multiplies>(A, B, OpBits, R);
254*700637cbSDimitry Andric }
255*700637cbSDimitry Andric
rem(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)256*700637cbSDimitry Andric static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
257*700637cbSDimitry Andric if constexpr (Signed)
258*700637cbSDimitry Andric R->copy(A.getValue().srem(B.getValue()));
259*700637cbSDimitry Andric else
260*700637cbSDimitry Andric R->copy(A.getValue().urem(B.getValue()));
261*700637cbSDimitry Andric return false;
262*700637cbSDimitry Andric }
263*700637cbSDimitry Andric
div(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)264*700637cbSDimitry Andric static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
265*700637cbSDimitry Andric if constexpr (Signed)
266*700637cbSDimitry Andric R->copy(A.getValue().sdiv(B.getValue()));
267*700637cbSDimitry Andric else
268*700637cbSDimitry Andric R->copy(A.getValue().udiv(B.getValue()));
269*700637cbSDimitry Andric return false;
270*700637cbSDimitry Andric }
271*700637cbSDimitry Andric
bitAnd(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)272*700637cbSDimitry Andric static bool bitAnd(IntegralAP A, IntegralAP B, unsigned OpBits,
273*700637cbSDimitry Andric IntegralAP *R) {
274*700637cbSDimitry Andric R->copy(A.getValue() & B.getValue());
275*700637cbSDimitry Andric return false;
276*700637cbSDimitry Andric }
277*700637cbSDimitry Andric
bitOr(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)278*700637cbSDimitry Andric static bool bitOr(IntegralAP A, IntegralAP B, unsigned OpBits,
279*700637cbSDimitry Andric IntegralAP *R) {
280*700637cbSDimitry Andric R->copy(A.getValue() | B.getValue());
281*700637cbSDimitry Andric return false;
282*700637cbSDimitry Andric }
283*700637cbSDimitry Andric
bitXor(IntegralAP A,IntegralAP B,unsigned OpBits,IntegralAP * R)284*700637cbSDimitry Andric static bool bitXor(IntegralAP A, IntegralAP B, unsigned OpBits,
285*700637cbSDimitry Andric IntegralAP *R) {
286*700637cbSDimitry Andric R->copy(A.getValue() ^ B.getValue());
287*700637cbSDimitry Andric return false;
288*700637cbSDimitry Andric }
289*700637cbSDimitry Andric
neg(const IntegralAP & A,IntegralAP * R)290*700637cbSDimitry Andric static bool neg(const IntegralAP &A, IntegralAP *R) {
291*700637cbSDimitry Andric APInt AI = A.getValue();
292*700637cbSDimitry Andric AI.negate();
293*700637cbSDimitry Andric R->copy(AI);
294*700637cbSDimitry Andric return false;
295*700637cbSDimitry Andric }
296*700637cbSDimitry Andric
comp(IntegralAP A,IntegralAP * R)297*700637cbSDimitry Andric static bool comp(IntegralAP A, IntegralAP *R) {
298*700637cbSDimitry Andric R->copy(~A.getValue());
299*700637cbSDimitry Andric return false;
300*700637cbSDimitry Andric }
301*700637cbSDimitry Andric
shiftLeft(const IntegralAP A,const IntegralAP B,unsigned OpBits,IntegralAP * R)302*700637cbSDimitry Andric static void shiftLeft(const IntegralAP A, const IntegralAP B, unsigned OpBits,
303*700637cbSDimitry Andric IntegralAP *R) {
304*700637cbSDimitry Andric *R = IntegralAP(A.getValue().shl(B.getValue().getZExtValue()));
305*700637cbSDimitry Andric }
306*700637cbSDimitry Andric
shiftRight(const IntegralAP A,const IntegralAP B,unsigned OpBits,IntegralAP * R)307*700637cbSDimitry Andric static void shiftRight(const IntegralAP A, const IntegralAP B,
308*700637cbSDimitry Andric unsigned OpBits, IntegralAP *R) {
309*700637cbSDimitry Andric unsigned ShiftAmount = B.getValue().getZExtValue();
310*700637cbSDimitry Andric if constexpr (Signed)
311*700637cbSDimitry Andric R->copy(A.getValue().ashr(ShiftAmount));
312*700637cbSDimitry Andric else
313*700637cbSDimitry Andric R->copy(A.getValue().lshr(ShiftAmount));
314*700637cbSDimitry Andric }
315*700637cbSDimitry Andric
316*700637cbSDimitry Andric // === Serialization support ===
bytesToSerialize()317*700637cbSDimitry Andric size_t bytesToSerialize() const {
318*700637cbSDimitry Andric assert(BitWidth != 0);
319*700637cbSDimitry Andric return sizeof(uint32_t) + (numWords() * sizeof(uint64_t));
320*700637cbSDimitry Andric }
321*700637cbSDimitry Andric
serialize(std::byte * Buff)322*700637cbSDimitry Andric void serialize(std::byte *Buff) const {
323*700637cbSDimitry Andric std::memcpy(Buff, &BitWidth, sizeof(uint32_t));
324*700637cbSDimitry Andric if (singleWord())
325*700637cbSDimitry Andric std::memcpy(Buff + sizeof(uint32_t), &Val, sizeof(uint64_t));
326*700637cbSDimitry Andric else {
327*700637cbSDimitry Andric std::memcpy(Buff + sizeof(uint32_t), Memory,
328*700637cbSDimitry Andric numWords() * sizeof(uint64_t));
329*700637cbSDimitry Andric }
330*700637cbSDimitry Andric }
331*700637cbSDimitry Andric
deserializeSize(const std::byte * Buff)332*700637cbSDimitry Andric static uint32_t deserializeSize(const std::byte *Buff) {
333*700637cbSDimitry Andric return *reinterpret_cast<const uint32_t *>(Buff);
334*700637cbSDimitry Andric }
335*700637cbSDimitry Andric
deserialize(const std::byte * Buff,IntegralAP<Signed> * Result)336*700637cbSDimitry Andric static void deserialize(const std::byte *Buff, IntegralAP<Signed> *Result) {
337*700637cbSDimitry Andric uint32_t BitWidth = Result->BitWidth;
338*700637cbSDimitry Andric assert(BitWidth != 0);
339*700637cbSDimitry Andric unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
340*700637cbSDimitry Andric
341*700637cbSDimitry Andric if (NumWords == 1)
342*700637cbSDimitry Andric std::memcpy(&Result->Val, Buff + sizeof(uint32_t), sizeof(uint64_t));
343*700637cbSDimitry Andric else {
344*700637cbSDimitry Andric assert(Result->Memory);
345*700637cbSDimitry Andric std::memcpy(Result->Memory, Buff + sizeof(uint32_t),
346*700637cbSDimitry Andric NumWords * sizeof(uint64_t));
347*700637cbSDimitry Andric }
348*700637cbSDimitry Andric }
349*700637cbSDimitry Andric
350*700637cbSDimitry Andric private:
351*700637cbSDimitry Andric template <template <typename T> class Op>
CheckAddSubMulUB(const IntegralAP & A,const IntegralAP & B,unsigned BitWidth,IntegralAP * R)352*700637cbSDimitry Andric static bool CheckAddSubMulUB(const IntegralAP &A, const IntegralAP &B,
353*700637cbSDimitry Andric unsigned BitWidth, IntegralAP *R) {
354*700637cbSDimitry Andric if constexpr (!Signed) {
355*700637cbSDimitry Andric R->copy(Op<APInt>{}(A.getValue(), B.getValue()));
356*700637cbSDimitry Andric return false;
357*700637cbSDimitry Andric }
358*700637cbSDimitry Andric
359*700637cbSDimitry Andric const APSInt &LHS = A.toAPSInt();
360*700637cbSDimitry Andric const APSInt &RHS = B.toAPSInt();
361*700637cbSDimitry Andric APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth));
362*700637cbSDimitry Andric APSInt Result = Value.trunc(LHS.getBitWidth());
363*700637cbSDimitry Andric R->copy(Result);
364*700637cbSDimitry Andric
365*700637cbSDimitry Andric return Result.extend(BitWidth) != Value;
366*700637cbSDimitry Andric }
367*700637cbSDimitry Andric };
368*700637cbSDimitry Andric
369*700637cbSDimitry Andric template <bool Signed>
370*700637cbSDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
371*700637cbSDimitry Andric IntegralAP<Signed> I) {
372*700637cbSDimitry Andric I.print(OS);
373*700637cbSDimitry Andric return OS;
374*700637cbSDimitry Andric }
375*700637cbSDimitry Andric
376*700637cbSDimitry Andric template <bool Signed>
getSwappedBytes(IntegralAP<Signed> F)377*700637cbSDimitry Andric IntegralAP<Signed> getSwappedBytes(IntegralAP<Signed> F) {
378*700637cbSDimitry Andric return F;
379*700637cbSDimitry Andric }
380*700637cbSDimitry Andric
381*700637cbSDimitry Andric } // namespace interp
382*700637cbSDimitry Andric } // namespace clang
383*700637cbSDimitry Andric
384*700637cbSDimitry Andric #endif
385