1 //===--- Function.h - Bytecode function for the VM --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Defines the Function class which holds all bytecode function-specific data. 10 // 11 // The scope class which describes local variables is also defined here. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H 16 #define LLVM_CLANG_AST_INTERP_FUNCTION_H 17 18 #include "Pointer.h" 19 #include "Source.h" 20 #include "clang/AST/Decl.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 namespace clang { 24 namespace interp { 25 class Program; 26 class ByteCodeEmitter; 27 enum PrimType : uint32_t; 28 29 /// Describes a scope block. 30 /// 31 /// The block gathers all the descriptors of the locals defined in this block. 32 class Scope final { 33 public: 34 /// Information about a local's storage. 35 struct Local { 36 /// Offset of the local in frame. 37 unsigned Offset; 38 /// Descriptor of the local. 39 Descriptor *Desc; 40 }; 41 42 using LocalVectorTy = llvm::SmallVector<Local, 8>; 43 44 Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {} 45 46 llvm::iterator_range<LocalVectorTy::const_iterator> locals() const { 47 return llvm::make_range(Descriptors.begin(), Descriptors.end()); 48 } 49 50 private: 51 /// Object descriptors in this block. 52 LocalVectorTy Descriptors; 53 }; 54 55 /// Bytecode function. 56 /// 57 /// Contains links to the bytecode of the function, as well as metadata 58 /// describing all arguments and stack-local variables. 59 /// 60 /// # Calling Convention 61 /// 62 /// When calling a function, all argument values must be on the stack. 63 /// 64 /// If the function has a This pointer (i.e. hasThisPointer() returns true, 65 /// the argument values need to be preceeded by a Pointer for the This object. 66 /// 67 /// If the function uses Return Value Optimization, the arguments (and 68 /// potentially the This pointer) need to be proceeded by a Pointer pointing 69 /// to the location to construct the returned value. 70 /// 71 /// After the function has been called, it will remove all arguments, 72 /// including RVO and This pointer, from the stack. 73 /// 74 class Function final { 75 public: 76 using ParamDescriptor = std::pair<PrimType, Descriptor *>; 77 78 /// Returns the size of the function's local stack. 79 unsigned getFrameSize() const { return FrameSize; } 80 /// Returns the size of the argument stack. 81 unsigned getArgSize() const { return ArgSize; } 82 83 /// Returns a pointer to the start of the code. 84 CodePtr getCodeBegin() const { return Code.data(); } 85 /// Returns a pointer to the end of the code. 86 CodePtr getCodeEnd() const { return Code.data() + Code.size(); } 87 88 /// Returns the original FunctionDecl. 89 const FunctionDecl *getDecl() const { return F; } 90 91 /// Returns the name of the function decl this code 92 /// was generated for. 93 const std::string getName() const { 94 if (!F) 95 return "<<expr>>"; 96 97 return F->getQualifiedNameAsString(); 98 } 99 100 /// Returns the location. 101 SourceLocation getLoc() const { return Loc; } 102 103 /// Returns a parameter descriptor. 104 ParamDescriptor getParamDescriptor(unsigned Offset) const; 105 106 /// Checks if the first argument is a RVO pointer. 107 bool hasRVO() const { return HasRVO; } 108 109 /// Range over the scope blocks. 110 llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator> 111 scopes() const { 112 return llvm::make_range(Scopes.begin(), Scopes.end()); 113 } 114 115 /// Range over argument types. 116 using arg_reverse_iterator = 117 SmallVectorImpl<PrimType>::const_reverse_iterator; 118 llvm::iterator_range<arg_reverse_iterator> args_reverse() const { 119 return llvm::reverse(ParamTypes); 120 } 121 122 /// Returns a specific scope. 123 Scope &getScope(unsigned Idx) { return Scopes[Idx]; } 124 const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; } 125 126 /// Returns the source information at a given PC. 127 SourceInfo getSource(CodePtr PC) const; 128 129 /// Checks if the function is valid to call in constexpr. 130 bool isConstexpr() const { return IsValid; } 131 132 /// Checks if the function is virtual. 133 bool isVirtual() const; 134 135 /// Checks if the function is a constructor. 136 bool isConstructor() const { return isa<CXXConstructorDecl>(F); } 137 /// Checks if the function is a destructor. 138 bool isDestructor() const { return isa<CXXDestructorDecl>(F); } 139 140 /// Returns the parent record decl, if any. 141 const CXXRecordDecl *getParentDecl() const { 142 if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) 143 return MD->getParent(); 144 return nullptr; 145 } 146 147 /// Checks if the function is fully done compiling. 148 bool isFullyCompiled() const { return IsFullyCompiled; } 149 150 bool hasThisPointer() const { return HasThisPointer; } 151 152 /// Checks if the function already has a body attached. 153 bool hasBody() const { return HasBody; } 154 155 unsigned getBuiltinID() const { return F->getBuiltinID(); } 156 157 unsigned getNumParams() const { return ParamTypes.size(); } 158 159 unsigned getParamOffset(unsigned ParamIndex) const { 160 return ParamOffsets[ParamIndex]; 161 } 162 163 private: 164 /// Construct a function representing an actual function. 165 Function(Program &P, const FunctionDecl *F, unsigned ArgSize, 166 llvm::SmallVectorImpl<PrimType> &&ParamTypes, 167 llvm::DenseMap<unsigned, ParamDescriptor> &&Params, 168 llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer, 169 bool HasRVO); 170 171 /// Sets the code of a function. 172 void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, 173 SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes, 174 bool NewHasBody) { 175 FrameSize = NewFrameSize; 176 Code = std::move(NewCode); 177 SrcMap = std::move(NewSrcMap); 178 Scopes = std::move(NewScopes); 179 IsValid = true; 180 HasBody = NewHasBody; 181 } 182 183 void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; } 184 185 private: 186 friend class Program; 187 friend class ByteCodeEmitter; 188 189 /// Program reference. 190 Program &P; 191 /// Location of the executed code. 192 SourceLocation Loc; 193 /// Declaration this function was compiled from. 194 const FunctionDecl *F; 195 /// Local area size: storage + metadata. 196 unsigned FrameSize = 0; 197 /// Size of the argument stack. 198 unsigned ArgSize; 199 /// Program code. 200 std::vector<std::byte> Code; 201 /// Opcode-to-expression mapping. 202 SourceMap SrcMap; 203 /// List of block descriptors. 204 llvm::SmallVector<Scope, 2> Scopes; 205 /// List of argument types. 206 llvm::SmallVector<PrimType, 8> ParamTypes; 207 /// Map from byte offset to parameter descriptor. 208 llvm::DenseMap<unsigned, ParamDescriptor> Params; 209 /// List of parameter offsets. 210 llvm::SmallVector<unsigned, 8> ParamOffsets; 211 /// Flag to indicate if the function is valid. 212 bool IsValid = false; 213 /// Flag to indicate if the function is done being 214 /// compiled to bytecode. 215 bool IsFullyCompiled = false; 216 /// Flag indicating if this function takes the this pointer 217 /// as the first implicit argument 218 bool HasThisPointer = false; 219 /// Whether this function has Return Value Optimization, i.e. 220 /// the return value is constructed in the caller's stack frame. 221 /// This is done for functions that return non-primive values. 222 bool HasRVO = false; 223 /// If we've already compiled the function's body. 224 bool HasBody = false; 225 226 public: 227 /// Dumps the disassembled bytecode to \c llvm::errs(). 228 void dump() const; 229 void dump(llvm::raw_ostream &OS) const; 230 }; 231 232 } // namespace interp 233 } // namespace clang 234 235 #endif 236