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