From 54916602614c5ea44f686346a33e5c069a7f1af5 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Sun, 12 Sep 2021 14:01:02 +0100 Subject: [PATCH] Add our own dianostic engine --- bin/serene.cpp | 3 +- docs/examples/hello_world.srn | 4 + include/serene/context.h | 25 +- include/serene/diagnostics.h | 93 ++++++ include/serene/errors/constants.h | 27 +- include/serene/reader/location.h | 41 ++- include/serene/reader/reader.h | 16 +- include/serene/source_mgr.h | 154 +++++---- resources/dockr/Dockerfile.llvm | 36 ++ src/serene/CMakeLists.txt | 2 + src/serene/context.cpp | 7 +- src/serene/diagnostics.cpp | 147 ++++++++ src/serene/reader/location.cpp | 29 +- src/serene/reader/reader.cpp | 121 ++++--- src/serene/source_mgr.cpp | 536 ++++++++++++++++-------------- 15 files changed, 824 insertions(+), 417 deletions(-) create mode 100644 include/serene/diagnostics.h create mode 100644 resources/dockr/Dockerfile.llvm create mode 100644 src/serene/diagnostics.cpp diff --git a/bin/serene.cpp b/bin/serene.cpp index b9af5fe..19c8365 100644 --- a/bin/serene.cpp +++ b/bin/serene.cpp @@ -28,6 +28,7 @@ #include "serene/context.h" #include "serene/jit.h" #include "serene/namespace.h" +#include "serene/reader/location.h" #include "serene/reader/reader.h" #include "serene/reader/semantics.h" #include "serene/slir/generatable.h" @@ -238,7 +239,7 @@ int main(int argc, char *argv[]) { applyPassManagerCLOptions(ctx->pm); ctx->sourceManager.setLoadPaths(loadPaths); - auto runLoc = llvm::SMLoc(); + auto runLoc = reader::LocationRange::UnknownLocation(inputNS); auto ns = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc, true); if (!ns) { diff --git a/docs/examples/hello_world.srn b/docs/examples/hello_world.srn index 15136f2..a8db664 100644 --- a/docs/examples/hello_world.srn +++ b/docs/examples/hello_world.srn @@ -1,4 +1,8 @@ (def main (fn () 3)) (def main1 (fn (v y n) 3)) ht + + + + (- 3 4 (sh - r e 3bea -32) ((((()))))) \ No newline at end of file diff --git a/include/serene/context.h b/include/serene/context.h index a9d7cb5..da9c7af 100644 --- a/include/serene/context.h +++ b/include/serene/context.h @@ -25,15 +25,14 @@ #ifndef SERENE_CONTEXT_H #define SERENE_CONTEXT_H +#include "serene/diagnostics.h" #include "serene/environment.h" #include "serene/namespace.h" #include "serene/passes.h" #include "serene/slir/dialect.h" #include "serene/source_mgr.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/SMLoc.h" - +#include #include #include #include @@ -44,6 +43,10 @@ namespace serene { +namespace reader { +class LocationRange; +} + namespace exprs { class Expression; using Node = std::shared_ptr; @@ -61,6 +64,13 @@ enum class CompilationPhase { }; class SereneContext { + struct Options { + /// Whether to use colors for the output or not + bool withColors = true; + + Options() = default; + }; + public: // -------------------------------------------------------------------------- // IMPORTANT: @@ -73,12 +83,15 @@ public: mlir::PassManager pm; - mlir::DiagnosticEngine &diagEngine; + std::unique_ptr diagEngine; /// The source manager is responsible for loading namespaces and practically /// managing the source code in form of memory buffers. SourceMgr sourceManager; + /// The set of options to change the compilers behaivoirs + Options opts; + std::string targetTriple; /// Insert the given `ns` into the context. The Context object is @@ -99,7 +112,7 @@ public: std::shared_ptr getNS(llvm::StringRef ns_name); SereneContext() - : pm(&mlirContext), diagEngine(mlirContext.getDiagEngine()), + : pm(&mlirContext), diagEngine(makeDiagnosticEngine(*this)), targetPhase(CompilationPhase::NoOptimization) { mlirContext.getOrLoadDialect(); mlirContext.getOrLoadDialect(); @@ -118,7 +131,7 @@ public: int getOptimizatioLevel(); NSPtr readNamespace(std::string name); - NSPtr readNamespace(std::string name, llvm::SMLoc loc); + NSPtr readNamespace(std::string name, reader::LocationRange loc); private: CompilationPhase targetPhase; diff --git a/include/serene/diagnostics.h b/include/serene/diagnostics.h new file mode 100644 index 0000000..443ed82 --- /dev/null +++ b/include/serene/diagnostics.h @@ -0,0 +1,93 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SERENE_DIAGNOSTICS_H +#define SERENE_DIAGNOSTICS_H + +#include "serene/errors/constants.h" +#include "serene/reader/location.h" +#include "serene/source_mgr.h" + +#include +#include +#include +#include + +namespace serene { +class SereneContext; +class DiagnosticEngine; + +class Diagnostic { + // TODO: Add support for llvm::SMFixIt + friend DiagnosticEngine; + + enum Type { + Error, + + // TODO: Add support for remarks and notes + Remark, + Note, + }; + + SereneContext &ctx; + reader::LocationRange loc; + std::string fn; + errors::ErrorVariant *err = nullptr; + Type type = Type::Error; + std::string message, lineContents; + + std::string getPrefix(llvm::StringRef prefix = ""); + +public: + Diagnostic(SereneContext &ctx, reader::LocationRange loc, + errors::ErrorVariant *e, llvm::StringRef msg, + llvm::StringRef fn = "") + : ctx(ctx), loc(loc), fn(fn), err(e), message(msg){}; + +protected: + void print(llvm::raw_ostream &os, llvm::StringRef prefix = ""); + void writeColorByType(llvm::raw_ostream &os, llvm::StringRef str); +}; + +class DiagnosticEngine { + SereneContext &ctx; + + mlir::DiagnosticEngine &diagEngine; + + Diagnostic toDiagnostic(reader::LocationRange loc, errors::ErrorVariant &e, + llvm::StringRef msg, llvm::StringRef fn = ""); + + void print(llvm::raw_ostream &os, Diagnostic &d); + +public: + DiagnosticEngine(SereneContext &ctx); + + void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e, + llvm::StringRef msg = ""); +}; + +std::unique_ptr makeDiagnosticEngine(SereneContext &ctx); +} // namespace serene + +#endif diff --git a/include/serene/errors/constants.h b/include/serene/errors/constants.h index d8052da..e00ca19 100644 --- a/include/serene/errors/constants.h +++ b/include/serene/errors/constants.h @@ -40,10 +40,17 @@ enum ErrID { E0005, E0006, E0007, + E0008, + E0009, + E0010, + E0011, + E0012, + E0013, }; struct ErrorVariant { ErrID id; + std::string description; std::string longDescription; @@ -73,12 +80,30 @@ static ErrorVariant ""); static ErrorVariant PassFailureError(E0007, "Pass Failure.", ""); +static ErrorVariant NSLoadError(E0008, "Faild to find a namespace.", ""); +static ErrorVariant + NSAddToSMError(E0009, "Faild to add the namespace to the source manager.", + ""); + +static ErrorVariant + EOFWhileScaningAList(E0010, "EOF reached before closing of list", ""); + +static ErrorVariant InvalidDigitForNumber(E0011, "Invalid digit for a number.", + ""); + +static ErrorVariant + TwoFloatPoints(E0012, "Two or more float point characters in a number", ""); +static ErrorVariant InvalidCharacterForSymbol( + E0013, "Two or more float point characters in a number", ""); static std::map ErrDesc = { {E0000, &UnknownError}, {E0001, &DefExpectSymbol}, {E0002, &DefWrongNumberOfArgs}, {E0003, &FnNoArgsList}, {E0004, &FnArgsMustBeList}, {E0005, &CantResolveSymbol}, - {E0006, &DontKnowHowToCallNode}, {E0007, &PassFailureError}}; + {E0006, &DontKnowHowToCallNode}, {E0007, &PassFailureError}, + {E0008, &NSLoadError}, {E0009, &NSAddToSMError}, + {E0010, &EOFWhileScaningAList}, {E0011, &InvalidDigitForNumber}, + {E0012, &TwoFloatPoints}, {E0013, &InvalidCharacterForSymbol}}; } // namespace errors } // namespace serene diff --git a/include/serene/reader/location.h b/include/serene/reader/location.h index 4725354..334e0c0 100644 --- a/include/serene/reader/location.h +++ b/include/serene/reader/location.h @@ -22,8 +22,8 @@ * SOFTWARE. */ -#ifndef LOCATION_H -#define LOCATION_H +#ifndef SERENE_LOCATION_H +#define SERENE_LOCATION_H #include "mlir/IR/Diagnostics.h" @@ -37,21 +37,40 @@ namespace reader { /// It represents a location in the input string to the parser via `line`, struct Location { + /// Since namespaces are our unit of compilation, we need to have + /// a namespace in hand llvm::StringRef ns; + + llvm::Optional filename = llvm::None; /// A pointer to the character that this location is pointing to /// it the input buffer const char *c = nullptr; /// At this stage we only support 65535 lines of code in each file - unsigned short int line; + unsigned short int line = 0; /// At this stage we only support 65535 chars in each line - unsigned short int col; + unsigned short int col = 0; + + bool knownLocation = true; ::std::string toString() const; - Location() = default; - Location clone(); - mlir::Location toMLIRLocation(SereneContext &ctx, llvm::StringRef ns); + Location() = default; + Location(llvm::StringRef ns, + llvm::Optional fname = llvm::None, + const char *c = nullptr, unsigned short int line = 0, + unsigned short int col = 0, bool knownLocation = true) + : ns(ns), filename(fname), c(c), line(line), col(col){}; + + Location clone(); + Location clone() const; + + mlir::Location toMLIRLocation(SereneContext &ctx); + + /// Returns an unknown location for the given \p ns. + static Location UnknownLocation(llvm::StringRef ns) { + return Location(ns, llvm::None, nullptr, 0, 0, false); + } }; class LocationRange { @@ -62,7 +81,13 @@ public: LocationRange() = default; LocationRange(Location _start) : start(_start), end(_start){}; LocationRange(Location _start, Location _end) : start(_start), end(_end){}; - LocationRange(const LocationRange &); + // LocationRange(const LocationRange &); + + bool isKnownLocation() { return start.knownLocation; }; + + static LocationRange UnknownLocation(llvm::StringRef ns) { + return LocationRange(Location::UnknownLocation(ns)); + } }; void incLocation(Location &, const char *); diff --git a/include/serene/reader/reader.h b/include/serene/reader/reader.h index ef6d580..a43ad87 100644 --- a/include/serene/reader/reader.h +++ b/include/serene/reader/reader.h @@ -58,22 +58,30 @@ private: llvm::StringRef ns; llvm::Optional filename; - const char *current_char = NULL; + const char *currentChar = NULL; llvm::StringRef buf; /// The position tracker that we will use to determine the end of the /// buffer since the buffer might not be null terminated - size_t current_pos = -1; + size_t currentPos = -1; - Location current_location; + Location currentLocation; + + /// When we're dealing with the end of line we need to know what is the col + /// number for that EOL + unsigned prevCol = 0; + + bool readEOL = false; /// Returns a clone of the current location Location getCurrentLocation(); /// Returns the next character from the stream. /// @param skip_whitespace An indicator to whether skip white space like chars /// or not - const char *getChar(bool skip_whitespace); + const char *getChar(bool skipWhitespace); + + const char *nextChar(); /// Unreads the current character by moving the char pointer to the previous /// char. diff --git a/include/serene/source_mgr.h b/include/serene/source_mgr.h index 55d4f64..d5f5c70 100644 --- a/include/serene/source_mgr.h +++ b/include/serene/source_mgr.h @@ -26,13 +26,15 @@ #define SERENE_SOURCE_MGR_H #include "serene/namespace.h" +#include "serene/reader/location.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MemoryBuffer.h" - +#include +#include +#include #include #include +#include +#include #define SMGR_LOG(...) \ DEBUG_WITH_TYPE("sourcemgr", llvm::dbgs() \ @@ -89,7 +91,7 @@ private: const char *getPointerForLineNumberSpecialized(unsigned lineNo) const; /// This is the location of the parent include, or null if at the top level. - llvm::SMLoc includeLoc; + reader::LocationRange includeLoc; SrcBuffer() = default; SrcBuffer(SrcBuffer &&); @@ -153,101 +155,97 @@ public: return 1; } - llvm::SMLoc getParentIncludeLoc(unsigned i) const { - assert(isValidBufferID(i)); - return buffers[i - 1].includeLoc; - } + // reader::LocationRange getParentIncludeLoc(unsigned i) const { + // assert(isValidBufferID(i)); + // return buffers[i - 1].includeLoc; + // } /// Add a new source buffer to this source manager. This takes ownership of /// the memory buffer. unsigned AddNewSourceBuffer(std::unique_ptr f, - llvm::SMLoc includeLoc) { - SrcBuffer nb; - nb.buffer = std::move(f); - nb.includeLoc = includeLoc; - buffers.push_back(std::move(nb)); - return buffers.size(); - } - + reader::LocationRange includeLoc); /// Search for a file with the specified name in the current directory or in /// one of the IncludeDirs. /// /// If no file is found, this returns 0, otherwise it returns the buffer ID /// of the stacked file. The full path to the included file can be found in /// \p IncludedFile. - unsigned AddIncludeFile(const std::string &filename, llvm::SMLoc includeLoc, - std::string &includedFile); + // unsigned AddIncludeFile(const std::string &filename, llvm::SMLoc + // includeLoc, + // std::string &includedFile); NSPtr readNamespace(SereneContext &ctx, std::string name, - llvm::SMLoc importLoc, bool entryNS = false); + reader::LocationRange importLoc, bool entryNS = false); - /// Return the ID of the buffer containing the specified location. - /// - /// 0 is returned if the buffer is not found. - unsigned FindBufferContainingLoc(llvm::SMLoc loc) const; + // /// Return the ID of the buffer containing the specified location. + // /// + // /// 0 is returned if the buffer is not found. + // unsigned FindBufferContainingLoc(llvm::SMLoc loc) const; - /// Find the line number for the specified location in the specified file. - /// This is not a fast method. - unsigned FindLineNumber(llvm::SMLoc loc, unsigned bufferID = 0) const { - return getLineAndColumn(loc, bufferID).first; - } + // /// Find the line number for the specified location in the specified file. + // /// This is not a fast method. + // unsigned FindLineNumber(llvm::SMLoc loc, unsigned bufferID = 0) const { + // return getLineAndColumn(loc, bufferID).first; + // } - /// Find the line and column number for the specified location in the - /// specified file. This is not a fast method. - std::pair getLineAndColumn(llvm::SMLoc loc, - unsigned bufferID = 0) const; + // /// Find the line and column number for the specified location in the + // /// specified file. This is not a fast method. + // std::pair getLineAndColumn(llvm::SMLoc loc, + // unsigned bufferID = 0) + // const; - /// Get a string with the \p llvm::SMLoc filename and line number - /// formatted in the standard style. - std::string getFormattedLocationNoOffset(llvm::SMLoc loc, - bool includePath = false) const; + // /// Get a string with the \p llvm::SMLoc filename and line number + // /// formatted in the standard style. + // std::string getFormattedLocationNoOffset(llvm::SMLoc loc, + // bool includePath = false) const; - /// Given a line and column number in a mapped buffer, turn it into an - /// llvm::SMLoc. This will return a null llvm::SMLoc if the line/column - /// location is invalid. - llvm::SMLoc FindLocForLineAndColumn(unsigned bufferID, unsigned lineNo, - unsigned colNo); + // /// Given a line and column number in a mapped buffer, turn it into an + // /// llvm::SMLoc. This will return a null llvm::SMLoc if the line/column + // /// location is invalid. + // llvm::SMLoc FindLocForLineAndColumn(unsigned bufferID, unsigned lineNo, + // unsigned colNo); - /// Emit a message about the specified location with the specified string. - /// - /// \param ShowColors Display colored messages if output is a terminal and - /// the default error handler is used. - void PrintMessage(llvm::raw_ostream &os, llvm::SMLoc loc, DiagKind kind, - const llvm::Twine &msg, - llvm::ArrayRef ranges = {}, - llvm::ArrayRef fixIts = {}, - bool showColors = true) const; + // /// Emit a message about the specified location with the specified string. + // /// + // /// \param ShowColors Display colored messages if output is a terminal and + // /// the default error handler is used. + // void PrintMessage(llvm::raw_ostream &os, llvm::SMLoc loc, DiagKind kind, + // const llvm::Twine &msg, + // llvm::ArrayRef ranges = {}, + // llvm::ArrayRef fixIts = {}, + // bool showColors = true) const; - /// Emits a diagnostic to llvm::errs(). - void PrintMessage(llvm::SMLoc loc, DiagKind kind, const llvm::Twine &msg, - llvm::ArrayRef ranges = {}, - llvm::ArrayRef fixIts = {}, - bool showColors = true) const; + // /// Emits a diagnostic to llvm::errs(). + // void PrintMessage(llvm::SMLoc loc, DiagKind kind, const llvm::Twine &msg, + // llvm::ArrayRef ranges = {}, + // llvm::ArrayRef fixIts = {}, + // bool showColors = true) const; - /// Emits a manually-constructed diagnostic to the given output stream. - /// - /// \param ShowColors Display colored messages if output is a terminal and - /// the default error handler is used. - void PrintMessage(llvm::raw_ostream &os, const SMDiagnostic &diagnostic, - bool showColors = true) const; + // /// Emits a manually-constructed diagnostic to the given output stream. + // /// + // /// \param ShowColors Display colored messages if output is a terminal and + // /// the default error handler is used. + // void PrintMessage(llvm::raw_ostream &os, const SMDiagnostic &diagnostic, + // bool showColors = true) const; - /// Return an SMDiagnostic at the specified location with the specified - /// string. - /// - /// \param Msg If non-null, the kind of message (e.g., "error") which is - /// prefixed to the message. - SMDiagnostic GetMessage(llvm::SMLoc loc, DiagKind kind, - const llvm::Twine &msg, - llvm::ArrayRef ranges = {}, - llvm::ArrayRef fixIts = {}) const; + // /// Return an SMDiagnostic at the specified location with the specified + // /// string. + // /// + // /// \param Msg If non-null, the kind of message (e.g., "error") which is + // /// prefixed to the message. + // SMDiagnostic GetMessage(llvm::SMLoc loc, DiagKind kind, + // const llvm::Twine &msg, + // llvm::ArrayRef ranges = {}, + // llvm::ArrayRef fixIts = {}) const; - /// Prints the names of included files and the line of the file they were - /// included from. A diagnostic handler can use this before printing its - /// custom formatted message. - /// - /// \param IncludeLoc The location of the include. - /// \param OS the raw_ostream to print on. - void PrintIncludeStack(llvm::SMLoc includeLoc, llvm::raw_ostream &os) const; + // /// Prints the names of included files and the line of the file they were + // /// included from. A diagnostic handler can use this before printing its + // /// custom formatted message. + // /// + // /// \param IncludeLoc The location of the include. + // /// \param OS the raw_ostream to print on. + // void PrintIncludeStack(llvm::SMLoc includeLoc, llvm::raw_ostream &os) + // const; }; /// Instances of this class encapsulate one diagnostic report, allowing diff --git a/resources/dockr/Dockerfile.llvm b/resources/dockr/Dockerfile.llvm new file mode 100644 index 0000000..7c8b51f --- /dev/null +++ b/resources/dockr/Dockerfile.llvm @@ -0,0 +1,36 @@ +FROM debian:11-slim + +RUN apt-get update && apt-get install -y wget gnupg + +RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - +RUN echo "deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-13 main" >> /etc/apt/sources.list +RUN apt-get update +RUN apt-get install -y ccache cmake ccache git ninja-build build-essential clang-13 lldb-13 lld-13 + +ENV CXX=clang++-13 +ENV CC=clang-13 + +RUN mkdir -p /opt/build +COPY ./llvm-project /usr/src/llvm-project + +WORKDIR /opt/build + +ENV LDFLAGS="-fuse-ld=lld-13" + +RUN cmake -G Ninja /usr/src/llvm-project/llvm \ + -DCMAKE_INSTALL_PREFIX=/opt/llvm \ + -DLLVM_PARALLEL_COMPILE_JOBS=7 \ + -DLLVM_PARALLEL_LINK_JOBS=1 \ + -DLLVM_BUILD_EXAMPLES=ON \ + -DLLVM_TARGETS_TO_BUILD="X86" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DLLVM_CCACHE_BUILD=ON \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DLLVM_ENABLE_PROJECTS='clang;lldb;lld;mlir;clang-tools-extra;compiler-rt' \ + -DCMAKE_C_COMPILER=clang-13 \ + -DCMAKE_CXX_COMPILER=clang++-13 \ + -DLLVM_ENABLE_LLD=ON + +RUN cmake --build . +RUN cmake -DCMAKE_INSTALL_PREFIX=/opt/llvm -P cmake_install.cmake diff --git a/src/serene/CMakeLists.txt b/src/serene/CMakeLists.txt index 2989191..3d31aa9 100644 --- a/src/serene/CMakeLists.txt +++ b/src/serene/CMakeLists.txt @@ -4,6 +4,7 @@ set(HEADER_LIST "${INCLUDE_DIR}/serene/context.h" "${INCLUDE_DIR}/serene/environment.h" "${INCLUDE_DIR}/serene/traits.h" + "${INCLUDE_DIR}/serene/diagnostics.h" "${INCLUDE_DIR}/serene/exprs/expression.h" "${INCLUDE_DIR}/serene/exprs/symbol.h" @@ -53,6 +54,7 @@ add_library(serene namespace.cpp jit.cpp source_mgr.cpp + diagnostics.cpp # Reader reader/reader.cpp diff --git a/src/serene/context.cpp b/src/serene/context.cpp index d0ef068..31bdcbd 100644 --- a/src/serene/context.cpp +++ b/src/serene/context.cpp @@ -26,6 +26,7 @@ #include "serene/namespace.h" #include "serene/passes.h" +#include "serene/reader/location.h" #include "serene/slir/generatable.h" namespace serene { @@ -93,11 +94,13 @@ int SereneContext::getOptimizatioLevel() { } NSPtr SereneContext::readNamespace(std::string name) { - llvm::SMLoc loc; + auto loc = reader::LocationRange::UnknownLocation(name); + return readNamespace(name, loc); }; -NSPtr SereneContext::readNamespace(std::string name, llvm::SMLoc loc) { +NSPtr SereneContext::readNamespace(std::string name, + reader::LocationRange loc) { return sourceManager.readNamespace(*this, name, loc); } diff --git a/src/serene/diagnostics.cpp b/src/serene/diagnostics.cpp new file mode 100644 index 0000000..a42b94f --- /dev/null +++ b/src/serene/diagnostics.cpp @@ -0,0 +1,147 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "serene/diagnostics.h" + +#include "serene/context.h" +#include "serene/reader/location.h" +#include "serene/source_mgr.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +namespace serene { +void Diagnostic::writeColorByType(llvm::raw_ostream &os, llvm::StringRef str) { + llvm::ColorMode mode = + ctx.opts.withColors ? llvm::ColorMode::Auto : llvm::ColorMode::Disable; + + llvm::WithColor s(os, llvm::raw_ostream::SAVEDCOLOR, true, false, mode); + + switch (type) { + case Type::Error: + s.changeColor(llvm::raw_ostream::Colors::RED); + break; + // case Type::Warning: + // s.changeColor(llvm::raw_ostream::Colors::YELLOW); + // break; + case Type::Note: + s.changeColor(llvm::raw_ostream::Colors::CYAN); + break; + case Type::Remark: + s.changeColor(llvm::raw_ostream::Colors::MAGENTA); + break; + } + + s << str; + s.resetColor(); +}; + +std::string Diagnostic::getPrefix(llvm::StringRef prefix) { + if (prefix != "") { + return prefix.str(); + } + + switch (type) { + case Type::Error: + return "Error"; + break; + case Type::Note: + return "Note"; + case Type::Remark: + return "Remark"; + } +}; + +void Diagnostic::print(llvm::raw_ostream &os, llvm::StringRef prefix) { + llvm::ColorMode mode = + ctx.opts.withColors ? llvm::ColorMode::Auto : llvm::ColorMode::Disable; + + llvm::WithColor s(os, llvm::raw_ostream::SAVEDCOLOR, true, false, mode); + + s << "["; + writeColorByType(os, getPrefix(prefix)); + s << "]: "; + + if (err) { + s << err->description << "\n"; + } + + if (message != "") { + s.changeColor(llvm::raw_ostream::Colors::YELLOW); + s << "With message: "; + s.resetColor(); + s << message << "\n"; + } + + s << "In ns '"; + s.changeColor(llvm::raw_ostream::Colors::MAGENTA); + s << loc.start.ns; + s.resetColor(); + + if (loc.start.filename.hasValue()) { + s << "' At: "; + s.changeColor(llvm::raw_ostream::Colors::YELLOW); + s << loc.start.filename.getValue(); + s.resetColor(); + s << ":"; + s.changeColor(llvm::raw_ostream::Colors::CYAN); + s << loc.start.line; + s.resetColor(); + s << ":"; + s.changeColor(llvm::raw_ostream::Colors::CYAN); + s << loc.start.col; + s.resetColor(); + } +}; + +DiagnosticEngine::DiagnosticEngine(SereneContext &ctx) + : ctx(ctx), diagEngine(ctx.mlirContext.getDiagEngine()){}; + +void DiagnosticEngine::print(llvm::raw_ostream &os, Diagnostic &d){}; + +Diagnostic DiagnosticEngine::toDiagnostic(reader::LocationRange loc, + errors::ErrorVariant &e, + llvm::StringRef msg, + llvm::StringRef fn) { + + return Diagnostic(ctx, loc, &e, msg, fn); +}; + +void DiagnosticEngine::emitSyntaxError(reader::LocationRange loc, + errors::ErrorVariant &e, + llvm::StringRef msg) { + Diagnostic diag(ctx, loc, &e, msg); + + diag.print(llvm::errs(), "SyntaxError"); + exit(1); +}; + +std::unique_ptr makeDiagnosticEngine(SereneContext &ctx) { + return std::make_unique(ctx); +} +} // namespace serene diff --git a/src/serene/reader/location.cpp b/src/serene/reader/location.cpp index 11d1c26..a60491f 100644 --- a/src/serene/reader/location.cpp +++ b/src/serene/reader/location.cpp @@ -32,22 +32,30 @@ namespace serene { namespace reader { -LocationRange::LocationRange(const LocationRange &loc) { - start = loc.start; - end = loc.end; -} +// LocationRange::LocationRange(const LocationRange &loc) { +// start = loc.start.clone(); +// end = loc.end.clone(); +// } /// Return the string represenation of the location. std::string Location::toString() const { return llvm::formatv("{0}:{1}", line, col); }; -Location Location::clone() { return Location{ns, c, line, col}; } +Location Location::clone() { + return Location{ns, filename, c, line, col, knownLocation}; +} -mlir::Location Location::toMLIRLocation(SereneContext &ctx, - llvm::StringRef ns) { +Location Location::clone() const { + return Location{ns, filename, c, line, col, knownLocation}; +} + +mlir::Location Location::toMLIRLocation(SereneContext &ctx) { // TODO: Create a new Location attribute that is namespace base - + if (filename.hasValue()) { + return mlir::FileLineColLoc::get(&ctx.mlirContext, filename.getValue(), + line, col); + } return mlir::FileLineColLoc::get(&ctx.mlirContext, ns, line, col); } /// Increase the given location by one and set the line/col value in respect to @@ -62,9 +70,10 @@ void incLocation(Location &loc, const char *c) { if (!newline) { loc.col++; + } else { + loc.line++; + loc.col = 0; } - - loc.line++; } /// decrease the given location by one and set the line/col value in respect to diff --git a/src/serene/reader/reader.cpp b/src/serene/reader/reader.cpp index e6ec727..b1d8424 100644 --- a/src/serene/reader/reader.cpp +++ b/src/serene/reader/reader.cpp @@ -27,12 +27,12 @@ #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Location.h" #include "mlir/Support/LogicalResult.h" +#include "serene/errors/constants.h" #include "serene/exprs/list.h" #include "serene/exprs/number.h" #include "serene/exprs/symbol.h" #include "serene/namespace.h" -#include "clang/AST/Stmt.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" @@ -53,54 +53,91 @@ namespace reader { Reader::Reader(SereneContext &ctx, llvm::StringRef buffer, llvm::StringRef ns, llvm::Optional filename) - : ctx(ctx), ns(ns), filename(filename), buf(buffer) { - current_location.ns = ns; -}; + : ctx(ctx), ns(ns), filename(filename), buf(buffer), + currentLocation(Location(ns, filename)){}; Reader::Reader(SereneContext &ctx, llvm::MemoryBufferRef buffer, llvm::StringRef ns, llvm::Optional filename) - : ctx(ctx), ns(ns), filename(filename), buf(buffer.getBuffer()) { - current_location.ns = ns; -}; + : ctx(ctx), ns(ns), filename(filename), buf(buffer.getBuffer()), + currentLocation(Location(ns, filename)){}; Reader::~Reader() { READER_LOG("Destroying the reader"); } const char *Reader::getChar(bool skip_whitespace) { for (;;) { - if (current_char == NULL) { + if (currentChar == NULL) { READER_LOG("Setting the first char of the buffer"); - current_char = buf.begin(); - current_pos = 1; + currentChar = buf.begin(); + currentPos = 1; + currentLocation.line = 1; + currentLocation.col = 1; } else { - current_char++; - current_pos++; + currentChar++; + currentPos++; + + prevCol = currentLocation.col; + currentLocation.col++; + + if (*currentChar == '\n') { + READER_LOG("Detected end of line"); + + if (readEOL) { + currentLocation.col = 1; + currentLocation.line++; + } + + readEOL = true; + } else { + + if (readEOL) { + currentLocation.line++; + currentLocation.col = 1; + } + readEOL = false; + } } + READER_LOG("Current Char: " << *currentChar + << " Location: " << currentLocation.toString()); - READER_LOG("Current Char: " << *current_char); - incLocation(current_location, current_char); - - if (skip_whitespace == true && isspace(*current_char)) { + if (skip_whitespace == true && isspace(*currentChar)) { READER_LOG("Skip whitespace is true and the char is a whitespace"); continue; } else { - return current_char; + return currentChar; } } }; +const char *Reader::nextChar() { return currentChar + 1; }; + void Reader::ungetChar() { - READER_LOG("Unread Char: " << *current_char); - current_char--; - current_pos--; + READER_LOG("Unread Char: " << *currentChar); + currentChar--; + currentPos--; // The char that we just unget - decLocation(current_location, current_char); + + if (*currentChar == '\n') { + // In case of EOL we don't decrease the line counter because we will read + // it again and it will be pointless + READER_LOG("Detected end of line"); + currentLocation.col = prevCol; + + } else { + prevCol = prevCol == 0 ? 0 : prevCol - 1; + + currentLocation.col = + currentLocation.col == 0 ? 0 : currentLocation.col - 1; + } + + READER_LOG("Current Char after unread: " << *currentChar << " Location: " + << currentLocation.toString()); }; bool Reader::isEndOfBuffer(const char *c) { - return *c == '\0' || current_pos > buf.size() || *c == EOF; + return *c == '\0' || currentPos > buf.size() || *c == EOF; }; -Location Reader::getCurrentLocation() { return current_location.clone(); }; +Location Reader::getCurrentLocation() { return currentLocation.clone(); }; /// A predicate function indicating whether the given char `c` is a valid /// char for the starting point of a symbol or not. @@ -150,10 +187,8 @@ exprs::Node Reader::readNumber(bool neg) { ((!(isspace(*c)) && (isdigit(*c) || *c == '.')))) { if (*c == '.' && floatNum == true) { - ctx.sourceManager.PrintMessage( - llvm::errs(), llvm::SMLoc::getFromPointer(c), - ctx.sourceManager.DK_Error, - llvm::formatv("Two float points in a number?\n", c)); + loc.end = getCurrentLocation(); + ctx.diagEngine->emitSyntaxError(loc, errors::TwoFloatPoints); exit(1); } @@ -167,10 +202,8 @@ exprs::Node Reader::readNumber(bool neg) { } if (std::isalpha(*c)) { - ctx.sourceManager.PrintMessage( - llvm::errs(), llvm::SMLoc::getFromPointer(c), - ctx.sourceManager.DK_Error, - llvm::formatv("Invalid digit for a number. Are you drunk?\n", c)); + loc.end = getCurrentLocation(); + ctx.diagEngine->emitSyntaxError(loc, errors::InvalidDigitForNumber); exit(1); } @@ -189,17 +222,13 @@ exprs::Node Reader::readSymbol() { READER_LOG("Reading a symbol..."); bool empty = true; auto c = getChar(false); + LocationRange loc; + loc.start = getCurrentLocation(); READER_LOG("Reading a symbol..."); if (!this->isValidForIdentifier(*c)) { - - // TODO: Replece this with a tranceback function or something to raise - // synatx error. - ctx.sourceManager.PrintMessage( - llvm::errs(), llvm::SMLoc::getFromPointer(c), - ctx.sourceManager.DK_Error, - llvm::formatv("Invalid character at the start of a symbol: '{0}'\n", - c)); + loc.end = getCurrentLocation(); + ctx.diagEngine->emitSyntaxError(loc, errors::InvalidCharacterForSymbol); exit(1); } @@ -217,8 +246,6 @@ exprs::Node Reader::readSymbol() { } std::string sym(""); - LocationRange loc; - loc.start = getCurrentLocation(); while (!isEndOfBuffer(c) && ((!(isspace(*c)) && this->isValidForIdentifier(*c)))) { @@ -253,11 +280,9 @@ exprs::Node Reader::readList() { auto c = getChar(true); if (isEndOfBuffer(c)) { - ctx.sourceManager.PrintMessage( - llvm::errs(), llvm::SMLoc::getFromPointer(c), - ctx.sourceManager.DK_Error, - llvm::formatv("EOF reached before closing of list")); - + list->location.end = getCurrentLocation(); + ctx.diagEngine->emitSyntaxError(list->location, + errors::EOFWhileScaningAList); exit(1); } @@ -280,9 +305,7 @@ exprs::Node Reader::readList() { /// Reads an expression by dispatching to the proper reader function. exprs::Node Reader::readExpr() { auto c = getChar(false); - READER_LOG("Read char at `readExpr`: " << *c << " << " << current_pos << "|" - << buf.size() << " BB " - << isEndOfBuffer(c)); + READER_LOG("Read char at `readExpr`: " << *c); ungetChar(); if (isEndOfBuffer(c)) { diff --git a/src/serene/source_mgr.cpp b/src/serene/source_mgr.cpp index 4410872..0e88302 100644 --- a/src/serene/source_mgr.cpp +++ b/src/serene/source_mgr.cpp @@ -25,7 +25,9 @@ #include "serene/source_mgr.h" #include "mlir/Support/LogicalResult.h" +#include "serene/errors/constants.h" #include "serene/namespace.h" +#include "serene/reader/location.h" #include "serene/reader/reader.h" #include "llvm/Support/MemoryBufferRef.h" @@ -49,7 +51,7 @@ std::string inline SourceMgr::convertNamespaceToPath(std::string ns_name) { }; NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name, - llvm::SMLoc importLoc, bool entryNS) { + reader::LocationRange importLoc, bool entryNS) { std::string includedFile; auto path = convertNamespaceToPath(name); @@ -69,16 +71,19 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name, } if (!newBufOrErr) { - PrintMessage(importLoc, DiagKind::DK_Error, - llvm::formatv("Couldn't find namespace '{0}'", name)); + auto msg = llvm::formatv("Couldn't find namespace '{0}'", name); + ctx.diagEngine->emitSyntaxError(importLoc, errors::NSLoadError, + llvm::StringRef(msg)); return nullptr; } auto bufferId = AddNewSourceBuffer(std::move(*newBufOrErr), importLoc); if (bufferId == 0) { - PrintMessage(importLoc, DiagKind::DK_Error, - llvm::formatv("Couldn't add namespace '{0}'", name)); + auto msg = llvm::formatv("Couldn't add namespace '{0}'", name); + ctx.diagEngine->emitSyntaxError(importLoc, errors::NSAddToSMError, + llvm::StringRef(msg)); + return nullptr; } @@ -107,122 +112,132 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name, return ns; }; -unsigned SourceMgr::AddIncludeFile(const std::string &filename, - llvm::SMLoc includeLoc, - std::string &includedFile) { - includedFile = filename; - llvm::ErrorOr> NewBufOrErr = - llvm::MemoryBuffer::getFile(includedFile); +unsigned SourceMgr::AddNewSourceBuffer(std::unique_ptr f, + reader::LocationRange includeLoc) { + SrcBuffer nb; + nb.buffer = std::move(f); + nb.includeLoc = includeLoc; + buffers.push_back(std::move(nb)); + return buffers.size(); +}; - // If the file didn't exist directly, see if it's in an include path. - for (unsigned i = 0, e = loadPaths.size(); i != e && !NewBufOrErr; ++i) { - includedFile = - loadPaths[i] + llvm::sys::path::get_separator().data() + filename; - NewBufOrErr = llvm::MemoryBuffer::getFile(includedFile); - } +// unsigned SourceMgr::AddIncludeFile(const std::string &filename, +// llvm::SMLoc includeLoc, +// std::string &includedFile) { +// includedFile = filename; +// llvm::ErrorOr> NewBufOrErr = +// llvm::MemoryBuffer::getFile(includedFile); - if (!NewBufOrErr) - return 0; +// // If the file didn't exist directly, see if it's in an include path. +// for (unsigned i = 0, e = loadPaths.size(); i != e && !NewBufOrErr; ++i) { +// includedFile = +// loadPaths[i] + llvm::sys::path::get_separator().data() + filename; +// NewBufOrErr = llvm::MemoryBuffer::getFile(includedFile); +// } - return AddNewSourceBuffer(std::move(*NewBufOrErr), includeLoc); -} +// if (!NewBufOrErr) +// return 0; -unsigned SourceMgr::FindBufferContainingLoc(llvm::SMLoc loc) const { - for (unsigned i = 0, e = buffers.size(); i != e; ++i) - if (loc.getPointer() >= buffers[i].buffer->getBufferStart() && - // Use <= here so that a pointer to the null at the end of the buffer - // is included as part of the buffer. - loc.getPointer() <= buffers[i].buffer->getBufferEnd()) - return i + 1; - return 0; -} +// return AddNewSourceBuffer(std::move(*NewBufOrErr), includeLoc); +// } -template -static std::vector &GetOrCreateOffsetCache(void *&offsetCache, - llvm::MemoryBuffer *buffer) { - if (offsetCache) - return *static_cast *>(offsetCache); +// unsigned SourceMgr::FindBufferContainingLoc(llvm::SMLoc loc) const { +// for (unsigned i = 0, e = buffers.size(); i != e; ++i) +// if (loc.getPointer() >= buffers[i].buffer->getBufferStart() && +// // Use <= here so that a pointer to the null at the end of the buffer +// // is included as part of the buffer. +// loc.getPointer() <= buffers[i].buffer->getBufferEnd()) +// return i + 1; +// return 0; +// } - // Lazily fill in the offset cache. - auto *offsets = new std::vector(); - size_t sz = buffer->getBufferSize(); - assert(sz <= std::numeric_limits::max()); - llvm::StringRef s = buffer->getBuffer(); - for (size_t n = 0; n < sz; ++n) { - if (s[n] == '\n') - offsets->push_back(static_cast(n)); - } +// template +// static std::vector &GetOrCreateOffsetCache(void *&offsetCache, +// llvm::MemoryBuffer *buffer) { +// if (offsetCache) +// return *static_cast *>(offsetCache); - offsetCache = offsets; - return *offsets; -} +// // Lazily fill in the offset cache. +// auto *offsets = new std::vector(); +// size_t sz = buffer->getBufferSize(); +// assert(sz <= std::numeric_limits::max()); +// llvm::StringRef s = buffer->getBuffer(); +// for (size_t n = 0; n < sz; ++n) { +// if (s[n] == '\n') +// offsets->push_back(static_cast(n)); +// } -template -unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *ptr) const { - std::vector &offsets = - GetOrCreateOffsetCache(offsetCache, buffer.get()); +// offsetCache = offsets; +// return *offsets; +// } - const char *bufStart = buffer->getBufferStart(); - assert(ptr >= bufStart && ptr <= buffer->getBufferEnd()); - ptrdiff_t ptrDiff = ptr - bufStart; - assert(ptrDiff >= 0 && - static_cast(ptrDiff) <= std::numeric_limits::max()); - T ptrOffset = static_cast(ptrDiff); +// template +// unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *ptr) +// const { +// std::vector &offsets = +// GetOrCreateOffsetCache(offsetCache, buffer.get()); - // llvm::lower_bound gives the number of EOL before PtrOffset. Add 1 to get - // the line number. - return llvm::lower_bound(offsets, ptrOffset) - offsets.begin() + 1; -} +// const char *bufStart = buffer->getBufferStart(); +// assert(ptr >= bufStart && ptr <= buffer->getBufferEnd()); +// ptrdiff_t ptrDiff = ptr - bufStart; +// assert(ptrDiff >= 0 && +// static_cast(ptrDiff) <= std::numeric_limits::max()); +// T ptrOffset = static_cast(ptrDiff); -/// Look up a given \p Ptr in in the buffer, determining which line it came -/// from. -unsigned SourceMgr::SrcBuffer::getLineNumber(const char *ptr) const { - size_t sz = buffer->getBufferSize(); - if (sz <= std::numeric_limits::max()) - return getLineNumberSpecialized(ptr); - else if (sz <= std::numeric_limits::max()) - return getLineNumberSpecialized(ptr); - else if (sz <= std::numeric_limits::max()) - return getLineNumberSpecialized(ptr); - else - return getLineNumberSpecialized(ptr); -} +// // llvm::lower_bound gives the number of EOL before PtrOffset. Add 1 to get +// // the line number. +// return llvm::lower_bound(offsets, ptrOffset) - offsets.begin() + 1; +// } -template -const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized( - unsigned lineNo) const { - std::vector &offsets = - GetOrCreateOffsetCache(offsetCache, buffer.get()); +// /// Look up a given \p Ptr in in the buffer, determining which line it came +// /// from. +// unsigned SourceMgr::SrcBuffer::getLineNumber(const char *ptr) const { +// size_t sz = buffer->getBufferSize(); +// if (sz <= std::numeric_limits::max()) +// return getLineNumberSpecialized(ptr); +// else if (sz <= std::numeric_limits::max()) +// return getLineNumberSpecialized(ptr); +// else if (sz <= std::numeric_limits::max()) +// return getLineNumberSpecialized(ptr); +// else +// return getLineNumberSpecialized(ptr); +// } - // We start counting line and column numbers from 1. - if (lineNo != 0) - --lineNo; +// template +// const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized( +// unsigned lineNo) const { +// std::vector &offsets = +// GetOrCreateOffsetCache(offsetCache, buffer.get()); - const char *bufStart = buffer->getBufferStart(); +// // We start counting line and column numbers from 1. +// if (lineNo != 0) +// --lineNo; - // The offset cache contains the location of the \n for the specified line, - // we want the start of the line. As such, we look for the previous entry. - if (lineNo == 0) - return bufStart; - if (lineNo > offsets.size()) - return nullptr; - return bufStart + offsets[lineNo - 1] + 1; -} +// const char *bufStart = buffer->getBufferStart(); -/// Return a pointer to the first character of the specified line number or -/// null if the line number is invalid. -const char * -SourceMgr::SrcBuffer::getPointerForLineNumber(unsigned lineNo) const { - size_t sz = buffer->getBufferSize(); - if (sz <= std::numeric_limits::max()) - return getPointerForLineNumberSpecialized(lineNo); - else if (sz <= std::numeric_limits::max()) - return getPointerForLineNumberSpecialized(lineNo); - else if (sz <= std::numeric_limits::max()) - return getPointerForLineNumberSpecialized(lineNo); - else - return getPointerForLineNumberSpecialized(lineNo); -} +// // The offset cache contains the location of the \n for the specified line, +// // we want the start of the line. As such, we look for the previous entry. +// if (lineNo == 0) +// return bufStart; +// if (lineNo > offsets.size()) +// return nullptr; +// return bufStart + offsets[lineNo - 1] + 1; +// } + +// /// Return a pointer to the first character of the specified line number or +// /// null if the line number is invalid. +// const char * +// SourceMgr::SrcBuffer::getPointerForLineNumber(unsigned lineNo) const { +// size_t sz = buffer->getBufferSize(); +// if (sz <= std::numeric_limits::max()) +// return getPointerForLineNumberSpecialized(lineNo); +// else if (sz <= std::numeric_limits::max()) +// return getPointerForLineNumberSpecialized(lineNo); +// else if (sz <= std::numeric_limits::max()) +// return getPointerForLineNumberSpecialized(lineNo); +// else +// return getPointerForLineNumberSpecialized(lineNo); +// } SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&other) : buffer(std::move(other.buffer)), offsetCache(other.offsetCache), @@ -245,190 +260,195 @@ SourceMgr::SrcBuffer::~SrcBuffer() { } } -std::pair -SourceMgr::getLineAndColumn(llvm::SMLoc loc, unsigned bufferID) const { - if (!bufferID) - bufferID = FindBufferContainingLoc(loc); - assert(bufferID && "Invalid location!"); +// std::pair +// SourceMgr::getLineAndColumn(llvm::SMLoc loc, unsigned bufferID) const { +// if (!bufferID) +// bufferID = FindBufferContainingLoc(loc); +// assert(bufferID && "Invalid location!"); - auto &sb = getBufferInfo(bufferID); - const char *ptr = loc.getPointer(); +// auto &sb = getBufferInfo(bufferID); +// const char *ptr = loc.getPointer(); - unsigned lineNo = sb.getLineNumber(ptr); - const char *bufStart = sb.buffer->getBufferStart(); - size_t newlineOffs = - llvm::StringRef(bufStart, ptr - bufStart).find_last_of("\n\r"); - if (newlineOffs == llvm::StringRef::npos) - newlineOffs = ~(size_t)0; - return std::make_pair(lineNo, ptr - bufStart - newlineOffs); -} +// unsigned lineNo = sb.getLineNumber(ptr); +// const char *bufStart = sb.buffer->getBufferStart(); +// size_t newlineOffs = +// llvm::StringRef(bufStart, ptr - bufStart).find_last_of("\n\r"); +// if (newlineOffs == llvm::StringRef::npos) +// newlineOffs = ~(size_t)0; +// return std::make_pair(lineNo, ptr - bufStart - newlineOffs); +// } -// FIXME: Note that the formatting of source locations is spread between -// multiple functions, some in SourceMgr and some in SMDiagnostic. A better -// solution would be a general-purpose source location formatter -// in one of those two classes, or possibly in llvm::SMLoc. +// // FIXME: Note that the formatting of source locations is spread between +// // multiple functions, some in SourceMgr and some in SMDiagnostic. A better +// // solution would be a general-purpose source location formatter +// // in one of those two classes, or possibly in llvm::SMLoc. -/// Get a string with the source location formatted in the standard -/// style, but without the line offset. If \p IncludePath is true, the path -/// is included. If false, only the file name and extension are included. -std::string SourceMgr::getFormattedLocationNoOffset(llvm::SMLoc loc, - bool includePath) const { - auto bufferID = FindBufferContainingLoc(loc); - assert(bufferID && "Invalid location!"); - auto fileSpec = getBufferInfo(bufferID).buffer->getBufferIdentifier(); +// /// Get a string with the source location formatted in the standard +// /// style, but without the line offset. If \p IncludePath is true, the path +// /// is included. If false, only the file name and extension are included. +// std::string SourceMgr::getFormattedLocationNoOffset(llvm::SMLoc loc, +// bool includePath) const { +// auto bufferID = FindBufferContainingLoc(loc); +// assert(bufferID && "Invalid location!"); +// auto fileSpec = getBufferInfo(bufferID).buffer->getBufferIdentifier(); - if (includePath) { - return fileSpec.str() + ":" + std::to_string(FindLineNumber(loc, bufferID)); - } else { - auto I = fileSpec.find_last_of("/\\"); - I = (I == fileSpec.size()) ? 0 : (I + 1); - return fileSpec.substr(I).str() + ":" + - std::to_string(FindLineNumber(loc, bufferID)); - } -} +// if (includePath) { +// return fileSpec.str() + ":" + std::to_string(FindLineNumber(loc, +// bufferID)); +// } else { +// auto I = fileSpec.find_last_of("/\\"); +// I = (I == fileSpec.size()) ? 0 : (I + 1); +// return fileSpec.substr(I).str() + ":" + +// std::to_string(FindLineNumber(loc, bufferID)); +// } +// } -/// Given a line and column number in a mapped buffer, turn it into an -/// llvm::SMLoc. This will return a null llvm::SMLoc if the line/column location -/// is invalid. -llvm::SMLoc SourceMgr::FindLocForLineAndColumn(unsigned bufferID, - unsigned lineNo, - unsigned colNo) { - auto &sb = getBufferInfo(bufferID); - const char *ptr = sb.getPointerForLineNumber(lineNo); - if (!ptr) - return llvm::SMLoc(); +// /// Given a line and column number in a mapped buffer, turn it into an +// /// llvm::SMLoc. This will return a null llvm::SMLoc if the line/column +// location +// /// is invalid. +// llvm::SMLoc SourceMgr::FindLocForLineAndColumn(unsigned bufferID, +// unsigned lineNo, +// unsigned colNo) { +// auto &sb = getBufferInfo(bufferID); +// const char *ptr = sb.getPointerForLineNumber(lineNo); +// if (!ptr) +// return llvm::SMLoc(); - // We start counting line and column numbers from 1. - if (colNo != 0) - --colNo; +// // We start counting line and column numbers from 1. +// if (colNo != 0) +// --colNo; - // If we have a column number, validate it. - if (colNo) { - // Make sure the location is within the current line. - if (ptr + colNo > sb.buffer->getBufferEnd()) - return llvm::SMLoc(); +// // If we have a column number, validate it. +// if (colNo) { +// // Make sure the location is within the current line. +// if (ptr + colNo > sb.buffer->getBufferEnd()) +// return llvm::SMLoc(); - // Make sure there is no newline in the way. - if (llvm::StringRef(ptr, colNo).find_first_of("\n\r") != - llvm::StringRef::npos) - return llvm::SMLoc(); +// // Make sure there is no newline in the way. +// if (llvm::StringRef(ptr, colNo).find_first_of("\n\r") != +// llvm::StringRef::npos) +// return llvm::SMLoc(); - ptr += colNo; - } +// ptr += colNo; +// } - return llvm::SMLoc::getFromPointer(ptr); -} +// return llvm::SMLoc::getFromPointer(ptr); +// } -void SourceMgr::PrintIncludeStack(llvm::SMLoc includeLoc, - llvm::raw_ostream &os) const { - if (includeLoc == llvm::SMLoc()) - return; // Top of stack. +// void SourceMgr::PrintIncludeStack(llvm::SMLoc includeLoc, +// llvm::raw_ostream &os) const { +// if (includeLoc == llvm::SMLoc()) +// return; // Top of stack. - unsigned curBuf = FindBufferContainingLoc(includeLoc); - assert(curBuf && "Invalid or unspecified location!"); +// unsigned curBuf = FindBufferContainingLoc(includeLoc); +// assert(curBuf && "Invalid or unspecified location!"); - PrintIncludeStack(getBufferInfo(curBuf).includeLoc, os); +// PrintIncludeStack(getBufferInfo(curBuf).includeLoc, os); - os << "Included from " << getBufferInfo(curBuf).buffer->getBufferIdentifier() - << ":" << FindLineNumber(includeLoc, curBuf) << ":\n"; -} +// os << "Included from " << +// getBufferInfo(curBuf).buffer->getBufferIdentifier() +// << ":" << FindLineNumber(includeLoc, curBuf) << ":\n"; +// } -SMDiagnostic SourceMgr::GetMessage(llvm::SMLoc loc, SourceMgr::DiagKind kind, - const llvm::Twine &msg, - llvm::ArrayRef ranges, - llvm::ArrayRef fixIts) const { - // First thing to do: find the current buffer containing the specified - // location to pull out the source line. - llvm::SmallVector, 4> colRanges; - std::pair lineAndCol; - llvm::StringRef bufferID = ""; - llvm::StringRef lineStr; +// SMDiagnostic SourceMgr::GetMessage(llvm::SMLoc loc, SourceMgr::DiagKind kind, +// const llvm::Twine &msg, +// llvm::ArrayRef ranges, +// llvm::ArrayRef fixIts) +// const { +// // First thing to do: find the current buffer containing the specified +// // location to pull out the source line. +// llvm::SmallVector, 4> colRanges; +// std::pair lineAndCol; +// llvm::StringRef bufferID = ""; +// llvm::StringRef lineStr; - if (loc.isValid()) { - unsigned curBuf = FindBufferContainingLoc(loc); - assert(curBuf && "Invalid or unspecified location!"); +// if (loc.isValid()) { +// unsigned curBuf = FindBufferContainingLoc(loc); +// assert(curBuf && "Invalid or unspecified location!"); - const llvm::MemoryBuffer *curMB = getMemoryBuffer(curBuf); - bufferID = curMB->getBufferIdentifier(); +// const llvm::MemoryBuffer *curMB = getMemoryBuffer(curBuf); +// bufferID = curMB->getBufferIdentifier(); - // Scan backward to find the start of the line. - const char *lineStart = loc.getPointer(); - const char *bufStart = curMB->getBufferStart(); - while (lineStart != bufStart && lineStart[-1] != '\n' && - lineStart[-1] != '\r') - --lineStart; +// // Scan backward to find the start of the line. +// const char *lineStart = loc.getPointer(); +// const char *bufStart = curMB->getBufferStart(); +// while (lineStart != bufStart && lineStart[-1] != '\n' && +// lineStart[-1] != '\r') +// --lineStart; - // Get the end of the line. - const char *lineEnd = loc.getPointer(); - const char *bufEnd = curMB->getBufferEnd(); - while (lineEnd != bufEnd && lineEnd[0] != '\n' && lineEnd[0] != '\r') - ++lineEnd; - lineStr = llvm::StringRef(lineStart, lineEnd - lineStart); +// // Get the end of the line. +// const char *lineEnd = loc.getPointer(); +// const char *bufEnd = curMB->getBufferEnd(); +// while (lineEnd != bufEnd && lineEnd[0] != '\n' && lineEnd[0] != '\r') +// ++lineEnd; +// lineStr = llvm::StringRef(lineStart, lineEnd - lineStart); - // Convert any ranges to column ranges that only intersect the line of the - // location. - for (unsigned i = 0, e = ranges.size(); i != e; ++i) { - llvm::SMRange r = ranges[i]; - if (!r.isValid()) - continue; +// // Convert any ranges to column ranges that only intersect the line of +// the +// // location. +// for (unsigned i = 0, e = ranges.size(); i != e; ++i) { +// llvm::SMRange r = ranges[i]; +// if (!r.isValid()) +// continue; - // If the line doesn't contain any part of the range, then ignore it. - if (r.Start.getPointer() > lineEnd || r.End.getPointer() < lineStart) - continue; +// // If the line doesn't contain any part of the range, then ignore it. +// if (r.Start.getPointer() > lineEnd || r.End.getPointer() < lineStart) +// continue; - // Ignore pieces of the range that go onto other lines. - if (r.Start.getPointer() < lineStart) - r.Start = llvm::SMLoc::getFromPointer(lineStart); - if (r.End.getPointer() > lineEnd) - r.End = llvm::SMLoc::getFromPointer(lineEnd); +// // Ignore pieces of the range that go onto other lines. +// if (r.Start.getPointer() < lineStart) +// r.Start = llvm::SMLoc::getFromPointer(lineStart); +// if (r.End.getPointer() > lineEnd) +// r.End = llvm::SMLoc::getFromPointer(lineEnd); - // Translate from llvm::SMLoc ranges to column ranges. - // FIXME: Handle multibyte characters. - colRanges.push_back(std::make_pair(r.Start.getPointer() - lineStart, - r.End.getPointer() - lineStart)); - } +// // Translate from llvm::SMLoc ranges to column ranges. +// // FIXME: Handle multibyte characters. +// colRanges.push_back(std::make_pair(r.Start.getPointer() - lineStart, +// r.End.getPointer() - lineStart)); +// } - lineAndCol = getLineAndColumn(loc, curBuf); - } +// lineAndCol = getLineAndColumn(loc, curBuf); +// } - return SMDiagnostic(*this, loc, bufferID, lineAndCol.first, - lineAndCol.second - 1, kind, msg.str(), lineStr, - colRanges, fixIts); -} +// return SMDiagnostic(*this, loc, bufferID, lineAndCol.first, +// lineAndCol.second - 1, kind, msg.str(), lineStr, +// colRanges, fixIts); +// } -void SourceMgr::PrintMessage(llvm::raw_ostream &os, - const SMDiagnostic &diagnostic, - bool showColors) const { - // Report the message with the diagnostic handler if present. - if (diagHandler) { - diagHandler(diagnostic, diagContext); - return; - } +// void SourceMgr::PrintMessage(llvm::raw_ostream &os, +// const SMDiagnostic &diagnostic, +// bool showColors) const { +// // Report the message with the diagnostic handler if present. +// if (diagHandler) { +// diagHandler(diagnostic, diagContext); +// return; +// } - if (diagnostic.getLoc().isValid()) { - unsigned CurBuf = FindBufferContainingLoc(diagnostic.getLoc()); - assert(CurBuf && "Invalid or unspecified location!"); - PrintIncludeStack(getBufferInfo(CurBuf).includeLoc, os); - } +// if (diagnostic.getLoc().isValid()) { +// unsigned CurBuf = FindBufferContainingLoc(diagnostic.getLoc()); +// assert(CurBuf && "Invalid or unspecified location!"); +// PrintIncludeStack(getBufferInfo(CurBuf).includeLoc, os); +// } - diagnostic.print(nullptr, os, showColors); -} +// diagnostic.print(nullptr, os, showColors); +// } -void SourceMgr::PrintMessage(llvm::raw_ostream &os, llvm::SMLoc loc, - SourceMgr::DiagKind kind, const llvm::Twine &msg, - llvm::ArrayRef ranges, - llvm::ArrayRef fixIts, - bool showColors) const { - PrintMessage(os, GetMessage(loc, kind, msg, ranges, fixIts), showColors); -} +// void SourceMgr::PrintMessage(llvm::raw_ostream &os, llvm::SMLoc loc, +// SourceMgr::DiagKind kind, const llvm::Twine +// &msg, llvm::ArrayRef ranges, +// llvm::ArrayRef fixIts, +// bool showColors) const { +// PrintMessage(os, GetMessage(loc, kind, msg, ranges, fixIts), showColors); +// } -void SourceMgr::PrintMessage(llvm::SMLoc loc, SourceMgr::DiagKind kind, - const llvm::Twine &msg, - llvm::ArrayRef ranges, - llvm::ArrayRef fixIts, - bool showColors) const { - PrintMessage(llvm::errs(), loc, kind, msg, ranges, fixIts, showColors); -} +// void SourceMgr::PrintMessage(llvm::SMLoc loc, SourceMgr::DiagKind kind, +// const llvm::Twine &msg, +// llvm::ArrayRef ranges, +// llvm::ArrayRef fixIts, +// bool showColors) const { +// PrintMessage(llvm::errs(), loc, kind, msg, ranges, fixIts, showColors); +// } //===----------------------------------------------------------------------===// // SMDiagnostic Implementation