From 312346de6be3de1889ea93c18ecb5d1339d3ca37 Mon Sep 17 00:00:00 2001 From: Stefan Weigl-Bosker Date: Sun, 11 Jan 2026 21:31:52 -0500 Subject: [willow]: Diagnostics and plumbing --- BUILD | 9 ---- BUILD.bazel | 9 ++++ willow/include/willow/IR/Context.h | 18 +++++++ willow/include/willow/IR/Diagnostic.h | 30 +++++++++++ willow/include/willow/IR/DiagnosticEngine.h | 83 +++++++++++++++++++++++++++++ willow/include/willow/IR/Instruction.h | 3 ++ willow/include/willow/Util/LogicalResult.h | 14 +++++ willow/lib/IR/Instruction.cpp | 1 + 8 files changed, 158 insertions(+), 9 deletions(-) delete mode 100644 BUILD create mode 100644 BUILD.bazel create mode 100644 willow/include/willow/IR/Context.h create mode 100644 willow/include/willow/IR/Diagnostic.h create mode 100644 willow/include/willow/IR/DiagnosticEngine.h create mode 100644 willow/include/willow/Util/LogicalResult.h create mode 100644 willow/lib/IR/Instruction.cpp diff --git a/BUILD b/BUILD deleted file mode 100644 index 6cbf83c..0000000 --- a/BUILD +++ /dev/null @@ -1,9 +0,0 @@ -load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") - -refresh_compile_commands( - name = "refresh_compile_commands", - - targets = { - "//willow:willow": "", - }, -) diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..6cbf83c --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,9 @@ +load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") + +refresh_compile_commands( + name = "refresh_compile_commands", + + targets = { + "//willow:willow": "", + }, +) diff --git a/willow/include/willow/IR/Context.h b/willow/include/willow/IR/Context.h new file mode 100644 index 0000000..3468e8f --- /dev/null +++ b/willow/include/willow/IR/Context.h @@ -0,0 +1,18 @@ +#ifndef WILLOW_INCLUDE_CONTEXT_H +#define WILLOW_INCLUDE_CONTEXT_H + +#include +#include + +namespace willow { + +/// The global context. Contains all shared state. +class WillowContext { + TypeContext ctx; + + std::vector> modules; +}; + +} // namespace willow + +#endif // WILLOW_INCLUDE_CONTEXT_H diff --git a/willow/include/willow/IR/Diagnostic.h b/willow/include/willow/IR/Diagnostic.h new file mode 100644 index 0000000..2a74898 --- /dev/null +++ b/willow/include/willow/IR/Diagnostic.h @@ -0,0 +1,30 @@ +#ifndef WILLOW_INCLUDE_IR_DIAGNOSTIC_H +#define WILLOW_INCLUDE_IR_DIAGNOSTIC_H + +#include + +#include +#include + +namespace willow { + +enum class Severity { Debug, Remark, Warning, Error }; + +struct Location { + std::string filename; + int line; + int col; +}; + +struct Diagnostic { + Severity severity; + std::string message; + std::optional location; + /// Extra lines that will be printed after the diagnostic. Call sites, extra + /// info, etc + std::vector notes; +}; + +} // namespace willow + +#endif // WILLOW_INCLUDE_SUPPORT_DIAGNOSTICS_H diff --git a/willow/include/willow/IR/DiagnosticEngine.h b/willow/include/willow/IR/DiagnosticEngine.h new file mode 100644 index 0000000..2293734 --- /dev/null +++ b/willow/include/willow/IR/DiagnosticEngine.h @@ -0,0 +1,83 @@ +#ifndef WILLOW_INCLUDE_IR_DIAGNOSTIC_ENGINE_H +#define WILLOW_INCLUDE_IR_DIAGNOSTIC_ENGINE_H + +/// \file DiagnosticEngine.h Portable diagnostic handling + +#include +#include + +#include + +namespace willow { + +class DiagnosticEngine { +public: + using Handler = std::function; + + DiagnosticEngine() = default; + explicit DiagnosticEngine(Handler h) : handler(std::move(h)) {} + + void setHandler(Handler h) { handler = std::move(h); } + + void report(Diagnostic d) { // NOLINT(performance-unnecessary-value-param) + if (handler) + handler(d); + } + +private: + Handler handler; +}; + +/// Helper class for building, propagating and reporting a Diagnostic. +class DiagnosticBuilder { + DiagnosticEngine *engine = nullptr; + Diagnostic diag; + std::ostringstream os; + +public: + DiagnosticBuilder(const DiagnosticBuilder &) = delete; + DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; + + DiagnosticBuilder(DiagnosticEngine &eng, Severity severity, + std::optional loc) + : engine(&eng) { + diag.severity = severity; + diag.location = std::move(loc); + } + + DiagnosticBuilder(DiagnosticBuilder &&other) noexcept + : engine(std::exchange(other.engine, nullptr)), + diag(std::move(other.diag)), os(std::move(other.os)) {} + + ~DiagnosticBuilder() { + if (!engine) // was moved from + return; + + diag.message += os.str(); + engine->report(std::move(diag)); + } + + template + DiagnosticBuilder &operator<<(T &&x) { + os << std::forward(x); + } + + /// Add a note to the diagnostic. Will be printed on its own line, following + /// the diagnostic itself. + DiagnosticBuilder ¬e(std::string n) { + diag.notes.push_back(std::move(n)); + return *this; + } + + operator LogicalResult() const { return LogicalResult::Failure; } +}; + +/// DiagnosticBuilder factory. +inline DiagnosticBuilder emit(DiagnosticEngine &eng, Severity severity, + std::optional loc = std::nullopt) { + return DiagnosticBuilder(eng, severity, std::move(loc)); +} + +} // namespace willow + +#endif // WILLOW_INCLUDE_IR_DIAGNOSTIC_ENGINE_H diff --git a/willow/include/willow/IR/Instruction.h b/willow/include/willow/IR/Instruction.h index a4dfbbb..f1bd0e6 100644 --- a/willow/include/willow/IR/Instruction.h +++ b/willow/include/willow/IR/Instruction.h @@ -80,6 +80,8 @@ public: operand->delUse(this); } + virtual bool verify(std::ostream &os) = 0; + bool hasParent() const { return parent != nullptr; } BasicBlock *getParent() { return parent; } const BasicBlock *getParent() const { return parent; } @@ -107,6 +109,7 @@ public: } }; +/// The base class for unary arithemetic instructions class UnaryInst : public Instruction { public: UnaryInst(std::string name, Type type, Op op, Value *value) diff --git a/willow/include/willow/Util/LogicalResult.h b/willow/include/willow/Util/LogicalResult.h new file mode 100644 index 0000000..3a345eb --- /dev/null +++ b/willow/include/willow/Util/LogicalResult.h @@ -0,0 +1,14 @@ +#ifndef WILLOW_INCLUDE_LOGICAL_RESULT_H +#define WILLOW_INCLUDE_LOGICAL_RESULT_H + +#include + +namespace willow { + +enum class LogicalResult : uint8_t { Success, Failure }; +inline bool succeeded(LogicalResult r) { return r == LogicalResult::Success; } +inline bool failed(LogicalResult r) { return r == LogicalResult::Failure; } + +} // namespace willow + +#endif // WILLOW_INCLUDE_LOGICAL_RESULT_H diff --git a/willow/lib/IR/Instruction.cpp b/willow/lib/IR/Instruction.cpp new file mode 100644 index 0000000..21a4cae --- /dev/null +++ b/willow/lib/IR/Instruction.cpp @@ -0,0 +1 @@ +#include -- cgit v1.2.3