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