1353942Sdim//===--- Source.h - Source location provider for the VM  --------*- C++ -*-===//
2353942Sdim//
3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353942Sdim// See https://llvm.org/LICENSE.txt for license information.
5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353942Sdim//
7353942Sdim//===----------------------------------------------------------------------===//
8353942Sdim//
9353942Sdim// Defines a program which organises and links multiple bytecode functions.
10353942Sdim//
11353942Sdim//===----------------------------------------------------------------------===//
12353942Sdim
13353942Sdim#ifndef LLVM_CLANG_AST_INTERP_SOURCE_H
14353942Sdim#define LLVM_CLANG_AST_INTERP_SOURCE_H
15353942Sdim
16353942Sdim#include "clang/AST/Decl.h"
17353942Sdim#include "clang/AST/Stmt.h"
18353942Sdim#include "llvm/Support/Endian.h"
19353942Sdim
20353942Sdimnamespace clang {
21353942Sdimnamespace interp {
22353942Sdimclass Function;
23353942Sdim
24353942Sdim/// Pointer into the code segment.
25353942Sdimclass CodePtr {
26353942Sdimpublic:
27353942Sdim  CodePtr() : Ptr(nullptr) {}
28353942Sdim
29353942Sdim  CodePtr &operator+=(int32_t Offset) {
30353942Sdim    Ptr += Offset;
31353942Sdim    return *this;
32353942Sdim  }
33353942Sdim
34353942Sdim  int32_t operator-(const CodePtr &RHS) const {
35353942Sdim    assert(Ptr != nullptr && RHS.Ptr != nullptr && "Invalid code pointer");
36353942Sdim    return Ptr - RHS.Ptr;
37353942Sdim  }
38353942Sdim
39353942Sdim  CodePtr operator-(size_t RHS) const {
40353942Sdim    assert(Ptr != nullptr && "Invalid code pointer");
41353942Sdim    return CodePtr(Ptr - RHS);
42353942Sdim  }
43353942Sdim
44353942Sdim  bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; }
45353942Sdim
46353942Sdim  /// Reads data and advances the pointer.
47353942Sdim  template <typename T> T read() {
48353942Sdim    T Value = ReadHelper<T>(Ptr);
49353942Sdim    Ptr += sizeof(T);
50353942Sdim    return Value;
51353942Sdim  }
52353942Sdim
53353942Sdimprivate:
54353942Sdim  /// Constructor used by Function to generate pointers.
55353942Sdim  CodePtr(const char *Ptr) : Ptr(Ptr) {}
56353942Sdim
57353942Sdim  /// Helper to decode a value or a pointer.
58353942Sdim  template <typename T>
59353942Sdim  static typename std::enable_if<!std::is_pointer<T>::value, T>::type
60353942Sdim  ReadHelper(const char *Ptr) {
61353942Sdim    using namespace llvm::support;
62353942Sdim    return endian::read<T, endianness::native, 1>(Ptr);
63353942Sdim  }
64353942Sdim
65353942Sdim  template <typename T>
66353942Sdim  static typename std::enable_if<std::is_pointer<T>::value, T>::type
67353942Sdim  ReadHelper(const char *Ptr) {
68353942Sdim    using namespace llvm::support;
69353942Sdim    auto Punned = endian::read<uintptr_t, endianness::native, 1>(Ptr);
70353942Sdim    return reinterpret_cast<T>(Punned);
71353942Sdim  }
72353942Sdim
73353942Sdimprivate:
74353942Sdim  friend class Function;
75353942Sdim
76353942Sdim  /// Pointer into the code owned by a function.
77353942Sdim  const char *Ptr;
78353942Sdim};
79353942Sdim
80353942Sdim/// Describes the statement/declaration an opcode was generated from.
81353942Sdimclass SourceInfo {
82353942Sdimpublic:
83353942Sdim  SourceInfo() {}
84353942Sdim  SourceInfo(const Stmt *E) : Source(E) {}
85353942Sdim  SourceInfo(const Decl *D) : Source(D) {}
86353942Sdim
87353942Sdim  SourceLocation getLoc() const;
88353942Sdim
89353942Sdim  const Stmt *asStmt() const { return Source.dyn_cast<const Stmt *>(); }
90353942Sdim  const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
91353942Sdim  const Expr *asExpr() const;
92353942Sdim
93353942Sdim  operator bool() const { return !Source.isNull(); }
94353942Sdim
95353942Sdimprivate:
96353942Sdim  llvm::PointerUnion<const Decl *, const Stmt *> Source;
97353942Sdim};
98353942Sdim
99353942Sdimusing SourceMap = std::vector<std::pair<unsigned, SourceInfo>>;
100353942Sdim
101353942Sdim/// Interface for classes which map locations to sources.
102353942Sdimclass SourceMapper {
103353942Sdimpublic:
104353942Sdim  virtual ~SourceMapper() {}
105353942Sdim
106353942Sdim  /// Returns source information for a given PC in a function.
107353942Sdim  virtual SourceInfo getSource(Function *F, CodePtr PC) const = 0;
108353942Sdim
109353942Sdim  /// Returns the expression if an opcode belongs to one, null otherwise.
110353942Sdim  const Expr *getExpr(Function *F, CodePtr PC) const;
111353942Sdim  /// Returns the location from which an opcode originates.
112353942Sdim  SourceLocation getLocation(Function *F, CodePtr PC) const;
113353942Sdim};
114353942Sdim
115353942Sdim} // namespace interp
116353942Sdim} // namespace clang
117353942Sdim
118353942Sdim#endif
119