Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/Function.h
35291 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/Support/raw_ostream.h"2324namespace clang {25namespace interp {26class Program;27class ByteCodeEmitter;28class Pointer;29enum PrimType : uint32_t;3031/// Describes a scope block.32///33/// The block gathers all the descriptors of the locals defined in this block.34class Scope final {35public:36/// Information about a local's storage.37struct Local {38/// Offset of the local in frame.39unsigned Offset;40/// Descriptor of the local.41Descriptor *Desc;42};4344using LocalVectorTy = llvm::SmallVector<Local, 8>;4546Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}4748llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {49return llvm::make_range(Descriptors.begin(), Descriptors.end());50}5152private:53/// Object descriptors in this block.54LocalVectorTy Descriptors;55};5657/// Bytecode function.58///59/// Contains links to the bytecode of the function, as well as metadata60/// describing all arguments and stack-local variables.61///62/// # Calling Convention63///64/// When calling a function, all argument values must be on the stack.65///66/// If the function has a This pointer (i.e. hasThisPointer() returns true,67/// the argument values need to be preceeded by a Pointer for the This object.68///69/// If the function uses Return Value Optimization, the arguments (and70/// potentially the This pointer) need to be preceeded by a Pointer pointing71/// to the location to construct the returned value.72///73/// After the function has been called, it will remove all arguments,74/// including RVO and This pointer, from the stack.75///76class Function final {77public:78using ParamDescriptor = std::pair<PrimType, Descriptor *>;7980/// Returns the size of the function's local stack.81unsigned getFrameSize() const { return FrameSize; }82/// Returns the size of the argument stack.83unsigned getArgSize() const { return ArgSize; }8485/// Returns a pointer to the start of the code.86CodePtr getCodeBegin() const { return Code.data(); }87/// Returns a pointer to the end of the code.88CodePtr getCodeEnd() const { return Code.data() + Code.size(); }8990/// Returns the original FunctionDecl.91const FunctionDecl *getDecl() const { return F; }9293/// Returns the name of the function decl this code94/// was generated for.95const std::string getName() const {96if (!F)97return "<<expr>>";9899return F->getQualifiedNameAsString();100}101102/// Returns the location.103SourceLocation getLoc() const { return Loc; }104105/// Returns a parameter descriptor.106ParamDescriptor getParamDescriptor(unsigned Offset) const;107108/// Checks if the first argument is a RVO pointer.109bool hasRVO() const { return HasRVO; }110111bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); }112113/// Range over the scope blocks.114llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>115scopes() const {116return llvm::make_range(Scopes.begin(), Scopes.end());117}118119/// Range over argument types.120using arg_reverse_iterator =121SmallVectorImpl<PrimType>::const_reverse_iterator;122llvm::iterator_range<arg_reverse_iterator> args_reverse() const {123return llvm::reverse(ParamTypes);124}125126/// Returns a specific scope.127Scope &getScope(unsigned Idx) { return Scopes[Idx]; }128const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }129130/// Returns the source information at a given PC.131SourceInfo getSource(CodePtr PC) const;132133/// Checks if the function is valid to call in constexpr.134bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); }135136/// Checks if the function is virtual.137bool isVirtual() const;138139/// Checks if the function is a constructor.140bool isConstructor() const { return isa<CXXConstructorDecl>(F); }141/// Checks if the function is a destructor.142bool isDestructor() const { return isa<CXXDestructorDecl>(F); }143144/// Returns the parent record decl, if any.145const CXXRecordDecl *getParentDecl() const {146if (const auto *MD = dyn_cast<CXXMethodDecl>(F))147return MD->getParent();148return nullptr;149}150151/// Returns whether this function is a lambda static invoker,152/// which we generate custom byte code for.153bool isLambdaStaticInvoker() const {154if (const auto *MD = dyn_cast<CXXMethodDecl>(F))155return MD->isLambdaStaticInvoker();156return false;157}158159/// Returns whether this function is the call operator160/// of a lambda record decl.161bool isLambdaCallOperator() const {162if (const auto *MD = dyn_cast<CXXMethodDecl>(F))163return clang::isLambdaCallOperator(MD);164return false;165}166167/// Checks if the function is fully done compiling.168bool isFullyCompiled() const { return IsFullyCompiled; }169170bool hasThisPointer() const { return HasThisPointer; }171172/// Checks if the function already has a body attached.173bool hasBody() const { return HasBody; }174175/// Checks if the function is defined.176bool isDefined() const { return Defined; }177178bool isVariadic() const { return Variadic; }179180unsigned getBuiltinID() const { return F->getBuiltinID(); }181182bool isBuiltin() const { return F->getBuiltinID() != 0; }183184bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; }185186unsigned getNumParams() const { return ParamTypes.size(); }187188/// Returns the number of parameter this function takes when it's called,189/// i.e excluding the instance pointer and the RVO pointer.190unsigned getNumWrittenParams() const {191assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO()));192return getNumParams() - hasThisPointer() - hasRVO();193}194unsigned getWrittenArgSize() const {195return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO()));196}197198bool isThisPointerExplicit() const {199if (const auto *MD = dyn_cast<CXXMethodDecl>(F))200return MD->isExplicitObjectMemberFunction();201return false;202}203204unsigned getParamOffset(unsigned ParamIndex) const {205return ParamOffsets[ParamIndex];206}207208private:209/// Construct a function representing an actual function.210Function(Program &P, const FunctionDecl *F, unsigned ArgSize,211llvm::SmallVectorImpl<PrimType> &&ParamTypes,212llvm::DenseMap<unsigned, ParamDescriptor> &&Params,213llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,214bool HasRVO, bool UnevaluatedBuiltin);215216/// Sets the code of a function.217void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,218SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,219bool NewHasBody) {220FrameSize = NewFrameSize;221Code = std::move(NewCode);222SrcMap = std::move(NewSrcMap);223Scopes = std::move(NewScopes);224IsValid = true;225HasBody = NewHasBody;226}227228void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }229void setDefined(bool D) { Defined = D; }230231private:232friend class Program;233friend class ByteCodeEmitter;234235/// Program reference.236Program &P;237/// Location of the executed code.238SourceLocation Loc;239/// Declaration this function was compiled from.240const FunctionDecl *F;241/// Local area size: storage + metadata.242unsigned FrameSize = 0;243/// Size of the argument stack.244unsigned ArgSize;245/// Program code.246std::vector<std::byte> Code;247/// Opcode-to-expression mapping.248SourceMap SrcMap;249/// List of block descriptors.250llvm::SmallVector<Scope, 2> Scopes;251/// List of argument types.252llvm::SmallVector<PrimType, 8> ParamTypes;253/// Map from byte offset to parameter descriptor.254llvm::DenseMap<unsigned, ParamDescriptor> Params;255/// List of parameter offsets.256llvm::SmallVector<unsigned, 8> ParamOffsets;257/// Flag to indicate if the function is valid.258bool IsValid = false;259/// Flag to indicate if the function is done being260/// compiled to bytecode.261bool IsFullyCompiled = false;262/// Flag indicating if this function takes the this pointer263/// as the first implicit argument264bool HasThisPointer = false;265/// Whether this function has Return Value Optimization, i.e.266/// the return value is constructed in the caller's stack frame.267/// This is done for functions that return non-primive values.268bool HasRVO = false;269/// If we've already compiled the function's body.270bool HasBody = false;271bool Defined = false;272bool Variadic = false;273bool IsUnevaluatedBuiltin = false;274275public:276/// Dumps the disassembled bytecode to \c llvm::errs().277void dump() const;278void dump(llvm::raw_ostream &OS) const;279};280281} // namespace interp282} // namespace clang283284#endif285286287