1a07aba5dSTimm Baeder //===--- Function.h - Bytecode function for the VM --------------*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder // 9a07aba5dSTimm Baeder // Defines the Function class which holds all bytecode function-specific data. 10a07aba5dSTimm Baeder // 11a07aba5dSTimm Baeder // The scope class which describes local variables is also defined here. 12a07aba5dSTimm Baeder // 13a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 14a07aba5dSTimm Baeder 15a07aba5dSTimm Baeder #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H 16a07aba5dSTimm Baeder #define LLVM_CLANG_AST_INTERP_FUNCTION_H 17a07aba5dSTimm Baeder 18a07aba5dSTimm Baeder #include "Descriptor.h" 19a07aba5dSTimm Baeder #include "Source.h" 20a07aba5dSTimm Baeder #include "clang/AST/ASTLambda.h" 21a07aba5dSTimm Baeder #include "clang/AST/Attr.h" 22a07aba5dSTimm Baeder #include "clang/AST/Decl.h" 23ca148b21STimm Baeder #include "llvm/ADT/PointerUnion.h" 24a07aba5dSTimm Baeder #include "llvm/Support/raw_ostream.h" 25a07aba5dSTimm Baeder 26a07aba5dSTimm Baeder namespace clang { 27a07aba5dSTimm Baeder namespace interp { 28a07aba5dSTimm Baeder class Program; 29a07aba5dSTimm Baeder class ByteCodeEmitter; 30a07aba5dSTimm Baeder class Pointer; 31a07aba5dSTimm Baeder enum PrimType : uint32_t; 32a07aba5dSTimm Baeder 33a07aba5dSTimm Baeder /// Describes a scope block. 34a07aba5dSTimm Baeder /// 35a07aba5dSTimm Baeder /// The block gathers all the descriptors of the locals defined in this block. 36a07aba5dSTimm Baeder class Scope final { 37a07aba5dSTimm Baeder public: 38a07aba5dSTimm Baeder /// Information about a local's storage. 39a07aba5dSTimm Baeder struct Local { 40a07aba5dSTimm Baeder /// Offset of the local in frame. 41a07aba5dSTimm Baeder unsigned Offset; 42a07aba5dSTimm Baeder /// Descriptor of the local. 43a07aba5dSTimm Baeder Descriptor *Desc; 44a07aba5dSTimm Baeder }; 45a07aba5dSTimm Baeder 46a07aba5dSTimm Baeder using LocalVectorTy = llvm::SmallVector<Local, 8>; 47a07aba5dSTimm Baeder 48a07aba5dSTimm Baeder Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {} 49a07aba5dSTimm Baeder 50a07aba5dSTimm Baeder llvm::iterator_range<LocalVectorTy::const_iterator> locals() const { 51a07aba5dSTimm Baeder return llvm::make_range(Descriptors.begin(), Descriptors.end()); 52a07aba5dSTimm Baeder } 53a07aba5dSTimm Baeder 54a07aba5dSTimm Baeder private: 55a07aba5dSTimm Baeder /// Object descriptors in this block. 56a07aba5dSTimm Baeder LocalVectorTy Descriptors; 57a07aba5dSTimm Baeder }; 58a07aba5dSTimm Baeder 59ca148b21STimm Baeder using FunctionDeclTy = 60ca148b21STimm Baeder llvm::PointerUnion<const FunctionDecl *, const BlockExpr *>; 61ca148b21STimm Baeder 62a07aba5dSTimm Baeder /// Bytecode function. 63a07aba5dSTimm Baeder /// 64a07aba5dSTimm Baeder /// Contains links to the bytecode of the function, as well as metadata 65a07aba5dSTimm Baeder /// describing all arguments and stack-local variables. 66a07aba5dSTimm Baeder /// 67a07aba5dSTimm Baeder /// # Calling Convention 68a07aba5dSTimm Baeder /// 69a07aba5dSTimm Baeder /// When calling a function, all argument values must be on the stack. 70a07aba5dSTimm Baeder /// 71a07aba5dSTimm Baeder /// If the function has a This pointer (i.e. hasThisPointer() returns true, 72a07aba5dSTimm Baeder /// the argument values need to be preceeded by a Pointer for the This object. 73a07aba5dSTimm Baeder /// 74a07aba5dSTimm Baeder /// If the function uses Return Value Optimization, the arguments (and 75a07aba5dSTimm Baeder /// potentially the This pointer) need to be preceeded by a Pointer pointing 76a07aba5dSTimm Baeder /// to the location to construct the returned value. 77a07aba5dSTimm Baeder /// 78a07aba5dSTimm Baeder /// After the function has been called, it will remove all arguments, 79a07aba5dSTimm Baeder /// including RVO and This pointer, from the stack. 80a07aba5dSTimm Baeder /// 81a07aba5dSTimm Baeder class Function final { 82a07aba5dSTimm Baeder public: 83a07aba5dSTimm Baeder using ParamDescriptor = std::pair<PrimType, Descriptor *>; 84a07aba5dSTimm Baeder 85a07aba5dSTimm Baeder /// Returns the size of the function's local stack. 86a07aba5dSTimm Baeder unsigned getFrameSize() const { return FrameSize; } 87a07aba5dSTimm Baeder /// Returns the size of the argument stack. 88a07aba5dSTimm Baeder unsigned getArgSize() const { return ArgSize; } 89a07aba5dSTimm Baeder 90a07aba5dSTimm Baeder /// Returns a pointer to the start of the code. 91a07aba5dSTimm Baeder CodePtr getCodeBegin() const { return Code.data(); } 92a07aba5dSTimm Baeder /// Returns a pointer to the end of the code. 93a07aba5dSTimm Baeder CodePtr getCodeEnd() const { return Code.data() + Code.size(); } 94a07aba5dSTimm Baeder 95a07aba5dSTimm Baeder /// Returns the original FunctionDecl. 96ca148b21STimm Baeder const FunctionDecl *getDecl() const { 97*23fbaff9SKazu Hirata return dyn_cast<const FunctionDecl *>(Source); 98ca148b21STimm Baeder } 99ca148b21STimm Baeder const BlockExpr *getExpr() const { 100*23fbaff9SKazu Hirata return dyn_cast<const BlockExpr *>(Source); 101ca148b21STimm Baeder } 102a07aba5dSTimm Baeder 103a07aba5dSTimm Baeder /// Returns the name of the function decl this code 104a07aba5dSTimm Baeder /// was generated for. 105a07aba5dSTimm Baeder const std::string getName() const { 1067d4afba8STimm Bäder if (!Source || !getDecl()) 107a07aba5dSTimm Baeder return "<<expr>>"; 108a07aba5dSTimm Baeder 1097d4afba8STimm Bäder return getDecl()->getQualifiedNameAsString(); 110a07aba5dSTimm Baeder } 111a07aba5dSTimm Baeder 112a07aba5dSTimm Baeder /// Returns a parameter descriptor. 113a07aba5dSTimm Baeder ParamDescriptor getParamDescriptor(unsigned Offset) const; 114a07aba5dSTimm Baeder 115a07aba5dSTimm Baeder /// Checks if the first argument is a RVO pointer. 116a07aba5dSTimm Baeder bool hasRVO() const { return HasRVO; } 117a07aba5dSTimm Baeder 118a07aba5dSTimm Baeder bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); } 119a07aba5dSTimm Baeder 120a07aba5dSTimm Baeder /// Range over the scope blocks. 121a07aba5dSTimm Baeder llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator> 122a07aba5dSTimm Baeder scopes() const { 123a07aba5dSTimm Baeder return llvm::make_range(Scopes.begin(), Scopes.end()); 124a07aba5dSTimm Baeder } 125a07aba5dSTimm Baeder 126a07aba5dSTimm Baeder /// Range over argument types. 127a07aba5dSTimm Baeder using arg_reverse_iterator = 128a07aba5dSTimm Baeder SmallVectorImpl<PrimType>::const_reverse_iterator; 129a07aba5dSTimm Baeder llvm::iterator_range<arg_reverse_iterator> args_reverse() const { 130a07aba5dSTimm Baeder return llvm::reverse(ParamTypes); 131a07aba5dSTimm Baeder } 132a07aba5dSTimm Baeder 133a07aba5dSTimm Baeder /// Returns a specific scope. 134a07aba5dSTimm Baeder Scope &getScope(unsigned Idx) { return Scopes[Idx]; } 135a07aba5dSTimm Baeder const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; } 136a07aba5dSTimm Baeder 137a07aba5dSTimm Baeder /// Returns the source information at a given PC. 138a07aba5dSTimm Baeder SourceInfo getSource(CodePtr PC) const; 139a07aba5dSTimm Baeder 140a07aba5dSTimm Baeder /// Checks if the function is valid to call in constexpr. 141a07aba5dSTimm Baeder bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); } 142a07aba5dSTimm Baeder 143a07aba5dSTimm Baeder /// Checks if the function is virtual. 144a07aba5dSTimm Baeder bool isVirtual() const; 145a07aba5dSTimm Baeder 146a07aba5dSTimm Baeder /// Checks if the function is a constructor. 147ca148b21STimm Baeder bool isConstructor() const { 148ca148b21STimm Baeder return isa_and_nonnull<CXXConstructorDecl>( 149*23fbaff9SKazu Hirata dyn_cast<const FunctionDecl *>(Source)); 150ca148b21STimm Baeder } 151a07aba5dSTimm Baeder /// Checks if the function is a destructor. 152ca148b21STimm Baeder bool isDestructor() const { 153ca148b21STimm Baeder return isa_and_nonnull<CXXDestructorDecl>( 154*23fbaff9SKazu Hirata dyn_cast<const FunctionDecl *>(Source)); 155ca148b21STimm Baeder } 156a07aba5dSTimm Baeder 157a07aba5dSTimm Baeder /// Returns the parent record decl, if any. 158a07aba5dSTimm Baeder const CXXRecordDecl *getParentDecl() const { 159ca148b21STimm Baeder if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( 160*23fbaff9SKazu Hirata dyn_cast<const FunctionDecl *>(Source))) 161a07aba5dSTimm Baeder return MD->getParent(); 162a07aba5dSTimm Baeder return nullptr; 163a07aba5dSTimm Baeder } 164a07aba5dSTimm Baeder 165a07aba5dSTimm Baeder /// Returns whether this function is a lambda static invoker, 166a07aba5dSTimm Baeder /// which we generate custom byte code for. 167a07aba5dSTimm Baeder bool isLambdaStaticInvoker() const { 168ca148b21STimm Baeder if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( 169*23fbaff9SKazu Hirata dyn_cast<const FunctionDecl *>(Source))) 170a07aba5dSTimm Baeder return MD->isLambdaStaticInvoker(); 171a07aba5dSTimm Baeder return false; 172a07aba5dSTimm Baeder } 173a07aba5dSTimm Baeder 174a07aba5dSTimm Baeder /// Returns whether this function is the call operator 175a07aba5dSTimm Baeder /// of a lambda record decl. 176a07aba5dSTimm Baeder bool isLambdaCallOperator() const { 177ca148b21STimm Baeder if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( 178*23fbaff9SKazu Hirata dyn_cast<const FunctionDecl *>(Source))) 179a07aba5dSTimm Baeder return clang::isLambdaCallOperator(MD); 180a07aba5dSTimm Baeder return false; 181a07aba5dSTimm Baeder } 182a07aba5dSTimm Baeder 183a07aba5dSTimm Baeder /// Checks if the function is fully done compiling. 184a07aba5dSTimm Baeder bool isFullyCompiled() const { return IsFullyCompiled; } 185a07aba5dSTimm Baeder 186a07aba5dSTimm Baeder bool hasThisPointer() const { return HasThisPointer; } 187a07aba5dSTimm Baeder 188a07aba5dSTimm Baeder /// Checks if the function already has a body attached. 189a07aba5dSTimm Baeder bool hasBody() const { return HasBody; } 190a07aba5dSTimm Baeder 191a07aba5dSTimm Baeder /// Checks if the function is defined. 192a07aba5dSTimm Baeder bool isDefined() const { return Defined; } 193a07aba5dSTimm Baeder 194a07aba5dSTimm Baeder bool isVariadic() const { return Variadic; } 195a07aba5dSTimm Baeder 1963745a2e8STimm Baeder unsigned getBuiltinID() const { return BuiltinID; } 197a07aba5dSTimm Baeder 1983745a2e8STimm Baeder bool isBuiltin() const { return getBuiltinID() != 0; } 199a07aba5dSTimm Baeder 2003745a2e8STimm Baeder bool isUnevaluatedBuiltin() const; 201a07aba5dSTimm Baeder 202a07aba5dSTimm Baeder unsigned getNumParams() const { return ParamTypes.size(); } 203a07aba5dSTimm Baeder 204a07aba5dSTimm Baeder /// Returns the number of parameter this function takes when it's called, 205a07aba5dSTimm Baeder /// i.e excluding the instance pointer and the RVO pointer. 206a07aba5dSTimm Baeder unsigned getNumWrittenParams() const { 207a07aba5dSTimm Baeder assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO())); 208a07aba5dSTimm Baeder return getNumParams() - hasThisPointer() - hasRVO(); 209a07aba5dSTimm Baeder } 210a07aba5dSTimm Baeder unsigned getWrittenArgSize() const { 211a07aba5dSTimm Baeder return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO())); 212a07aba5dSTimm Baeder } 213a07aba5dSTimm Baeder 214a07aba5dSTimm Baeder bool isThisPointerExplicit() const { 215ca148b21STimm Baeder if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( 216ca148b21STimm Baeder Source.dyn_cast<const FunctionDecl *>())) 217a07aba5dSTimm Baeder return MD->isExplicitObjectMemberFunction(); 218a07aba5dSTimm Baeder return false; 219a07aba5dSTimm Baeder } 220a07aba5dSTimm Baeder 221a07aba5dSTimm Baeder unsigned getParamOffset(unsigned ParamIndex) const { 222a07aba5dSTimm Baeder return ParamOffsets[ParamIndex]; 223a07aba5dSTimm Baeder } 224a07aba5dSTimm Baeder 2256f8e8551STimm Baeder PrimType getParamType(unsigned ParamIndex) const { 2266f8e8551STimm Baeder return ParamTypes[ParamIndex]; 2276f8e8551STimm Baeder } 2286f8e8551STimm Baeder 229a07aba5dSTimm Baeder private: 230a07aba5dSTimm Baeder /// Construct a function representing an actual function. 231ca148b21STimm Baeder Function(Program &P, FunctionDeclTy Source, unsigned ArgSize, 232a07aba5dSTimm Baeder llvm::SmallVectorImpl<PrimType> &&ParamTypes, 233a07aba5dSTimm Baeder llvm::DenseMap<unsigned, ParamDescriptor> &&Params, 234a07aba5dSTimm Baeder llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer, 2353745a2e8STimm Baeder bool HasRVO, unsigned BuiltinID); 236a07aba5dSTimm Baeder 237a07aba5dSTimm Baeder /// Sets the code of a function. 238a07aba5dSTimm Baeder void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, 239a07aba5dSTimm Baeder SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes, 240a07aba5dSTimm Baeder bool NewHasBody) { 241a07aba5dSTimm Baeder FrameSize = NewFrameSize; 242a07aba5dSTimm Baeder Code = std::move(NewCode); 243a07aba5dSTimm Baeder SrcMap = std::move(NewSrcMap); 244a07aba5dSTimm Baeder Scopes = std::move(NewScopes); 245a07aba5dSTimm Baeder IsValid = true; 246a07aba5dSTimm Baeder HasBody = NewHasBody; 247a07aba5dSTimm Baeder } 248a07aba5dSTimm Baeder 249a07aba5dSTimm Baeder void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; } 250a07aba5dSTimm Baeder void setDefined(bool D) { Defined = D; } 251a07aba5dSTimm Baeder 252a07aba5dSTimm Baeder private: 253a07aba5dSTimm Baeder friend class Program; 254a07aba5dSTimm Baeder friend class ByteCodeEmitter; 255a07aba5dSTimm Baeder 256a07aba5dSTimm Baeder /// Program reference. 257a07aba5dSTimm Baeder Program &P; 258a07aba5dSTimm Baeder /// Declaration this function was compiled from. 259ca148b21STimm Baeder FunctionDeclTy Source; 260a07aba5dSTimm Baeder /// Local area size: storage + metadata. 261a07aba5dSTimm Baeder unsigned FrameSize = 0; 262a07aba5dSTimm Baeder /// Size of the argument stack. 263a07aba5dSTimm Baeder unsigned ArgSize; 264a07aba5dSTimm Baeder /// Program code. 265a07aba5dSTimm Baeder std::vector<std::byte> Code; 266a07aba5dSTimm Baeder /// Opcode-to-expression mapping. 267a07aba5dSTimm Baeder SourceMap SrcMap; 268a07aba5dSTimm Baeder /// List of block descriptors. 269a07aba5dSTimm Baeder llvm::SmallVector<Scope, 2> Scopes; 270a07aba5dSTimm Baeder /// List of argument types. 271a07aba5dSTimm Baeder llvm::SmallVector<PrimType, 8> ParamTypes; 272a07aba5dSTimm Baeder /// Map from byte offset to parameter descriptor. 273a07aba5dSTimm Baeder llvm::DenseMap<unsigned, ParamDescriptor> Params; 274a07aba5dSTimm Baeder /// List of parameter offsets. 275a07aba5dSTimm Baeder llvm::SmallVector<unsigned, 8> ParamOffsets; 276a07aba5dSTimm Baeder /// Flag to indicate if the function is valid. 277a07aba5dSTimm Baeder bool IsValid = false; 278a07aba5dSTimm Baeder /// Flag to indicate if the function is done being 279a07aba5dSTimm Baeder /// compiled to bytecode. 280a07aba5dSTimm Baeder bool IsFullyCompiled = false; 281a07aba5dSTimm Baeder /// Flag indicating if this function takes the this pointer 282a07aba5dSTimm Baeder /// as the first implicit argument 283a07aba5dSTimm Baeder bool HasThisPointer = false; 284a07aba5dSTimm Baeder /// Whether this function has Return Value Optimization, i.e. 285a07aba5dSTimm Baeder /// the return value is constructed in the caller's stack frame. 286a07aba5dSTimm Baeder /// This is done for functions that return non-primive values. 287a07aba5dSTimm Baeder bool HasRVO = false; 288a07aba5dSTimm Baeder /// If we've already compiled the function's body. 289a07aba5dSTimm Baeder bool HasBody = false; 290a07aba5dSTimm Baeder bool Defined = false; 291a07aba5dSTimm Baeder bool Variadic = false; 2923745a2e8STimm Baeder unsigned BuiltinID = 0; 293a07aba5dSTimm Baeder 294a07aba5dSTimm Baeder public: 295a07aba5dSTimm Baeder /// Dumps the disassembled bytecode to \c llvm::errs(). 296a07aba5dSTimm Baeder void dump() const; 297a07aba5dSTimm Baeder void dump(llvm::raw_ostream &OS) const; 298a07aba5dSTimm Baeder }; 299a07aba5dSTimm Baeder 300a07aba5dSTimm Baeder } // namespace interp 301a07aba5dSTimm Baeder } // namespace clang 302a07aba5dSTimm Baeder 303a07aba5dSTimm Baeder #endif 304