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