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 "Source.h" 19 #include "Descriptor.h" 20 #include "clang/AST/ASTLambda.h" 21 #include "clang/AST/Decl.h" 22 #include "llvm/Support/raw_ostream.h" 23 24 namespace clang { 25 namespace interp { 26 class Program; 27 class ByteCodeEmitter; 28 class Pointer; 29 enum PrimType : uint32_t; 30 31 /// Describes a scope block. 32 /// 33 /// The block gathers all the descriptors of the locals defined in this block. 34 class Scope final { 35 public: 36 /// Information about a local's storage. 37 struct Local { 38 /// Offset of the local in frame. 39 unsigned Offset; 40 /// Descriptor of the local. 41 Descriptor *Desc; 42 }; 43 44 using LocalVectorTy = llvm::SmallVector<Local, 8>; 45 46 Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {} 47 48 llvm::iterator_range<LocalVectorTy::const_iterator> locals() const { 49 return llvm::make_range(Descriptors.begin(), Descriptors.end()); 50 } 51 52 private: 53 /// Object descriptors in this block. 54 LocalVectorTy Descriptors; 55 }; 56 57 /// Bytecode function. 58 /// 59 /// Contains links to the bytecode of the function, as well as metadata 60 /// describing all arguments and stack-local variables. 61 /// 62 /// # Calling Convention 63 /// 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 (and 70 /// potentially the This pointer) need to be preceeded by a Pointer pointing 71 /// 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 /// 76 class Function final { 77 public: 78 using ParamDescriptor = std::pair<PrimType, Descriptor *>; 79 80 /// Returns the size of the function's local stack. 81 unsigned getFrameSize() const { return FrameSize; } 82 /// Returns the size of the argument stack. 83 unsigned getArgSize() const { return ArgSize; } 84 85 /// Returns a pointer to the start of the code. 86 CodePtr getCodeBegin() const { return Code.data(); } 87 /// Returns a pointer to the end of the code. 88 CodePtr getCodeEnd() const { return Code.data() + Code.size(); } 89 90 /// Returns the original FunctionDecl. 91 const FunctionDecl *getDecl() const { return F; } 92 93 /// Returns the name of the function decl this code 94 /// was generated for. 95 const std::string getName() const { 96 if (!F) 97 return "<<expr>>"; 98 99 return F->getQualifiedNameAsString(); 100 } 101 102 /// Returns the location. 103 SourceLocation getLoc() const { return Loc; } 104 105 /// Returns a parameter descriptor. 106 ParamDescriptor getParamDescriptor(unsigned Offset) const; 107 108 /// Checks if the first argument is a RVO pointer. 109 bool hasRVO() const { return HasRVO; } 110 111 /// Range over the scope blocks. 112 llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator> 113 scopes() const { 114 return llvm::make_range(Scopes.begin(), Scopes.end()); 115 } 116 117 /// Range over argument types. 118 using arg_reverse_iterator = 119 SmallVectorImpl<PrimType>::const_reverse_iterator; 120 llvm::iterator_range<arg_reverse_iterator> args_reverse() const { 121 return llvm::reverse(ParamTypes); 122 } 123 124 /// Returns a specific scope. 125 Scope &getScope(unsigned Idx) { return Scopes[Idx]; } 126 const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; } 127 128 /// Returns the source information at a given PC. 129 SourceInfo getSource(CodePtr PC) const; 130 131 /// Checks if the function is valid to call in constexpr. 132 bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); } 133 134 /// Checks if the function is virtual. 135 bool isVirtual() const; 136 137 /// Checks if the function is a constructor. 138 bool isConstructor() const { return isa<CXXConstructorDecl>(F); } 139 /// Checks if the function is a destructor. 140 bool isDestructor() const { return isa<CXXDestructorDecl>(F); } 141 142 /// Returns the parent record decl, if any. 143 const CXXRecordDecl *getParentDecl() const { 144 if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) 145 return MD->getParent(); 146 return nullptr; 147 } 148 149 /// Returns whether this function is a lambda static invoker, 150 /// which we generate custom byte code for. 151 bool isLambdaStaticInvoker() const { 152 if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) 153 return MD->isLambdaStaticInvoker(); 154 return false; 155 } 156 157 /// Returns whether this function is the call operator 158 /// of a lambda record decl. 159 bool isLambdaCallOperator() const { 160 if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) 161 return clang::isLambdaCallOperator(MD); 162 return false; 163 } 164 165 /// Checks if the function is fully done compiling. 166 bool isFullyCompiled() const { return IsFullyCompiled; } 167 168 bool hasThisPointer() const { return HasThisPointer; } 169 170 /// Checks if the function already has a body attached. 171 bool hasBody() const { return HasBody; } 172 173 /// Checks if the function is defined. 174 bool isDefined() const { return Defined; } 175 176 bool isVariadic() const { return Variadic; } 177 178 unsigned getBuiltinID() const { return F->getBuiltinID(); } 179 180 bool isBuiltin() const { return F->getBuiltinID() != 0; } 181 182 bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; } 183 184 unsigned getNumParams() const { return ParamTypes.size(); } 185 186 unsigned getParamOffset(unsigned ParamIndex) const { 187 return ParamOffsets[ParamIndex]; 188 } 189 190 private: 191 /// Construct a function representing an actual function. 192 Function(Program &P, const FunctionDecl *F, unsigned ArgSize, 193 llvm::SmallVectorImpl<PrimType> &&ParamTypes, 194 llvm::DenseMap<unsigned, ParamDescriptor> &&Params, 195 llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer, 196 bool HasRVO, bool UnevaluatedBuiltin); 197 198 /// Sets the code of a function. 199 void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, 200 SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes, 201 bool NewHasBody) { 202 FrameSize = NewFrameSize; 203 Code = std::move(NewCode); 204 SrcMap = std::move(NewSrcMap); 205 Scopes = std::move(NewScopes); 206 IsValid = true; 207 HasBody = NewHasBody; 208 } 209 210 void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; } 211 void setDefined(bool D) { Defined = D; } 212 213 private: 214 friend class Program; 215 friend class ByteCodeEmitter; 216 217 /// Program reference. 218 Program &P; 219 /// Location of the executed code. 220 SourceLocation Loc; 221 /// Declaration this function was compiled from. 222 const FunctionDecl *F; 223 /// Local area size: storage + metadata. 224 unsigned FrameSize = 0; 225 /// Size of the argument stack. 226 unsigned ArgSize; 227 /// Program code. 228 std::vector<std::byte> Code; 229 /// Opcode-to-expression mapping. 230 SourceMap SrcMap; 231 /// List of block descriptors. 232 llvm::SmallVector<Scope, 2> Scopes; 233 /// List of argument types. 234 llvm::SmallVector<PrimType, 8> ParamTypes; 235 /// Map from byte offset to parameter descriptor. 236 llvm::DenseMap<unsigned, ParamDescriptor> Params; 237 /// List of parameter offsets. 238 llvm::SmallVector<unsigned, 8> ParamOffsets; 239 /// Flag to indicate if the function is valid. 240 bool IsValid = false; 241 /// Flag to indicate if the function is done being 242 /// compiled to bytecode. 243 bool IsFullyCompiled = false; 244 /// Flag indicating if this function takes the this pointer 245 /// as the first implicit argument 246 bool HasThisPointer = false; 247 /// Whether this function has Return Value Optimization, i.e. 248 /// the return value is constructed in the caller's stack frame. 249 /// This is done for functions that return non-primive values. 250 bool HasRVO = false; 251 /// If we've already compiled the function's body. 252 bool HasBody = false; 253 bool Defined = false; 254 bool Variadic = false; 255 bool IsUnevaluatedBuiltin = false; 256 257 public: 258 /// Dumps the disassembled bytecode to \c llvm::errs(). 259 void dump() const; 260 void dump(llvm::raw_ostream &OS) const; 261 }; 262 263 } // namespace interp 264 } // namespace clang 265 266 #endif 267