[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
//===--- Disasm.cpp - Disassembler for bytecode functions -------*- 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Dump method for Function which disassembles the bytecode.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2024-03-13 08:09:07 +01:00
|
|
|
#include "Boolean.h"
|
2024-06-05 13:21:40 +02:00
|
|
|
#include "Context.h"
|
|
|
|
#include "EvaluationResult.h"
|
2024-09-27 11:32:43 +02:00
|
|
|
#include "FixedPoint.h"
|
2023-01-25 14:51:16 +01:00
|
|
|
#include "Floating.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "Function.h"
|
2024-03-13 08:09:07 +01:00
|
|
|
#include "FunctionPointer.h"
|
|
|
|
#include "Integral.h"
|
2024-01-31 10:00:42 +01:00
|
|
|
#include "IntegralAP.h"
|
2024-03-19 10:06:20 +01:00
|
|
|
#include "InterpFrame.h"
|
2024-06-06 11:17:48 +02:00
|
|
|
#include "MemberPointer.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "Opcode.h"
|
|
|
|
#include "PrimType.h"
|
|
|
|
#include "Program.h"
|
2024-02-23 09:09:45 +01:00
|
|
|
#include "clang/AST/ASTDumperUtils.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2024-06-27 15:11:26 +02:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2020-04-06 10:32:16 -07:00
|
|
|
#include "llvm/Support/Format.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::interp;
|
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
template <typename T>
|
|
|
|
inline static std::string printArg(Program &P, CodePtr &OpPC) {
|
2022-11-07 18:25:46 +00:00
|
|
|
if constexpr (std::is_pointer_v<T>) {
|
2022-09-23 12:40:44 +02:00
|
|
|
uint32_t ID = OpPC.read<uint32_t>();
|
2025-04-13 15:46:01 +02:00
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
SS << reinterpret_cast<T>(P.getNativePointer(ID));
|
|
|
|
return Result;
|
2022-09-23 12:40:44 +02:00
|
|
|
} else {
|
2025-04-13 15:46:01 +02:00
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
auto Arg = OpPC.read<T>();
|
|
|
|
SS << Arg;
|
|
|
|
return Result;
|
2022-09-23 12:40:44 +02:00
|
|
|
}
|
[Clang interpreter] Avoid storing pointers at unaligned locations
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
2021-07-28 14:49:37 +01:00
|
|
|
}
|
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
template <> inline std::string printArg<Floating>(Program &P, CodePtr &OpPC) {
|
|
|
|
auto F = Floating::deserialize(*OpPC);
|
2023-07-13 11:17:56 +02:00
|
|
|
OpPC += align(F.bytesToSerialize());
|
2025-04-13 15:46:01 +02:00
|
|
|
|
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
SS << F;
|
|
|
|
return Result;
|
2023-07-13 11:17:56 +02:00
|
|
|
}
|
|
|
|
|
2024-01-31 10:00:42 +01:00
|
|
|
template <>
|
2025-04-13 15:46:01 +02:00
|
|
|
inline std::string printArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
|
|
|
|
auto F = IntegralAP<false>::deserialize(*OpPC);
|
|
|
|
OpPC += align(F.bytesToSerialize());
|
2024-01-31 10:00:42 +01:00
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
SS << F;
|
|
|
|
return Result;
|
|
|
|
}
|
2024-01-31 10:00:42 +01:00
|
|
|
template <>
|
2025-04-13 15:46:01 +02:00
|
|
|
inline std::string printArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
|
|
|
|
auto F = IntegralAP<true>::deserialize(*OpPC);
|
|
|
|
OpPC += align(F.bytesToSerialize());
|
|
|
|
|
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
SS << F;
|
|
|
|
return Result;
|
2024-01-31 10:00:42 +01:00
|
|
|
}
|
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
template <> inline std::string printArg<FixedPoint>(Program &P, CodePtr &OpPC) {
|
|
|
|
auto F = FixedPoint::deserialize(*OpPC);
|
|
|
|
OpPC += align(F.bytesToSerialize());
|
|
|
|
|
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream SS(Result);
|
|
|
|
SS << F;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isJumpOpcode(Opcode Op) {
|
|
|
|
return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t getNumDisplayWidth(size_t N) {
|
|
|
|
unsigned L = 1u, M = 10u;
|
|
|
|
while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
|
|
|
|
M *= 10u;
|
|
|
|
|
|
|
|
return L;
|
2025-01-20 15:10:12 +01:00
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
|
2024-02-23 09:09:45 +01:00
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
|
|
|
|
OS << getName() << " " << (const void *)this << "\n";
|
|
|
|
}
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
OS << "frame size: " << getFrameSize() << "\n";
|
|
|
|
OS << "arg size: " << getArgSize() << "\n";
|
|
|
|
OS << "rvo: " << hasRVO() << "\n";
|
2022-09-18 20:40:27 +02:00
|
|
|
OS << "this arg: " << hasThisPointer() << "\n";
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
struct OpText {
|
|
|
|
size_t Addr;
|
|
|
|
std::string Op;
|
|
|
|
bool IsJump;
|
|
|
|
llvm::SmallVector<std::string> Args;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto PrintName = [](const char *Name) -> std::string {
|
|
|
|
return std::string(Name);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
};
|
|
|
|
|
2025-04-13 15:46:01 +02:00
|
|
|
llvm::SmallVector<OpText> Code;
|
|
|
|
size_t LongestAddr = 0;
|
|
|
|
size_t LongestOp = 0;
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
|
|
|
|
size_t Addr = PC - Start;
|
2025-04-13 15:46:01 +02:00
|
|
|
OpText Text;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
auto Op = PC.read<Opcode>();
|
2025-04-13 15:46:01 +02:00
|
|
|
Text.Addr = Addr;
|
|
|
|
Text.IsJump = isJumpOpcode(Op);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
switch (Op) {
|
|
|
|
#define GET_DISASM
|
|
|
|
#include "Opcodes.inc"
|
|
|
|
#undef GET_DISASM
|
|
|
|
}
|
2025-04-13 15:46:01 +02:00
|
|
|
Code.push_back(Text);
|
|
|
|
LongestOp = std::max(Text.Op.size(), LongestOp);
|
|
|
|
LongestAddr = std::max(getNumDisplayWidth(Addr), LongestAddr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Record jumps and their targets.
|
|
|
|
struct JmpData {
|
|
|
|
size_t From;
|
|
|
|
size_t To;
|
|
|
|
};
|
|
|
|
llvm::SmallVector<JmpData> Jumps;
|
|
|
|
for (auto &Text : Code) {
|
|
|
|
if (Text.IsJump)
|
|
|
|
Jumps.push_back({Text.Addr, Text.Addr + std::stoi(Text.Args[0]) +
|
|
|
|
align(sizeof(Opcode)) +
|
|
|
|
align(sizeof(int32_t))});
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::SmallVector<std::string> Text;
|
|
|
|
Text.reserve(Code.size());
|
|
|
|
size_t LongestLine = 0;
|
|
|
|
// Print code to a string, one at a time.
|
|
|
|
for (auto C : Code) {
|
|
|
|
std::string Line;
|
|
|
|
llvm::raw_string_ostream LS(Line);
|
|
|
|
LS << C.Addr;
|
|
|
|
LS.indent(LongestAddr - getNumDisplayWidth(C.Addr) + 4);
|
|
|
|
LS << C.Op;
|
|
|
|
LS.indent(LongestOp - C.Op.size() + 4);
|
|
|
|
for (auto &Arg : C.Args) {
|
|
|
|
LS << Arg << ' ';
|
|
|
|
}
|
|
|
|
Text.push_back(Line);
|
|
|
|
LongestLine = std::max(Line.size(), LongestLine);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2025-04-13 15:46:01 +02:00
|
|
|
|
|
|
|
assert(Code.size() == Text.size());
|
|
|
|
|
|
|
|
auto spaces = [](unsigned N) -> std::string {
|
|
|
|
std::string S;
|
|
|
|
for (unsigned I = 0; I != N; ++I)
|
|
|
|
S += ' ';
|
|
|
|
return S;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Now, draw the jump lines.
|
|
|
|
for (auto &J : Jumps) {
|
|
|
|
if (J.To > J.From) {
|
|
|
|
bool FoundStart = false;
|
|
|
|
for (size_t LineIndex = 0; LineIndex != Text.size(); ++LineIndex) {
|
|
|
|
Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
|
|
|
|
|
|
|
|
if (Code[LineIndex].Addr == J.From) {
|
|
|
|
Text[LineIndex] += " --+";
|
|
|
|
FoundStart = true;
|
|
|
|
} else if (Code[LineIndex].Addr == J.To) {
|
|
|
|
Text[LineIndex] += " <-+";
|
|
|
|
break;
|
|
|
|
} else if (FoundStart) {
|
|
|
|
Text[LineIndex] += " |";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LongestLine += 5;
|
|
|
|
} else {
|
|
|
|
bool FoundStart = false;
|
|
|
|
for (ssize_t LineIndex = Text.size() - 1; LineIndex >= 0; --LineIndex) {
|
|
|
|
Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
|
|
|
|
if (Code[LineIndex].Addr == J.From) {
|
|
|
|
Text[LineIndex] += " --+";
|
|
|
|
FoundStart = true;
|
|
|
|
} else if (Code[LineIndex].Addr == J.To) {
|
|
|
|
Text[LineIndex] += " <-+";
|
|
|
|
break;
|
|
|
|
} else if (FoundStart) {
|
|
|
|
Text[LineIndex] += " |";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LongestLine += 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &Line : Text)
|
|
|
|
OS << Line << '\n';
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
|
|
|
|
|
2024-03-13 08:09:07 +01:00
|
|
|
static const char *primTypeToString(PrimType T) {
|
|
|
|
switch (T) {
|
|
|
|
case PT_Sint8:
|
|
|
|
return "Sint8";
|
|
|
|
case PT_Uint8:
|
|
|
|
return "Uint8";
|
|
|
|
case PT_Sint16:
|
|
|
|
return "Sint16";
|
|
|
|
case PT_Uint16:
|
|
|
|
return "Uint16";
|
|
|
|
case PT_Sint32:
|
|
|
|
return "Sint32";
|
|
|
|
case PT_Uint32:
|
|
|
|
return "Uint32";
|
|
|
|
case PT_Sint64:
|
|
|
|
return "Sint64";
|
|
|
|
case PT_Uint64:
|
|
|
|
return "Uint64";
|
|
|
|
case PT_IntAP:
|
|
|
|
return "IntAP";
|
|
|
|
case PT_IntAPS:
|
|
|
|
return "IntAPS";
|
|
|
|
case PT_Bool:
|
|
|
|
return "Bool";
|
|
|
|
case PT_Float:
|
|
|
|
return "Float";
|
|
|
|
case PT_Ptr:
|
|
|
|
return "Ptr";
|
|
|
|
case PT_FnPtr:
|
|
|
|
return "FnPtr";
|
2024-06-06 11:17:48 +02:00
|
|
|
case PT_MemberPtr:
|
|
|
|
return "MemberPtr";
|
2024-09-27 11:32:43 +02:00
|
|
|
case PT_FixedPoint:
|
|
|
|
return "FixedPoint";
|
2024-03-13 08:09:07 +01:00
|
|
|
}
|
|
|
|
llvm_unreachable("Unhandled PrimType");
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
|
2024-02-23 09:09:45 +01:00
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
|
|
|
|
OS << "\n:: Program\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
|
|
|
|
OS << "Total memory : " << Allocator.getTotalMemory() << " bytes\n";
|
|
|
|
OS << "Global Variables: " << Globals.size() << "\n";
|
|
|
|
}
|
|
|
|
unsigned GI = 0;
|
|
|
|
for (const Global *G : Globals) {
|
|
|
|
const Descriptor *Desc = G->block()->getDescriptor();
|
2024-03-13 08:09:07 +01:00
|
|
|
Pointer GP = getPtrGlobal(GI);
|
|
|
|
|
2024-04-16 13:29:10 +02:00
|
|
|
OS << GI << ": " << (const void *)G->block() << " ";
|
2024-02-23 11:19:30 +01:00
|
|
|
{
|
|
|
|
ColorScope SC(OS, true,
|
|
|
|
GP.isInitialized()
|
|
|
|
? TerminalColor{llvm::raw_ostream::GREEN, false}
|
|
|
|
: TerminalColor{llvm::raw_ostream::RED, false});
|
|
|
|
OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
|
|
|
|
}
|
2024-02-23 09:09:45 +01:00
|
|
|
Desc->dump(OS);
|
2024-06-27 15:11:26 +02:00
|
|
|
|
2024-06-28 12:18:33 +02:00
|
|
|
if (GP.isInitialized() && Desc->IsTemporary) {
|
2024-06-27 15:11:26 +02:00
|
|
|
if (const auto *MTE =
|
|
|
|
dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());
|
|
|
|
MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
|
2024-06-28 12:18:33 +02:00
|
|
|
if (const APValue *V =
|
|
|
|
MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
|
|
|
|
OS << " (global temporary value: ";
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
|
|
|
|
std::string VStr;
|
|
|
|
llvm::raw_string_ostream SS(VStr);
|
|
|
|
V->dump(SS, Ctx.getASTContext());
|
|
|
|
|
|
|
|
for (unsigned I = 0; I != VStr.size(); ++I) {
|
|
|
|
if (VStr[I] == '\n')
|
|
|
|
VStr[I] = ' ';
|
|
|
|
}
|
|
|
|
VStr.pop_back(); // Remove the newline (or now space) at the end.
|
|
|
|
OS << VStr;
|
|
|
|
}
|
|
|
|
OS << ')';
|
|
|
|
}
|
2024-06-27 15:11:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-23 09:09:45 +01:00
|
|
|
OS << "\n";
|
2024-06-05 13:14:18 +02:00
|
|
|
if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
|
2024-03-13 08:09:07 +01:00
|
|
|
OS << " ";
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
|
|
|
|
OS << primTypeToString(Desc->getPrimType()) << " ";
|
|
|
|
}
|
|
|
|
TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });
|
|
|
|
OS << "\n";
|
|
|
|
}
|
2024-02-23 09:09:45 +01:00
|
|
|
++GI;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
|
|
|
|
OS << "Functions: " << Funcs.size() << "\n";
|
|
|
|
}
|
|
|
|
for (const auto &Func : Funcs) {
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
Func.second->dump();
|
|
|
|
}
|
2024-02-23 09:09:45 +01:00
|
|
|
for (const auto &Anon : AnonFuncs) {
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
Anon->dump();
|
|
|
|
}
|
|
|
|
}
|
2024-02-23 09:09:45 +01:00
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Descriptor::dump() const {
|
|
|
|
dump(llvm::errs());
|
|
|
|
llvm::errs() << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
|
|
|
|
// Source
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
|
|
|
|
if (const auto *ND = dyn_cast_if_present<NamedDecl>(asDecl()))
|
2024-03-17 14:49:08 +01:00
|
|
|
ND->printQualifiedName(OS);
|
2024-02-23 09:09:45 +01:00
|
|
|
else if (asExpr())
|
2024-06-27 15:40:34 +02:00
|
|
|
OS << "Expr " << (const void *)asExpr();
|
2024-02-23 09:09:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print a few interesting bits about the descriptor.
|
|
|
|
if (isPrimitiveArray())
|
|
|
|
OS << " primitive-array";
|
|
|
|
else if (isCompositeArray())
|
|
|
|
OS << " composite-array";
|
2024-08-10 09:09:12 +02:00
|
|
|
else if (isUnion())
|
|
|
|
OS << " union";
|
2024-02-23 09:09:45 +01:00
|
|
|
else if (isRecord())
|
|
|
|
OS << " record";
|
|
|
|
else if (isPrimitive())
|
2025-02-05 08:04:59 +01:00
|
|
|
OS << " primitive " << primTypeToString(getPrimType());
|
2024-02-23 09:09:45 +01:00
|
|
|
|
|
|
|
if (isZeroSizeArray())
|
2024-04-29 08:09:12 +02:00
|
|
|
OS << " zero-size-array";
|
2024-02-23 09:09:45 +01:00
|
|
|
else if (isUnknownSizeArray())
|
|
|
|
OS << " unknown-size-array";
|
|
|
|
|
|
|
|
if (isDummy())
|
|
|
|
OS << " dummy";
|
2025-04-16 09:00:52 +02:00
|
|
|
if (IsConstexprUnknown)
|
|
|
|
OS << " constexpr-unknown";
|
2024-02-23 09:09:45 +01:00
|
|
|
}
|
2024-03-19 10:06:20 +01:00
|
|
|
|
2025-02-16 12:15:43 +01:00
|
|
|
/// Dump descriptor, including all valid offsets.
|
|
|
|
LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset,
|
|
|
|
unsigned Indent) const {
|
|
|
|
unsigned Spaces = Indent * 2;
|
|
|
|
llvm::raw_ostream &OS = llvm::errs();
|
|
|
|
OS.indent(Spaces);
|
|
|
|
dump(OS);
|
|
|
|
OS << '\n';
|
|
|
|
OS.indent(Spaces) << "Metadata: " << getMetadataSize() << " bytes\n";
|
|
|
|
OS.indent(Spaces) << "Size: " << getSize() << " bytes\n";
|
|
|
|
OS.indent(Spaces) << "AllocSize: " << getAllocSize() << " bytes\n";
|
|
|
|
Offset += getMetadataSize();
|
|
|
|
if (isCompositeArray()) {
|
|
|
|
OS.indent(Spaces) << "Elements: " << getNumElems() << '\n';
|
|
|
|
unsigned FO = Offset;
|
|
|
|
for (unsigned I = 0; I != getNumElems(); ++I) {
|
|
|
|
FO += sizeof(InlineDescriptor);
|
|
|
|
assert(ElemDesc->getMetadataSize() == 0);
|
|
|
|
OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n';
|
|
|
|
ElemDesc->dumpFull(FO, Indent + 1);
|
|
|
|
|
|
|
|
FO += ElemDesc->getAllocSize();
|
|
|
|
}
|
|
|
|
} else if (isRecord()) {
|
|
|
|
ElemRecord->dump(OS, Indent + 1, Offset);
|
|
|
|
} else if (isPrimitive()) {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << '\n';
|
|
|
|
}
|
|
|
|
|
2024-04-25 07:45:16 +02:00
|
|
|
LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
|
|
|
|
OS << "InlineDescriptor " << (const void *)this << "\n";
|
|
|
|
}
|
|
|
|
OS << "Offset: " << Offset << "\n";
|
|
|
|
OS << "IsConst: " << IsConst << "\n";
|
|
|
|
OS << "IsInitialized: " << IsInitialized << "\n";
|
|
|
|
OS << "IsBase: " << IsBase << "\n";
|
|
|
|
OS << "IsActive: " << IsActive << "\n";
|
2024-08-10 09:09:12 +02:00
|
|
|
OS << "InUnion: " << InUnion << "\n";
|
2024-04-25 07:45:16 +02:00
|
|
|
OS << "IsFieldMutable: " << IsFieldMutable << "\n";
|
|
|
|
OS << "Desc: ";
|
|
|
|
if (Desc)
|
|
|
|
Desc->dump(OS);
|
|
|
|
else
|
|
|
|
OS << "nullptr";
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
|
2024-03-19 10:06:20 +01:00
|
|
|
LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
|
|
|
|
unsigned Indent) const {
|
|
|
|
unsigned Spaces = Indent * 2;
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
|
|
|
|
OS.indent(Spaces);
|
|
|
|
if (getCallee())
|
|
|
|
describe(OS);
|
|
|
|
else
|
|
|
|
OS << "Frame (Depth: " << getDepth() << ")";
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
OS.indent(Spaces) << "Function: " << getFunction();
|
|
|
|
if (const Function *F = getFunction()) {
|
|
|
|
OS << " (" << F->getName() << ")";
|
|
|
|
}
|
|
|
|
OS << "\n";
|
|
|
|
OS.indent(Spaces) << "This: " << getThis() << "\n";
|
|
|
|
OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";
|
2024-07-26 11:20:31 +02:00
|
|
|
OS.indent(Spaces) << "Depth: " << Depth << "\n";
|
|
|
|
OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";
|
|
|
|
OS.indent(Spaces) << "Args: " << (void *)Args << "\n";
|
|
|
|
OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";
|
|
|
|
OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)
|
|
|
|
<< "\n";
|
2024-03-19 10:06:20 +01:00
|
|
|
|
2024-07-26 11:20:31 +02:00
|
|
|
for (const InterpFrame *F = this->Caller; F; F = F->Caller) {
|
2024-03-19 10:06:20 +01:00
|
|
|
F->dump(OS, Indent + 1);
|
|
|
|
}
|
|
|
|
}
|
2024-04-05 16:56:35 +02:00
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
|
|
|
|
unsigned Offset) const {
|
|
|
|
unsigned Indent = Indentation * 2;
|
|
|
|
OS.indent(Indent);
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
|
|
|
|
OS << getName() << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned I = 0;
|
|
|
|
for (const Record::Base &B : bases()) {
|
|
|
|
OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
|
|
|
|
<< "\n";
|
|
|
|
B.R->dump(OS, Indentation + 1, Offset + B.Offset);
|
|
|
|
++I;
|
|
|
|
}
|
|
|
|
|
|
|
|
I = 0;
|
|
|
|
for (const Record::Field &F : fields()) {
|
|
|
|
OS.indent(Indent) << "- Field " << I << ": ";
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
|
|
|
|
OS << F.Decl->getName();
|
|
|
|
}
|
|
|
|
OS << ". Offset " << (Offset + F.Offset) << "\n";
|
|
|
|
++I;
|
|
|
|
}
|
2024-04-25 07:46:17 +02:00
|
|
|
|
|
|
|
I = 0;
|
|
|
|
for (const Record::Base &B : virtual_bases()) {
|
|
|
|
OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
|
|
|
|
<< (Offset + B.Offset) << "\n";
|
|
|
|
B.R->dump(OS, Indentation + 1, Offset + B.Offset);
|
|
|
|
++I;
|
|
|
|
}
|
2024-04-05 16:56:35 +02:00
|
|
|
}
|
2024-04-13 06:10:38 +02:00
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
|
|
|
|
{
|
|
|
|
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
|
2024-07-09 08:27:50 +02:00
|
|
|
OS << "Block " << (const void *)this;
|
2024-04-13 06:10:38 +02:00
|
|
|
}
|
2024-07-09 08:27:50 +02:00
|
|
|
OS << " (";
|
|
|
|
Desc->dump(OS);
|
|
|
|
OS << ")\n";
|
2024-04-13 06:10:38 +02:00
|
|
|
unsigned NPointers = 0;
|
|
|
|
for (const Pointer *P = Pointers; P; P = P->Next) {
|
|
|
|
++NPointers;
|
|
|
|
}
|
2025-03-26 12:25:14 +01:00
|
|
|
OS << " EvalID: " << EvalID << '\n';
|
|
|
|
OS << " DeclID: ";
|
|
|
|
if (DeclID)
|
|
|
|
OS << *DeclID << '\n';
|
|
|
|
else
|
|
|
|
OS << "-\n";
|
2024-04-13 06:10:38 +02:00
|
|
|
OS << " Pointers: " << NPointers << "\n";
|
|
|
|
OS << " Dead: " << IsDead << "\n";
|
|
|
|
OS << " Static: " << IsStatic << "\n";
|
|
|
|
OS << " Extern: " << IsExtern << "\n";
|
|
|
|
OS << " Initialized: " << IsInitialized << "\n";
|
2025-03-26 12:25:14 +01:00
|
|
|
OS << " Weak: " << IsWeak << "\n";
|
|
|
|
OS << " Dynamic: " << IsDynamic << "\n";
|
2024-04-13 06:10:38 +02:00
|
|
|
}
|
2024-06-05 13:21:40 +02:00
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void EvaluationResult::dump() const {
|
|
|
|
assert(Ctx);
|
|
|
|
auto &OS = llvm::errs();
|
|
|
|
const ASTContext &ASTCtx = Ctx->getASTContext();
|
|
|
|
|
|
|
|
switch (Kind) {
|
|
|
|
case Empty:
|
|
|
|
OS << "Empty\n";
|
|
|
|
break;
|
|
|
|
case RValue:
|
|
|
|
OS << "RValue: ";
|
|
|
|
std::get<APValue>(Value).dump(OS, ASTCtx);
|
|
|
|
break;
|
|
|
|
case LValue: {
|
|
|
|
assert(Source);
|
|
|
|
QualType SourceType;
|
2025-01-14 15:25:08 -08:00
|
|
|
if (const auto *D = dyn_cast<const Decl *>(Source)) {
|
2024-06-05 13:21:40 +02:00
|
|
|
if (const auto *VD = dyn_cast<ValueDecl>(D))
|
|
|
|
SourceType = VD->getType();
|
2025-01-14 15:25:08 -08:00
|
|
|
} else if (const auto *E = dyn_cast<const Expr *>(Source)) {
|
2024-06-05 13:21:40 +02:00
|
|
|
SourceType = E->getType();
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << "LValue: ";
|
|
|
|
if (const auto *P = std::get_if<Pointer>(&Value))
|
2024-07-20 15:25:00 +02:00
|
|
|
P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
|
2024-06-05 13:21:40 +02:00
|
|
|
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
|
2024-07-20 15:25:00 +02:00
|
|
|
FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
|
2024-06-05 13:21:40 +02:00
|
|
|
OS << "\n";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Invalid:
|
|
|
|
OS << "Invalid\n";
|
|
|
|
break;
|
|
|
|
case Valid:
|
|
|
|
OS << "Valid\n";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|