1//===--- Source.h - Source location provider 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 a program which organises and links multiple bytecode functions.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_SOURCE_H
14#define LLVM_CLANG_AST_INTERP_SOURCE_H
15
16#include "PrimType.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/Stmt.h"
19#include "llvm/Support/Endian.h"
20
21namespace clang {
22namespace interp {
23class Function;
24
25/// Pointer into the code segment.
26class CodePtr final {
27public:
28  CodePtr() : Ptr(nullptr) {}
29
30  CodePtr &operator+=(int32_t Offset) {
31    Ptr += Offset;
32    return *this;
33  }
34
35  int32_t operator-(const CodePtr &RHS) const {
36    assert(Ptr != nullptr && RHS.Ptr != nullptr && "Invalid code pointer");
37    return Ptr - RHS.Ptr;
38  }
39
40  CodePtr operator-(size_t RHS) const {
41    assert(Ptr != nullptr && "Invalid code pointer");
42    return CodePtr(Ptr - RHS);
43  }
44
45  bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; }
46
47  operator bool() const { return Ptr; }
48
49  /// Reads data and advances the pointer.
50  template <typename T> std::enable_if_t<!std::is_pointer<T>::value, T> read() {
51    assert(aligned(Ptr));
52    using namespace llvm::support;
53    T Value = endian::read<T, endianness::native, 1>(Ptr);
54    Ptr += align(sizeof(T));
55    return Value;
56  }
57
58private:
59  /// Constructor used by Function to generate pointers.
60  CodePtr(const char *Ptr) : Ptr(Ptr) {}
61
62private:
63  friend class Function;
64
65  /// Pointer into the code owned by a function.
66  const char *Ptr;
67};
68
69/// Describes the statement/declaration an opcode was generated from.
70class SourceInfo final {
71public:
72  SourceInfo() {}
73  SourceInfo(const Stmt *E) : Source(E) {}
74  SourceInfo(const Decl *D) : Source(D) {}
75
76  SourceLocation getLoc() const;
77
78  const Stmt *asStmt() const { return Source.dyn_cast<const Stmt *>(); }
79  const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
80  const Expr *asExpr() const;
81
82  operator bool() const { return !Source.isNull(); }
83
84private:
85  llvm::PointerUnion<const Decl *, const Stmt *> Source;
86};
87
88using SourceMap = std::vector<std::pair<unsigned, SourceInfo>>;
89
90/// Interface for classes which map locations to sources.
91class SourceMapper {
92public:
93  virtual ~SourceMapper() {}
94
95  /// Returns source information for a given PC in a function.
96  virtual SourceInfo getSource(const Function *F, CodePtr PC) const = 0;
97
98  /// Returns the expression if an opcode belongs to one, null otherwise.
99  const Expr *getExpr(const Function *F, CodePtr PC) const;
100  /// Returns the location from which an opcode originates.
101  SourceLocation getLocation(const Function *F, CodePtr PC) const;
102};
103
104} // namespace interp
105} // namespace clang
106
107#endif
108