The Clang interpreter's bytecode uses a packed stream of bytes representation, but also wants to have some opcodes take pointers as arguments, which are currently embedded in the bytecode directly. However, CHERI, and thus Arm's upcoming experimental Morello prototype, provide spatial memory safety for C/C++ by implementing language-level (and sub-language-level) pointers as capabilities, which track bounds, permissions and validity in hardware. This uses tagged memory with a single tag bit at every capability-aligned address, and so storing pointers to unaligned addresses results in the tag being stripped, leading to a tag fault when the pointer is ultimately dereferenced at a later point. In order to support a stricter C/C++ implementation like CHERI, we no longer store pointers directly in the bytecode, instead storing them in a table and embedding the index in the bytecode. Reviewed By: nand Differential Revision: https://reviews.llvm.org/D97606
104 lines
2.8 KiB
C++
104 lines
2.8 KiB
C++
//===--- Source.h - Source location provider for the VM --------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines a program which organises and links multiple bytecode functions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_AST_INTERP_SOURCE_H
|
|
#define LLVM_CLANG_AST_INTERP_SOURCE_H
|
|
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/Stmt.h"
|
|
#include "llvm/Support/Endian.h"
|
|
|
|
namespace clang {
|
|
namespace interp {
|
|
class Function;
|
|
|
|
/// Pointer into the code segment.
|
|
class CodePtr {
|
|
public:
|
|
CodePtr() : Ptr(nullptr) {}
|
|
|
|
CodePtr &operator+=(int32_t Offset) {
|
|
Ptr += Offset;
|
|
return *this;
|
|
}
|
|
|
|
int32_t operator-(const CodePtr &RHS) const {
|
|
assert(Ptr != nullptr && RHS.Ptr != nullptr && "Invalid code pointer");
|
|
return Ptr - RHS.Ptr;
|
|
}
|
|
|
|
CodePtr operator-(size_t RHS) const {
|
|
assert(Ptr != nullptr && "Invalid code pointer");
|
|
return CodePtr(Ptr - RHS);
|
|
}
|
|
|
|
bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; }
|
|
|
|
/// Reads data and advances the pointer.
|
|
template <typename T> std::enable_if_t<!std::is_pointer<T>::value, T> read() {
|
|
using namespace llvm::support;
|
|
T Value = endian::read<T, endianness::native, 1>(Ptr);
|
|
Ptr += sizeof(T);
|
|
return Value;
|
|
}
|
|
|
|
private:
|
|
/// Constructor used by Function to generate pointers.
|
|
CodePtr(const char *Ptr) : Ptr(Ptr) {}
|
|
|
|
private:
|
|
friend class Function;
|
|
|
|
/// Pointer into the code owned by a function.
|
|
const char *Ptr;
|
|
};
|
|
|
|
/// Describes the statement/declaration an opcode was generated from.
|
|
class SourceInfo {
|
|
public:
|
|
SourceInfo() {}
|
|
SourceInfo(const Stmt *E) : Source(E) {}
|
|
SourceInfo(const Decl *D) : Source(D) {}
|
|
|
|
SourceLocation getLoc() const;
|
|
|
|
const Stmt *asStmt() const { return Source.dyn_cast<const Stmt *>(); }
|
|
const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
|
|
const Expr *asExpr() const;
|
|
|
|
operator bool() const { return !Source.isNull(); }
|
|
|
|
private:
|
|
llvm::PointerUnion<const Decl *, const Stmt *> Source;
|
|
};
|
|
|
|
using SourceMap = std::vector<std::pair<unsigned, SourceInfo>>;
|
|
|
|
/// Interface for classes which map locations to sources.
|
|
class SourceMapper {
|
|
public:
|
|
virtual ~SourceMapper() {}
|
|
|
|
/// Returns source information for a given PC in a function.
|
|
virtual SourceInfo getSource(Function *F, CodePtr PC) const = 0;
|
|
|
|
/// Returns the expression if an opcode belongs to one, null otherwise.
|
|
const Expr *getExpr(Function *F, CodePtr PC) const;
|
|
/// Returns the location from which an opcode originates.
|
|
SourceLocation getLocation(Function *F, CodePtr PC) const;
|
|
};
|
|
|
|
} // namespace interp
|
|
} // namespace clang
|
|
|
|
#endif
|