21#include "llvm/Support/SystemZ/zOSSupport.h"
27 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
28 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
29 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
30 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
31 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
32 "We're assuming 8 bit chars");
54 return Run(Parent,
Func);
61 size_t StackSizeBefore = Stk.size();
64 if (!
C.interpretCall(FD, E)) {
66 Stk.clearTo(StackSizeBefore);
72 bool Recursing = !Stk.empty();
73 size_t StackSizeBefore = Stk.size();
78 if (Res.isInvalid()) {
80 Stk.clearTo(StackSizeBefore);
91 Stk.clearTo(StackSizeBefore);
95 Result = Res.stealAPValue();
103 bool Recursing = !Stk.empty();
104 size_t StackSizeBefore = Stk.size();
107 auto Res =
C.interpretExpr(E,
false,
109 if (Res.isInvalid()) {
111 Stk.clearTo(StackSizeBefore);
121 Stk.clearTo(StackSizeBefore);
125 Result = Res.stealAPValue();
132 bool Recursing = !Stk.empty();
133 size_t StackSizeBefore = Stk.size();
136 bool CheckGlobalInitialized =
139 auto Res =
C.interpretDecl(VD,
Init, CheckGlobalInitialized);
140 if (Res.isInvalid()) {
142 Stk.clearTo(StackSizeBefore);
153 Stk.clearTo(StackSizeBefore);
157 Result = Res.stealAPValue();
161template <
typename ResultT>
162bool Context::evaluateStringRepr(
State &Parent,
const Expr *SizeExpr,
172 if (!SizeValue.
isInt())
174 uint64_t Size = SizeValue.
getInt().getZExtValue();
176 auto PtrRes =
C.interpretAsPointer(PtrExpr, [&](
const Pointer &Ptr) {
178 if constexpr (std::is_same_v<ResultT, APValue>)
191 Parent.
FFDiag(SizeExpr, diag::note_constexpr_access_past_end) <<
AK_Read;
195 if constexpr (std::is_same_v<ResultT, APValue>) {
198 for (uint64_t I = 0; I !=
Size; ++I) {
199 if (std::optional<APValue> ElemVal =
201 Result.getArrayInitializedElt(I) = *ElemVal;
206 assert((std::is_same_v<ResultT, std::string>));
207 if (Size <
Result.max_size())
215 if (PtrRes.isInvalid()) {
229 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
237 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
245 auto PtrRes =
C.interpretAsPointer(E, [&](
const Pointer &Ptr) {
256 const char *Chars =
reinterpret_cast<const char *
>(Ptr.
getRawAddress());
257 unsigned Length = strnlen(Chars, N);
261 Result.assign(Chars, Length);
266 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
268 auto Elem = Ptr.
elem<
T>(I);
271 Result.push_back(
static_cast<char>(Elem));
278 if (PtrRes.isInvalid()) {
290 auto PtrRes =
C.interpretAsPointer(E, [&](
const Pointer &Ptr) {
306 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
308 auto Elem = Ptr.
elem<
T>(I);
318 if (PtrRes.isInvalid()) {
341 llvm_unreachable(
"Unhandled BitWidth");
357 llvm_unreachable(
"Unhandled BitWidth");
362 if (
const auto *BT = dyn_cast<BuiltinType>(
T.getCanonicalType())) {
363 auto Kind = BT->getKind();
364 if (Kind == BuiltinType::Bool)
366 if (Kind == BuiltinType::NullPtr)
368 if (Kind == BuiltinType::BoundMember)
372 if (Kind == BuiltinType::Short)
374 if (Kind == BuiltinType::UShort)
377 if (Kind == BuiltinType::Int)
379 if (Kind == BuiltinType::UInt)
381 if (Kind == BuiltinType::Long)
383 if (Kind == BuiltinType::ULong)
385 if (Kind == BuiltinType::LongLong)
387 if (Kind == BuiltinType::ULongLong)
390 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
392 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
393 Kind == BuiltinType::Char8)
396 if (BT->isSignedInteger())
398 if (BT->isUnsignedInteger())
401 if (BT->isFloatingPoint())
405 if (
T->isPointerOrReferenceType())
408 if (
T->isMemberPointerType())
417 if (
const auto *D =
T->getAsEnumDecl()) {
418 if (!D->isComplete())
420 return classify(D->getIntegerType());
424 return classify(AT->getValueType());
426 if (
const auto *DT = dyn_cast<DecltypeType>(
T))
427 return classify(DT->getUnderlyingType());
429 if (
T->isObjCObjectPointerType() ||
T->isBlockPointerType())
432 if (
T->isFixedPointType())
440 return Ctx.getTargetInfo().getCharWidth();
446 return Ctx.getFloatTypeSemantics(
T);
466 assert(InitialFunction);
485 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
493 "Couldn't find an overriding function in the class hierarchy?");
507 bool IsLambdaStaticInvoker =
false;
508 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
509 MD && MD->isLambdaStaticInvoker()) {
515 IsLambdaStaticInvoker =
true;
521 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
530 ParamTypes.push_back(
PT_Ptr);
538 bool HasThisPointer =
false;
539 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
540 if (!IsLambdaStaticInvoker) {
541 HasThisPointer = MD->isInstance();
542 if (MD->isImplicitObjectMemberFunction()) {
543 ParamTypes.push_back(
PT_Ptr);
552 if (!MD->getParent()->isCompleteDefinition())
554 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
557 MD->
getParent()->getCaptureFields(LC, LTC);
559 if (MD->isStatic() && !LC.empty()) {
572 Descriptor *Desc = P->createDescriptor(PD, PT);
573 ParamDescriptors.insert({
ParamOffset, {PT, Desc}});
576 ParamTypes.push_back(PT);
580 assert(!P->getFunction(FuncDecl));
582 FuncDecl,
ParamOffset, std::move(ParamTypes), std::move(ParamDescriptors),
583 std::move(ParamOffsets), HasThisPointer, HasRVO, IsLambdaStaticInvoker);
593 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
600 Descriptor *Desc = P->createDescriptor(PD, PT);
601 ParamDescriptors.insert({
ParamOffset, {PT, Desc}});
604 ParamTypes.push_back(PT);
612 P->createFunction(E,
ParamOffset, std::move(ParamTypes),
613 std::move(ParamDescriptors), std::move(ParamOffsets),
618 Func->setDefined(
true);
620 Func->setIsFullyCompiled(
true);
630 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
631 assert(CurDecl && FinalDecl);
633 unsigned OffsetSum = 0;
637 for (
const Record::Base &B : CurRecord->
bases()) {
640 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
641 OffsetSum += B.Offset;
647 if (CurDecl == FinalDecl)
651 assert(OffsetSum > 0);
656 return P->getOrCreateRecord(D);
660 return ID == Builtin::BI__builtin_classify_type ||
661 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
662 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
This file provides some common utility functions for processing Lambda related AST Constructs.
static PrimType integralTypeToPrimTypeS(unsigned BitWidth)
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
#define INT_TYPE_SWITCH(Expr, B)
static bool isRecordType(QualType T)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A fixed int type of a specified bitwidth.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
ArrayRef< ParmVarDecl * > parameters() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const BlockDecl * getBlockDecl() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
CXXMethodDecl * getCorrespondingMethodDeclaredInClass(const CXXRecordDecl *RD, bool MayBeBase=false)
Find if RD declares a function that overrides this function, and if so, return it.
Represents a C++ struct/union/class.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
This represents one expression.
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a parameter to a function.
A (possibly-)qualified type.
Represents a struct/union/class.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Represents a variable declaration or definition.
Compilation context for expressions.
const LangOptions & getLangOpts() const
Returns the language options.
const Function * getOrCreateObjCBlock(const BlockExpr *E)
~Context()
Cleans up the constexpr VM.
Context(ASTContext &Ctx)
Initialises the constexpr VM.
bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
bool canClassify(QualType T)
bool evaluateString(State &Parent, const Expr *E, std::string &Result)
Evaluate.
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
unsigned getCharBit() const
Returns CHAR_BIT.
bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result)
Evalute.
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, const FunctionDecl *FD)
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
const Record * getRecord(const RecordDecl *D) const
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
OptPrimType classify(QualType T) const
Classifies a type.
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
bool evaluate(State &Parent, const Expr *E, APValue &Result, ConstantExprKind Kind)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init, APValue &Result)
Evaluates a toplevel initializer.
void clear()
Clears the stack.
bool empty() const
Returns whether the stack is empty.
A pointer to a memory block, live or dead.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
int64_t getIndex() const
Returns the index into an array.
bool isConst() const
Checks if an object or a subfield is mutable.
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
bool isLive() const
Checks if the pointer is live.
T & elem(unsigned I) const
Dereferences the element at index I.
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
size_t elemSize() const
Returns the element size of the innermost field.
const std::byte * getRawAddress() const
If backed by actual data (i.e.
The program contains and links the bytecode for all functions.
Structure/Class descriptor.
unsigned getNumBases() const
llvm::iterator_range< const_base_iter > bases() const
Interface for the VM to interact with the AST walker's context.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Defines the clang::TargetInfo interface.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
bool Init(InterpState &S, CodePtr OpPC)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool Interpret(InterpState &S)
Interpreter entry point.
The JSON file list parser is used to communicate input to InstallAPI.
Expr::ConstantExprKind ConstantExprKind
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Describes a memory block created by an allocation site.
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const