diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Interp/Function.h')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/Interp/Function.h | 162 |
1 files changed, 142 insertions, 20 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Function.h b/contrib/llvm-project/clang/lib/AST/Interp/Function.h index 28531f04b6e9..92bcd9692791 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Function.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Function.h @@ -15,8 +15,10 @@ #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H #define LLVM_CLANG_AST_INTERP_FUNCTION_H -#include "Pointer.h" +#include "Descriptor.h" #include "Source.h" +#include "clang/AST/ASTLambda.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "llvm/Support/raw_ostream.h" @@ -24,12 +26,13 @@ namespace clang { namespace interp { class Program; class ByteCodeEmitter; +class Pointer; enum PrimType : uint32_t; /// Describes a scope block. /// /// The block gathers all the descriptors of the locals defined in this block. -class Scope { +class Scope final { public: /// Information about a local's storage. struct Local { @@ -43,7 +46,7 @@ public: Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {} - llvm::iterator_range<LocalVectorTy::iterator> locals() { + llvm::iterator_range<LocalVectorTy::const_iterator> locals() const { return llvm::make_range(Descriptors.begin(), Descriptors.end()); } @@ -56,74 +59,176 @@ private: /// /// Contains links to the bytecode of the function, as well as metadata /// describing all arguments and stack-local variables. -class Function { +/// +/// # Calling Convention +/// +/// When calling a function, all argument values must be on the stack. +/// +/// If the function has a This pointer (i.e. hasThisPointer() returns true, +/// the argument values need to be preceeded by a Pointer for the This object. +/// +/// If the function uses Return Value Optimization, the arguments (and +/// potentially the This pointer) need to be preceeded by a Pointer pointing +/// to the location to construct the returned value. +/// +/// After the function has been called, it will remove all arguments, +/// including RVO and This pointer, from the stack. +/// +class Function final { public: using ParamDescriptor = std::pair<PrimType, Descriptor *>; /// Returns the size of the function's local stack. unsigned getFrameSize() const { return FrameSize; } - /// Returns the size of the argument stackx + /// Returns the size of the argument stack. unsigned getArgSize() const { return ArgSize; } /// Returns a pointer to the start of the code. - CodePtr getCodeBegin() const; + CodePtr getCodeBegin() const { return Code.data(); } /// Returns a pointer to the end of the code. - CodePtr getCodeEnd() const; + CodePtr getCodeEnd() const { return Code.data() + Code.size(); } /// Returns the original FunctionDecl. const FunctionDecl *getDecl() const { return F; } - /// Returns the lcoation. + /// Returns the name of the function decl this code + /// was generated for. + const std::string getName() const { + if (!F) + return "<<expr>>"; + + return F->getQualifiedNameAsString(); + } + + /// Returns the location. SourceLocation getLoc() const { return Loc; } /// Returns a parameter descriptor. ParamDescriptor getParamDescriptor(unsigned Offset) const; /// Checks if the first argument is a RVO pointer. - bool hasRVO() const { return ParamTypes.size() != Params.size(); } + bool hasRVO() const { return HasRVO; } + + bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); } /// Range over the scope blocks. - llvm::iterator_range<llvm::SmallVector<Scope, 2>::iterator> scopes() { + llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator> + scopes() const { return llvm::make_range(Scopes.begin(), Scopes.end()); } /// Range over argument types. - using arg_reverse_iterator = SmallVectorImpl<PrimType>::reverse_iterator; - llvm::iterator_range<arg_reverse_iterator> args_reverse() { - return llvm::make_range(ParamTypes.rbegin(), ParamTypes.rend()); + using arg_reverse_iterator = + SmallVectorImpl<PrimType>::const_reverse_iterator; + llvm::iterator_range<arg_reverse_iterator> args_reverse() const { + return llvm::reverse(ParamTypes); } /// Returns a specific scope. Scope &getScope(unsigned Idx) { return Scopes[Idx]; } + const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; } /// Returns the source information at a given PC. SourceInfo getSource(CodePtr PC) const; /// Checks if the function is valid to call in constexpr. - bool isConstexpr() const { return IsValid; } + bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); } /// Checks if the function is virtual. bool isVirtual() const; /// Checks if the function is a constructor. bool isConstructor() const { return isa<CXXConstructorDecl>(F); } + /// Checks if the function is a destructor. + bool isDestructor() const { return isa<CXXDestructorDecl>(F); } + + /// Returns the parent record decl, if any. + const CXXRecordDecl *getParentDecl() const { + if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) + return MD->getParent(); + return nullptr; + } + + /// Returns whether this function is a lambda static invoker, + /// which we generate custom byte code for. + bool isLambdaStaticInvoker() const { + if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) + return MD->isLambdaStaticInvoker(); + return false; + } + + /// Returns whether this function is the call operator + /// of a lambda record decl. + bool isLambdaCallOperator() const { + if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) + return clang::isLambdaCallOperator(MD); + return false; + } + + /// Checks if the function is fully done compiling. + bool isFullyCompiled() const { return IsFullyCompiled; } + + bool hasThisPointer() const { return HasThisPointer; } + + /// Checks if the function already has a body attached. + bool hasBody() const { return HasBody; } + + /// Checks if the function is defined. + bool isDefined() const { return Defined; } + + bool isVariadic() const { return Variadic; } + + unsigned getBuiltinID() const { return F->getBuiltinID(); } + + bool isBuiltin() const { return F->getBuiltinID() != 0; } + + bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; } + + unsigned getNumParams() const { return ParamTypes.size(); } + + /// Returns the number of parameter this function takes when it's called, + /// i.e excluding the instance pointer and the RVO pointer. + unsigned getNumWrittenParams() const { + assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO())); + return getNumParams() - hasThisPointer() - hasRVO(); + } + unsigned getWrittenArgSize() const { + return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO())); + } + + bool isThisPointerExplicit() const { + if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) + return MD->isExplicitObjectMemberFunction(); + return false; + } + + unsigned getParamOffset(unsigned ParamIndex) const { + return ParamOffsets[ParamIndex]; + } private: /// Construct a function representing an actual function. Function(Program &P, const FunctionDecl *F, unsigned ArgSize, - llvm::SmallVector<PrimType, 8> &&ParamTypes, - llvm::DenseMap<unsigned, ParamDescriptor> &&Params); + llvm::SmallVectorImpl<PrimType> &&ParamTypes, + llvm::DenseMap<unsigned, ParamDescriptor> &&Params, + llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer, + bool HasRVO, bool UnevaluatedBuiltin); /// Sets the code of a function. - void setCode(unsigned NewFrameSize, std::vector<char> &&NewCode, SourceMap &&NewSrcMap, - llvm::SmallVector<Scope, 2> &&NewScopes) { + void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, + SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes, + bool NewHasBody) { FrameSize = NewFrameSize; Code = std::move(NewCode); SrcMap = std::move(NewSrcMap); Scopes = std::move(NewScopes); IsValid = true; + HasBody = NewHasBody; } + void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; } + void setDefined(bool D) { Defined = D; } + private: friend class Program; friend class ByteCodeEmitter; @@ -135,11 +240,11 @@ private: /// Declaration this function was compiled from. const FunctionDecl *F; /// Local area size: storage + metadata. - unsigned FrameSize; + unsigned FrameSize = 0; /// Size of the argument stack. unsigned ArgSize; /// Program code. - std::vector<char> Code; + std::vector<std::byte> Code; /// Opcode-to-expression mapping. SourceMap SrcMap; /// List of block descriptors. @@ -148,8 +253,25 @@ private: llvm::SmallVector<PrimType, 8> ParamTypes; /// Map from byte offset to parameter descriptor. llvm::DenseMap<unsigned, ParamDescriptor> Params; + /// List of parameter offsets. + llvm::SmallVector<unsigned, 8> ParamOffsets; /// Flag to indicate if the function is valid. bool IsValid = false; + /// Flag to indicate if the function is done being + /// compiled to bytecode. + bool IsFullyCompiled = false; + /// Flag indicating if this function takes the this pointer + /// as the first implicit argument + bool HasThisPointer = false; + /// Whether this function has Return Value Optimization, i.e. + /// the return value is constructed in the caller's stack frame. + /// This is done for functions that return non-primive values. + bool HasRVO = false; + /// If we've already compiled the function's body. + bool HasBody = false; + bool Defined = false; + bool Variadic = false; + bool IsUnevaluatedBuiltin = false; public: /// Dumps the disassembled bytecode to \c llvm::errs(). |