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
23namespace clang {
24namespace interp {
25class Program;
26class ByteCodeEmitter;
27enum PrimType : uint32_t;
28
29/// Describes a scope block.
30///
31/// The block gathers all the descriptors of the locals defined in this block.
32class Scope {
33public:
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::iterator> locals() {
47    return llvm::make_range(Descriptors.begin(), Descriptors.end());
48  }
49
50private:
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.
59class Function {
60public:
61  using ParamDescriptor = std::pair<PrimType, Descriptor *>;
62
63  /// Returns the size of the function's local stack.
64  unsigned getFrameSize() const { return FrameSize; }
65  /// Returns the size of the argument stackx
66  unsigned getArgSize() const { return ArgSize; }
67
68  /// Returns a pointer to the start of the code.
69  CodePtr getCodeBegin() const;
70  /// Returns a pointer to the end of the code.
71  CodePtr getCodeEnd() const;
72
73  /// Returns the original FunctionDecl.
74  const FunctionDecl *getDecl() const { return F; }
75
76  /// Returns the lcoation.
77  SourceLocation getLoc() const { return Loc; }
78
79  /// Returns a parameter descriptor.
80  ParamDescriptor getParamDescriptor(unsigned Offset) const;
81
82  /// Checks if the first argument is a RVO pointer.
83  bool hasRVO() const { return ParamTypes.size() != Params.size(); }
84
85  /// Range over the scope blocks.
86  llvm::iterator_range<llvm::SmallVector<Scope, 2>::iterator> scopes() {
87    return llvm::make_range(Scopes.begin(), Scopes.end());
88  }
89
90  /// Range over argument types.
91  using arg_reverse_iterator = SmallVectorImpl<PrimType>::reverse_iterator;
92  llvm::iterator_range<arg_reverse_iterator> args_reverse() {
93    return llvm::make_range(ParamTypes.rbegin(), ParamTypes.rend());
94  }
95
96  /// Returns a specific scope.
97  Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
98
99  /// Returns the source information at a given PC.
100  SourceInfo getSource(CodePtr PC) const;
101
102  /// Checks if the function is valid to call in constexpr.
103  bool isConstexpr() const { return IsValid; }
104
105  /// Checks if the function is virtual.
106  bool isVirtual() const;
107
108  /// Checks if the function is a constructor.
109  bool isConstructor() const { return isa<CXXConstructorDecl>(F); }
110
111private:
112  /// Construct a function representing an actual function.
113  Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
114           llvm::SmallVector<PrimType, 8> &&ParamTypes,
115           llvm::DenseMap<unsigned, ParamDescriptor> &&Params);
116
117  /// Sets the code of a function.
118  void setCode(unsigned NewFrameSize, std::vector<char> &&NewCode, SourceMap &&NewSrcMap,
119               llvm::SmallVector<Scope, 2> &&NewScopes) {
120    FrameSize = NewFrameSize;
121    Code = std::move(NewCode);
122    SrcMap = std::move(NewSrcMap);
123    Scopes = std::move(NewScopes);
124    IsValid = true;
125  }
126
127private:
128  friend class Program;
129  friend class ByteCodeEmitter;
130
131  /// Program reference.
132  Program &P;
133  /// Location of the executed code.
134  SourceLocation Loc;
135  /// Declaration this function was compiled from.
136  const FunctionDecl *F;
137  /// Local area size: storage + metadata.
138  unsigned FrameSize;
139  /// Size of the argument stack.
140  unsigned ArgSize;
141  /// Program code.
142  std::vector<char> Code;
143  /// Opcode-to-expression mapping.
144  SourceMap SrcMap;
145  /// List of block descriptors.
146  llvm::SmallVector<Scope, 2> Scopes;
147  /// List of argument types.
148  llvm::SmallVector<PrimType, 8> ParamTypes;
149  /// Map from byte offset to parameter descriptor.
150  llvm::DenseMap<unsigned, ParamDescriptor> Params;
151  /// Flag to indicate if the function is valid.
152  bool IsValid = false;
153
154public:
155  /// Dumps the disassembled bytecode to \c llvm::errs().
156  void dump() const;
157  void dump(llvm::raw_ostream &OS) const;
158};
159
160} // namespace interp
161} // namespace clang
162
163#endif
164