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 | |