1//===--- ExprConstShared.h - Shared consetxpr functionality ----*- 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// Shared functionality between the new constant expression
10// interpreter (AST/ByteCode/) and the current one (ExprConstant.cpp).
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H
15#define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H
16
17#include "clang/Basic/BuiltinTraits.h"
18#include <cstdint>
19#include <optional>
20
21namespace llvm {
22class APFloat;
23class APSInt;
24class APInt;
25}
26namespace clang {
27class QualType;
28class LangOptions;
29class ASTContext;
30class CharUnits;
31class Expr;
32class CallExpr;
33class CXXRecordDecl;
34} // namespace clang
35using namespace clang;
36/// Values returned by __builtin_classify_type, chosen to match the values
37/// produced by GCC's builtin.
38enum class GCCTypeClass {
39 None = -1,
40 Void = 0,
41 Integer = 1,
42 // GCC reserves 2 for character types, but instead classifies them as
43 // integers.
44 Enum = 3,
45 Bool = 4,
46 Pointer = 5,
47 // GCC reserves 6 for references, but appears to never use it (because
48 // expressions never have reference type, presumably).
49 PointerToDataMember = 7,
50 RealFloat = 8,
51 Complex = 9,
52 // GCC reserves 10 for functions, but does not use it since GCC version 6 due
53 // to decay to pointer. (Prior to version 6 it was only used in C++ mode).
54 // GCC claims to reserve 11 for pointers to member functions, but *actually*
55 // uses 12 for that purpose, same as for a class or struct. Maybe it
56 // internally implements a pointer to member as a struct? Who knows.
57 PointerToMemberFunction = 12, // Not a bug, see above.
58 ClassOrStruct = 12,
59 Union = 13,
60 // GCC reserves 14 for arrays, but does not use it since GCC version 6 due to
61 // decay to pointer. (Prior to version 6 it was only used in C++ mode).
62 // GCC reserves 15 for strings, but actually uses 5 (pointer) for string
63 // literals.
64 // Lang = 16,
65 // OpaqueType = 17,
66 BitInt = 18,
67 Vector = 19
68};
69
70GCCTypeClass EvaluateBuiltinClassifyType(QualType T,
71 const LangOptions &LangOpts);
72
73void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
74 llvm::APFloat D, llvm::APFloat &ResR,
75 llvm::APFloat &ResI);
76void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
77 llvm::APFloat D, llvm::APFloat &ResR,
78 llvm::APFloat &ResI);
79
80CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
81 UnaryExprOrTypeTrait ExprKind);
82
83/// Convert a builtin ID to the canonical x86 builtin ID the constant evaluators
84/// dispatch on in their x86 target-specific cases.
85///
86/// Target-independent builtins are returned unchanged. An x86 target builtin
87/// (including an auxiliary-target x86 builtin, whose ID is shifted past the
88/// primary target's builtins) is translated to its canonical X86::BI* value.
89/// Any other target's builtin returns 0: the constant evaluators only fold x86
90/// target builtins, and target builtin IDs of different targets overlap (each
91/// numbers from Builtin::FirstTSBuiltin), so an unrelated target's ID must not
92/// be mistaken for an x86 one.
93///
94/// The ID-based overload performs no work beyond a single comparison for
95/// target-independent builtins, so it is suitable for hot paths (e.g. the
96/// bytecode interpreter's builtin dispatch) where re-deriving the ID from the
97/// call expression would be wasteful.
98unsigned ConvertBuiltinIDToX86BuiltinID(const ASTContext &Ctx,
99 unsigned BuiltinID);
100unsigned ConvertBuiltinIDToX86BuiltinID(const ASTContext &Ctx,
101 const CallExpr *E);
102
103uint8_t GFNIMultiplicativeInverse(uint8_t Byte);
104uint8_t GFNIMul(uint8_t AByte, uint8_t BByte);
105uint8_t GFNIAffine(uint8_t XByte, const llvm::APInt &AQword,
106 const llvm::APSInt &Imm, bool Inverse = false);
107llvm::APSInt NormalizeRotateAmount(const llvm::APSInt &Value,
108 const llvm::APSInt &Amount);
109
110std::optional<llvm::APFloat>
111EvalScalarMinMaxFp(const llvm::APFloat &A, const llvm::APFloat &B,
112 std::optional<llvm::APSInt> RoundingMode, bool IsMin);
113
114const Expr *ignorePointerCastsAndParens(const Expr *E);
115
116bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD);
117bool isReadByLvalueToRvalueConversion(QualType T);
118
119#endif
120