Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/Function.h
213799 views
//===--- Function.h - Bytecode function for the VM --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines the Function class which holds all bytecode function-specific data.9//10// The scope class which describes local variables is also defined here.11//12//===----------------------------------------------------------------------===//1314#ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H15#define LLVM_CLANG_AST_INTERP_FUNCTION_H1617#include "Descriptor.h"18#include "Source.h"19#include "clang/AST/ASTLambda.h"20#include "clang/AST/Attr.h"21#include "clang/AST/Decl.h"22#include "llvm/ADT/PointerUnion.h"23#include "llvm/Support/raw_ostream.h"2425namespace clang {26namespace interp {27class Program;28class ByteCodeEmitter;29class Pointer;30enum PrimType : uint32_t;3132/// Describes a scope block.33///34/// The block gathers all the descriptors of the locals defined in this block.35class Scope final {36public:37/// Information about a local's storage.38struct Local {39/// Offset of the local in frame.40unsigned Offset;41/// Descriptor of the local.42Descriptor *Desc;43};4445using LocalVectorTy = llvm::SmallVector<Local, 8>;4647Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}4849llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {50return llvm::make_range(Descriptors.begin(), Descriptors.end());51}5253llvm::iterator_range<LocalVectorTy::const_reverse_iterator>54locals_reverse() const {55return llvm::reverse(Descriptors);56}5758private:59/// Object descriptors in this block.60LocalVectorTy Descriptors;61};6263using FunctionDeclTy =64llvm::PointerUnion<const FunctionDecl *, const BlockExpr *>;6566/// Bytecode function.67///68/// Contains links to the bytecode of the function, as well as metadata69/// describing all arguments and stack-local variables.70///71/// # Calling Convention72///73/// When calling a function, all argument values must be on the stack.74///75/// If the function has a This pointer (i.e. hasThisPointer() returns true,76/// the argument values need to be preceeded by a Pointer for the This object.77///78/// If the function uses Return Value Optimization, the arguments (and79/// potentially the This pointer) need to be preceeded by a Pointer pointing80/// to the location to construct the returned value.81///82/// After the function has been called, it will remove all arguments,83/// including RVO and This pointer, from the stack.84///85class Function final {86public:87enum class FunctionKind {88Normal,89Ctor,90Dtor,91LambdaStaticInvoker,92LambdaCallOperator,93CopyOrMoveOperator,94};95using ParamDescriptor = std::pair<PrimType, Descriptor *>;9697/// Returns the size of the function's local stack.98unsigned getFrameSize() const { return FrameSize; }99/// Returns the size of the argument stack.100unsigned getArgSize() const { return ArgSize; }101102/// Returns a pointer to the start of the code.103CodePtr getCodeBegin() const { return Code.data(); }104/// Returns a pointer to the end of the code.105CodePtr getCodeEnd() const { return Code.data() + Code.size(); }106107/// Returns the original FunctionDecl.108const FunctionDecl *getDecl() const {109return dyn_cast<const FunctionDecl *>(Source);110}111const BlockExpr *getExpr() const {112return dyn_cast<const BlockExpr *>(Source);113}114115/// Returns the name of the function decl this code116/// was generated for.117std::string getName() const {118if (!Source || !getDecl())119return "<<expr>>";120121return getDecl()->getQualifiedNameAsString();122}123124/// Returns a parameter descriptor.125ParamDescriptor getParamDescriptor(unsigned Offset) const;126127/// Checks if the first argument is a RVO pointer.128bool hasRVO() const { return HasRVO; }129130bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); }131132/// Range over the scope blocks.133llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>134scopes() const {135return llvm::make_range(Scopes.begin(), Scopes.end());136}137138/// Range over argument types.139using arg_reverse_iterator =140SmallVectorImpl<PrimType>::const_reverse_iterator;141llvm::iterator_range<arg_reverse_iterator> args_reverse() const {142return llvm::reverse(ParamTypes);143}144145/// Returns a specific scope.146Scope &getScope(unsigned Idx) { return Scopes[Idx]; }147const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }148149/// Returns the source information at a given PC.150SourceInfo getSource(CodePtr PC) const;151152/// Checks if the function is valid to call.153bool isValid() const { return IsValid || isLambdaStaticInvoker(); }154155/// Checks if the function is virtual.156bool isVirtual() const { return Virtual; };157bool isImmediate() const { return Immediate; }158bool isConstexpr() const { return Constexpr; }159160/// Checks if the function is a constructor.161bool isConstructor() const { return Kind == FunctionKind::Ctor; }162/// Checks if the function is a destructor.163bool isDestructor() const { return Kind == FunctionKind::Dtor; }164/// Checks if the function is copy or move operator.165bool isCopyOrMoveOperator() const {166return Kind == FunctionKind::CopyOrMoveOperator;167}168169/// Returns whether this function is a lambda static invoker,170/// which we generate custom byte code for.171bool isLambdaStaticInvoker() const {172return Kind == FunctionKind::LambdaStaticInvoker;173}174175/// Returns whether this function is the call operator176/// of a lambda record decl.177bool isLambdaCallOperator() const {178return Kind == FunctionKind::LambdaCallOperator;179}180181/// Returns the parent record decl, if any.182const CXXRecordDecl *getParentDecl() const {183if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(184dyn_cast<const FunctionDecl *>(Source)))185return MD->getParent();186return nullptr;187}188189/// Checks if the function is fully done compiling.190bool isFullyCompiled() const { return IsFullyCompiled; }191192bool hasThisPointer() const { return HasThisPointer; }193194/// Checks if the function already has a body attached.195bool hasBody() const { return HasBody; }196197/// Checks if the function is defined.198bool isDefined() const { return Defined; }199200bool isVariadic() const { return Variadic; }201202unsigned getNumParams() const { return ParamTypes.size(); }203204/// Returns the number of parameter this function takes when it's called,205/// i.e excluding the instance pointer and the RVO pointer.206unsigned getNumWrittenParams() const {207assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO()));208return getNumParams() - hasThisPointer() - hasRVO();209}210unsigned getWrittenArgSize() const {211return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO()));212}213214bool isThisPointerExplicit() const {215if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(216dyn_cast<const FunctionDecl *>(Source)))217return MD->isExplicitObjectMemberFunction();218return false;219}220221unsigned getParamOffset(unsigned ParamIndex) const {222return ParamOffsets[ParamIndex];223}224225PrimType getParamType(unsigned ParamIndex) const {226return ParamTypes[ParamIndex];227}228229private:230/// Construct a function representing an actual function.231Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,232llvm::SmallVectorImpl<PrimType> &&ParamTypes,233llvm::DenseMap<unsigned, ParamDescriptor> &&Params,234llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,235bool HasRVO, bool IsLambdaStaticInvoker);236237/// Sets the code of a function.238void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,239SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,240bool NewHasBody) {241FrameSize = NewFrameSize;242Code = std::move(NewCode);243SrcMap = std::move(NewSrcMap);244Scopes = std::move(NewScopes);245IsValid = true;246HasBody = NewHasBody;247}248249void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }250void setDefined(bool D) { Defined = D; }251252private:253friend class Program;254friend class ByteCodeEmitter;255friend class Context;256257/// Program reference.258Program &P;259/// Function Kind.260FunctionKind Kind;261/// Declaration this function was compiled from.262FunctionDeclTy Source;263/// Local area size: storage + metadata.264unsigned FrameSize = 0;265/// Size of the argument stack.266unsigned ArgSize;267/// Program code.268std::vector<std::byte> Code;269/// Opcode-to-expression mapping.270SourceMap SrcMap;271/// List of block descriptors.272llvm::SmallVector<Scope, 2> Scopes;273/// List of argument types.274llvm::SmallVector<PrimType, 8> ParamTypes;275/// Map from byte offset to parameter descriptor.276llvm::DenseMap<unsigned, ParamDescriptor> Params;277/// List of parameter offsets.278llvm::SmallVector<unsigned, 8> ParamOffsets;279/// Flag to indicate if the function is valid.280LLVM_PREFERRED_TYPE(bool)281unsigned IsValid : 1;282/// Flag to indicate if the function is done being283/// compiled to bytecode.284LLVM_PREFERRED_TYPE(bool)285unsigned IsFullyCompiled : 1;286/// Flag indicating if this function takes the this pointer287/// as the first implicit argument288LLVM_PREFERRED_TYPE(bool)289unsigned HasThisPointer : 1;290/// Whether this function has Return Value Optimization, i.e.291/// the return value is constructed in the caller's stack frame.292/// This is done for functions that return non-primive values.293LLVM_PREFERRED_TYPE(bool)294unsigned HasRVO : 1;295/// If we've already compiled the function's body.296LLVM_PREFERRED_TYPE(bool)297unsigned HasBody : 1;298LLVM_PREFERRED_TYPE(bool)299unsigned Defined : 1;300LLVM_PREFERRED_TYPE(bool)301unsigned Variadic : 1;302LLVM_PREFERRED_TYPE(bool)303unsigned Virtual : 1;304LLVM_PREFERRED_TYPE(bool)305unsigned Immediate : 1;306LLVM_PREFERRED_TYPE(bool)307unsigned Constexpr : 1;308309public:310/// Dumps the disassembled bytecode to \c llvm::errs().311void dump() const;312void dump(llvm::raw_ostream &OS) const;313};314315} // namespace interp316} // namespace clang317318#endif319320321