xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/Source.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1a7dea167SDimitry Andric //===--- Source.h - Source location provider for the VM  --------*- C++ -*-===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric //
9a7dea167SDimitry Andric // Defines a program which organises and links multiple bytecode functions.
10a7dea167SDimitry Andric //
11a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
12a7dea167SDimitry Andric 
13a7dea167SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_SOURCE_H
14a7dea167SDimitry Andric #define LLVM_CLANG_AST_INTERP_SOURCE_H
15a7dea167SDimitry Andric 
16bdd1243dSDimitry Andric #include "PrimType.h"
17*5f757f3fSDimitry Andric #include "clang/AST/DeclBase.h"
18a7dea167SDimitry Andric #include "clang/AST/Stmt.h"
19*5f757f3fSDimitry Andric #include "llvm/ADT/PointerUnion.h"
20a7dea167SDimitry Andric #include "llvm/Support/Endian.h"
21a7dea167SDimitry Andric 
22a7dea167SDimitry Andric namespace clang {
23*5f757f3fSDimitry Andric class Expr;
24*5f757f3fSDimitry Andric class SourceLocation;
25*5f757f3fSDimitry Andric class SourceRange;
26a7dea167SDimitry Andric namespace interp {
27a7dea167SDimitry Andric class Function;
28a7dea167SDimitry Andric 
29a7dea167SDimitry Andric /// Pointer into the code segment.
30bdd1243dSDimitry Andric class CodePtr final {
31a7dea167SDimitry Andric public:
32a7dea167SDimitry Andric   CodePtr() : Ptr(nullptr) {}
33a7dea167SDimitry Andric 
34a7dea167SDimitry Andric   CodePtr &operator+=(int32_t Offset) {
35a7dea167SDimitry Andric     Ptr += Offset;
36a7dea167SDimitry Andric     return *this;
37a7dea167SDimitry Andric   }
38a7dea167SDimitry Andric 
39a7dea167SDimitry Andric   int32_t operator-(const CodePtr &RHS) const {
40a7dea167SDimitry Andric     assert(Ptr != nullptr && RHS.Ptr != nullptr && "Invalid code pointer");
41a7dea167SDimitry Andric     return Ptr - RHS.Ptr;
42a7dea167SDimitry Andric   }
43a7dea167SDimitry Andric 
44a7dea167SDimitry Andric   CodePtr operator-(size_t RHS) const {
45a7dea167SDimitry Andric     assert(Ptr != nullptr && "Invalid code pointer");
46a7dea167SDimitry Andric     return CodePtr(Ptr - RHS);
47a7dea167SDimitry Andric   }
48a7dea167SDimitry Andric 
49a7dea167SDimitry Andric   bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; }
50*5f757f3fSDimitry Andric   const std::byte *operator*() const { return Ptr; }
51a7dea167SDimitry Andric 
52bdd1243dSDimitry Andric   operator bool() const { return Ptr; }
53bdd1243dSDimitry Andric 
54a7dea167SDimitry Andric   /// Reads data and advances the pointer.
55349cc55cSDimitry Andric   template <typename T> std::enable_if_t<!std::is_pointer<T>::value, T> read() {
56bdd1243dSDimitry Andric     assert(aligned(Ptr));
57349cc55cSDimitry Andric     using namespace llvm::support;
58*5f757f3fSDimitry Andric     T Value = endian::read<T, llvm::endianness::native>(Ptr);
59bdd1243dSDimitry Andric     Ptr += align(sizeof(T));
60a7dea167SDimitry Andric     return Value;
61a7dea167SDimitry Andric   }
62a7dea167SDimitry Andric 
63a7dea167SDimitry Andric private:
64a7dea167SDimitry Andric   friend class Function;
6506c3fb27SDimitry Andric   /// Constructor used by Function to generate pointers.
6606c3fb27SDimitry Andric   CodePtr(const std::byte *Ptr) : Ptr(Ptr) {}
67a7dea167SDimitry Andric   /// Pointer into the code owned by a function.
6806c3fb27SDimitry Andric   const std::byte *Ptr;
69a7dea167SDimitry Andric };
70a7dea167SDimitry Andric 
71a7dea167SDimitry Andric /// Describes the statement/declaration an opcode was generated from.
72bdd1243dSDimitry Andric class SourceInfo final {
73a7dea167SDimitry Andric public:
74a7dea167SDimitry Andric   SourceInfo() {}
75a7dea167SDimitry Andric   SourceInfo(const Stmt *E) : Source(E) {}
76a7dea167SDimitry Andric   SourceInfo(const Decl *D) : Source(D) {}
77a7dea167SDimitry Andric 
78a7dea167SDimitry Andric   SourceLocation getLoc() const;
79*5f757f3fSDimitry Andric   SourceRange getRange() const;
80a7dea167SDimitry Andric 
81a7dea167SDimitry Andric   const Stmt *asStmt() const { return Source.dyn_cast<const Stmt *>(); }
82a7dea167SDimitry Andric   const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
83a7dea167SDimitry Andric   const Expr *asExpr() const;
84a7dea167SDimitry Andric 
85a7dea167SDimitry Andric   operator bool() const { return !Source.isNull(); }
86a7dea167SDimitry Andric 
87a7dea167SDimitry Andric private:
88a7dea167SDimitry Andric   llvm::PointerUnion<const Decl *, const Stmt *> Source;
89a7dea167SDimitry Andric };
90a7dea167SDimitry Andric 
91a7dea167SDimitry Andric using SourceMap = std::vector<std::pair<unsigned, SourceInfo>>;
92a7dea167SDimitry Andric 
93a7dea167SDimitry Andric /// Interface for classes which map locations to sources.
94a7dea167SDimitry Andric class SourceMapper {
95a7dea167SDimitry Andric public:
96a7dea167SDimitry Andric   virtual ~SourceMapper() {}
97a7dea167SDimitry Andric 
98a7dea167SDimitry Andric   /// Returns source information for a given PC in a function.
99bdd1243dSDimitry Andric   virtual SourceInfo getSource(const Function *F, CodePtr PC) const = 0;
100a7dea167SDimitry Andric 
101a7dea167SDimitry Andric   /// Returns the expression if an opcode belongs to one, null otherwise.
102bdd1243dSDimitry Andric   const Expr *getExpr(const Function *F, CodePtr PC) const;
103a7dea167SDimitry Andric   /// Returns the location from which an opcode originates.
104bdd1243dSDimitry Andric   SourceLocation getLocation(const Function *F, CodePtr PC) const;
105*5f757f3fSDimitry Andric   SourceRange getRange(const Function *F, CodePtr PC) const;
106a7dea167SDimitry Andric };
107a7dea167SDimitry Andric 
108a7dea167SDimitry Andric } // namespace interp
109a7dea167SDimitry Andric } // namespace clang
110a7dea167SDimitry Andric 
111a7dea167SDimitry Andric #endif
112