| 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 | #include "Function.h" |
| 10 | #include "Program.h" |
| 11 | #include "clang/AST/Decl.h" |
| 12 | #include "clang/AST/DeclCXX.h" |
| 13 | |
| 14 | using namespace clang; |
| 15 | using namespace clang::interp; |
| 16 | |
| 17 | Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize, |
| 18 | llvm::SmallVectorImpl<PrimType> &&ParamTypes, |
| 19 | llvm::DenseMap<unsigned, ParamDescriptor> &&Params, |
| 20 | llvm::SmallVectorImpl<unsigned> &&ParamOffsets, |
| 21 | bool HasThisPointer, bool HasRVO, bool IsLambdaStaticInvoker) |
| 22 | : P(P), Kind(FunctionKind::Normal), Source(Source), ArgSize(ArgSize), |
| 23 | ParamTypes(std::move(ParamTypes)), Params(std::move(Params)), |
| 24 | ParamOffsets(std::move(ParamOffsets)), IsValid(false), |
| 25 | IsFullyCompiled(false), HasThisPointer(HasThisPointer), HasRVO(HasRVO), |
| 26 | HasBody(false), Defined(false) { |
| 27 | if (const auto *F = dyn_cast<const FunctionDecl *>(Val&: Source)) { |
| 28 | Variadic = F->isVariadic(); |
| 29 | Immediate = F->isImmediateFunction(); |
| 30 | Constexpr = F->isConstexpr() || F->hasAttr<MSConstexprAttr>(); |
| 31 | if (const auto *CD = dyn_cast<CXXConstructorDecl>(Val: F)) { |
| 32 | Virtual = CD->isVirtual(); |
| 33 | Kind = FunctionKind::Ctor; |
| 34 | } else if (const auto *CD = dyn_cast<CXXDestructorDecl>(Val: F)) { |
| 35 | Virtual = CD->isVirtual(); |
| 36 | Kind = FunctionKind::Dtor; |
| 37 | } else if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: F)) { |
| 38 | Virtual = MD->isVirtual(); |
| 39 | if (IsLambdaStaticInvoker) |
| 40 | Kind = FunctionKind::LambdaStaticInvoker; |
| 41 | else if (clang::isLambdaCallOperator(DC: F)) |
| 42 | Kind = FunctionKind::LambdaCallOperator; |
| 43 | else if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) |
| 44 | Kind = FunctionKind::CopyOrMoveOperator; |
| 45 | } else { |
| 46 | Virtual = false; |
| 47 | } |
| 48 | } else { |
| 49 | Variadic = false; |
| 50 | Virtual = false; |
| 51 | Immediate = false; |
| 52 | Constexpr = false; |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { |
| 57 | auto It = Params.find(Val: Offset); |
| 58 | assert(It != Params.end() && "Invalid parameter offset" ); |
| 59 | return It->second; |
| 60 | } |
| 61 | |
| 62 | SourceInfo Function::getSource(CodePtr PC) const { |
| 63 | assert(PC >= getCodeBegin() && "PC does not belong to this function" ); |
| 64 | assert(PC <= getCodeEnd() && "PC Does not belong to this function" ); |
| 65 | assert(hasBody() && "Function has no body" ); |
| 66 | unsigned Offset = PC - getCodeBegin(); |
| 67 | using Elem = std::pair<unsigned, SourceInfo>; |
| 68 | auto It = llvm::lower_bound(Range: SrcMap, Value: Elem{Offset, {}}, C: llvm::less_first()); |
| 69 | if (It == SrcMap.end()) |
| 70 | return SrcMap.back().second; |
| 71 | return It->second; |
| 72 | } |
| 73 | |