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 "ByteCode/State.h"
18#include "clang/Basic/BuiltinTraits.h"
19#include <cstdint>
20#include <optional>
21
22namespace llvm {
23class APFloat;
24class APSInt;
25class APInt;
26}
27namespace clang {
28class QualType;
29class LangOptions;
30class ASTContext;
31class CharUnits;
32class Expr;
33class CallExpr;
34class CXXRecordDecl;
35
36CharUnits GetAlignOfDynamicAlloc(const ASTContext &Ctx, QualType AllocType,
37 DynAllocKind AllocKind);
38} // namespace clang
39using namespace clang;
40/// Values returned by __builtin_classify_type, chosen to match the values
41/// produced by GCC's builtin.
42enum class GCCTypeClass {
43 None = -1,
44 Void = 0,
45 Integer = 1,
46 // GCC reserves 2 for character types, but instead classifies them as
47 // integers.
48 Enum = 3,
49 Bool = 4,
50 Pointer = 5,
51 // GCC reserves 6 for references, but appears to never use it (because
52 // expressions never have reference type, presumably).
53 PointerToDataMember = 7,
54 RealFloat = 8,
55 Complex = 9,
56 // GCC reserves 10 for functions, but does not use it since GCC version 6 due
57 // to decay to pointer. (Prior to version 6 it was only used in C++ mode).
58 // GCC claims to reserve 11 for pointers to member functions, but *actually*
59 // uses 12 for that purpose, same as for a class or struct. Maybe it
60 // internally implements a pointer to member as a struct? Who knows.
61 PointerToMemberFunction = 12, // Not a bug, see above.
62 ClassOrStruct = 12,
63 Union = 13,
64 // GCC reserves 14 for arrays, but does not use it since GCC version 6 due to
65 // decay to pointer. (Prior to version 6 it was only used in C++ mode).
66 // GCC reserves 15 for strings, but actually uses 5 (pointer) for string
67 // literals.
68 // Lang = 16,
69 // OpaqueType = 17,
70 BitInt = 18,
71 Vector = 19
72};
73
74GCCTypeClass EvaluateBuiltinClassifyType(QualType T,
75 const LangOptions &LangOpts);
76
77void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
78 llvm::APFloat D, llvm::APFloat &ResR,
79 llvm::APFloat &ResI);
80void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
81 llvm::APFloat D, llvm::APFloat &ResR,
82 llvm::APFloat &ResI);
83
84CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
85 UnaryExprOrTypeTrait ExprKind);
86
87/// Convert a builtin ID to the canonical x86 builtin ID the constant evaluators
88/// dispatch on in their x86 target-specific cases.
89///
90/// Target-independent builtins are returned unchanged. An x86 target builtin
91/// (including an auxiliary-target x86 builtin, whose ID is shifted past the
92/// primary target's builtins) is translated to its canonical X86::BI* value.
93/// Any other target's builtin returns 0: the constant evaluators only fold x86
94/// target builtins, and target builtin IDs of different targets overlap (each
95/// numbers from Builtin::FirstTSBuiltin), so an unrelated target's ID must not
96/// be mistaken for an x86 one.
97///
98/// The ID-based overload performs no work beyond a single comparison for
99/// target-independent builtins, so it is suitable for hot paths (e.g. the
100/// bytecode interpreter's builtin dispatch) where re-deriving the ID from the
101/// call expression would be wasteful.
102unsigned ConvertBuiltinIDToX86BuiltinID(const ASTContext &Ctx,
103 unsigned BuiltinID);
104unsigned ConvertBuiltinIDToX86BuiltinID(const ASTContext &Ctx,
105 const CallExpr *E);
106
107uint8_t GFNIMultiplicativeInverse(uint8_t Byte);
108uint8_t GFNIMul(uint8_t AByte, uint8_t BByte);
109uint8_t GFNIAffine(uint8_t XByte, const llvm::APInt &AQword,
110 const llvm::APSInt &Imm, bool Inverse = false);
111llvm::APSInt NormalizeRotateAmount(const llvm::APSInt &Value,
112 const llvm::APSInt &Amount);
113
114std::optional<llvm::APFloat>
115EvalScalarMinMaxFp(const llvm::APFloat &A, const llvm::APFloat &B,
116 std::optional<llvm::APSInt> RoundingMode, bool IsMin);
117
118const Expr *ignorePointerCastsAndParens(const Expr *E);
119
120bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD);
121bool isReadByLvalueToRvalueConversion(QualType T);
122/// Determines whether the given kind of constant expression is only ever
123/// used for name mangling. If so, it's permitted to reference things that we
124/// can't generate code for (in particular, dllimported functions).
125inline bool isForManglingOnly(ConstantExprKind Kind) {
126 switch (Kind) {
127 case ConstantExprKind::Normal:
128 case ConstantExprKind::ClassTemplateArgument:
129 case ConstantExprKind::ImmediateInvocation:
130 case ConstantExprKind::Initializer:
131 // Note that non-type template arguments of class type are emitted as
132 // template parameter objects.
133 return false;
134
135 case ConstantExprKind::NonClassTemplateArgument:
136 return true;
137 }
138 llvm_unreachable("unknown ConstantExprKind");
139}
140
141inline bool isTemplateArgument(ConstantExprKind Kind) {
142 switch (Kind) {
143 case ConstantExprKind::Normal:
144 case ConstantExprKind::ImmediateInvocation:
145 case ConstantExprKind::Initializer:
146 return false;
147
148 case ConstantExprKind::ClassTemplateArgument:
149 case ConstantExprKind::NonClassTemplateArgument:
150 return true;
151 }
152 llvm_unreachable("unknown ConstantExprKind");
153}
154
155/// Should this call expression be treated as forming an opaque constant?
156inline bool isOpaqueConstantCall(const CallExpr *E) {
157 unsigned Builtin = E->getBuiltinCallee();
158 return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
159 Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
160 Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
161 Builtin == Builtin::BI__builtin_function_start);
162}
163
164bool isGlobalLValue(const ValueDecl *D, const Expr *E);
165
166#endif
167