Add our own dianostic engine
This commit is contained in:
parent
800e3c5fc8
commit
5491660261
|
@ -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) {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
(def main (fn () 3))
|
||||
(def main1 (fn (v y n) 3))
|
||||
ht
|
||||
|
||||
|
||||
|
||||
|
||||
(- 3 4 (sh - r e 3bea -32) ((((())))))
|
|
@ -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 <llvm/ADT/Optional.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/Support/Host.h>
|
||||
|
@ -44,6 +43,10 @@
|
|||
|
||||
namespace serene {
|
||||
|
||||
namespace reader {
|
||||
class LocationRange;
|
||||
}
|
||||
|
||||
namespace exprs {
|
||||
class Expression;
|
||||
using Node = std::shared_ptr<Expression>;
|
||||
|
@ -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<DiagnosticEngine> 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<Namespace> getNS(llvm::StringRef ns_name);
|
||||
|
||||
SereneContext()
|
||||
: pm(&mlirContext), diagEngine(mlirContext.getDiagEngine()),
|
||||
: pm(&mlirContext), diagEngine(makeDiagnosticEngine(*this)),
|
||||
targetPhase(CompilationPhase::NoOptimization) {
|
||||
mlirContext.getOrLoadDialect<serene::slir::SereneDialect>();
|
||||
mlirContext.getOrLoadDialect<mlir::StandardOpsDialect>();
|
||||
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- C++ -*-
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||
*
|
||||
* 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 <llvm/ADT/StringRef.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Diagnostics.h>
|
||||
|
||||
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<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx);
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
|
@ -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<ErrID, ErrorVariant *> 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
|
||||
|
|
|
@ -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<llvm::StringRef> 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<llvm::StringRef> 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 *);
|
||||
|
|
|
@ -58,22 +58,30 @@ private:
|
|||
llvm::StringRef ns;
|
||||
llvm::Optional<llvm::StringRef> 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.
|
||||
|
|
|
@ -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 <llvm/ADT/SmallVector.h>
|
||||
#include <llvm/Support/ErrorOr.h>
|
||||
#include <llvm/Support/MemoryBuffer.h>
|
||||
#include <llvm/Support/SourceMgr.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Diagnostics.h>
|
||||
#include <mlir/Support/Timing.h>
|
||||
|
||||
#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<llvm::MemoryBuffer> 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<unsigned, unsigned> 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<unsigned, unsigned> 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<llvm::SMRange> ranges = {},
|
||||
llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges = {},
|
||||
// llvm::ArrayRef<llvm::SMFixIt> fixIts = {},
|
||||
// bool showColors = true) const;
|
||||
|
||||
/// Emits a diagnostic to llvm::errs().
|
||||
void PrintMessage(llvm::SMLoc loc, DiagKind kind, const llvm::Twine &msg,
|
||||
llvm::ArrayRef<llvm::SMRange> ranges = {},
|
||||
llvm::ArrayRef<llvm::SMFixIt> fixIts = {},
|
||||
bool showColors = true) const;
|
||||
// /// Emits a diagnostic to llvm::errs().
|
||||
// void PrintMessage(llvm::SMLoc loc, DiagKind kind, const llvm::Twine &msg,
|
||||
// llvm::ArrayRef<llvm::SMRange> ranges = {},
|
||||
// llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges = {},
|
||||
llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges = {},
|
||||
// llvm::ArrayRef<llvm::SMFixIt> 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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/* -*- C++ -*-
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||
*
|
||||
* 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 <llvm/Support/FormatVariadic.h>
|
||||
#include <memory>
|
||||
|
||||
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<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx) {
|
||||
return std::make_unique<DiagnosticEngine>(ctx);
|
||||
}
|
||||
} // namespace serene
|
|
@ -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
|
||||
|
|
|
@ -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<llvm::StringRef> 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<llvm::StringRef> 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)) {
|
||||
|
|
|
@ -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<std::unique_ptr<llvm::MemoryBuffer>> NewBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(includedFile);
|
||||
unsigned SourceMgr::AddNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> 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<std::unique_ptr<llvm::MemoryBuffer>> 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 <typename T>
|
||||
static std::vector<T> &GetOrCreateOffsetCache(void *&offsetCache,
|
||||
llvm::MemoryBuffer *buffer) {
|
||||
if (offsetCache)
|
||||
return *static_cast<std::vector<T> *>(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<T>();
|
||||
size_t sz = buffer->getBufferSize();
|
||||
assert(sz <= std::numeric_limits<T>::max());
|
||||
llvm::StringRef s = buffer->getBuffer();
|
||||
for (size_t n = 0; n < sz; ++n) {
|
||||
if (s[n] == '\n')
|
||||
offsets->push_back(static_cast<T>(n));
|
||||
}
|
||||
// template <typename T>
|
||||
// static std::vector<T> &GetOrCreateOffsetCache(void *&offsetCache,
|
||||
// llvm::MemoryBuffer *buffer) {
|
||||
// if (offsetCache)
|
||||
// return *static_cast<std::vector<T> *>(offsetCache);
|
||||
|
||||
offsetCache = offsets;
|
||||
return *offsets;
|
||||
}
|
||||
// // Lazily fill in the offset cache.
|
||||
// auto *offsets = new std::vector<T>();
|
||||
// size_t sz = buffer->getBufferSize();
|
||||
// assert(sz <= std::numeric_limits<T>::max());
|
||||
// llvm::StringRef s = buffer->getBuffer();
|
||||
// for (size_t n = 0; n < sz; ++n) {
|
||||
// if (s[n] == '\n')
|
||||
// offsets->push_back(static_cast<T>(n));
|
||||
// }
|
||||
|
||||
template <typename T>
|
||||
unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *ptr) const {
|
||||
std::vector<T> &offsets =
|
||||
GetOrCreateOffsetCache<T>(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<size_t>(ptrDiff) <= std::numeric_limits<T>::max());
|
||||
T ptrOffset = static_cast<T>(ptrDiff);
|
||||
// template <typename T>
|
||||
// unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *ptr)
|
||||
// const {
|
||||
// std::vector<T> &offsets =
|
||||
// GetOrCreateOffsetCache<T>(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<size_t>(ptrDiff) <= std::numeric_limits<T>::max());
|
||||
// T ptrOffset = static_cast<T>(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<uint8_t>::max())
|
||||
return getLineNumberSpecialized<uint8_t>(ptr);
|
||||
else if (sz <= std::numeric_limits<uint16_t>::max())
|
||||
return getLineNumberSpecialized<uint16_t>(ptr);
|
||||
else if (sz <= std::numeric_limits<uint32_t>::max())
|
||||
return getLineNumberSpecialized<uint32_t>(ptr);
|
||||
else
|
||||
return getLineNumberSpecialized<uint64_t>(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 <typename T>
|
||||
const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(
|
||||
unsigned lineNo) const {
|
||||
std::vector<T> &offsets =
|
||||
GetOrCreateOffsetCache<T>(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<uint8_t>::max())
|
||||
// return getLineNumberSpecialized<uint8_t>(ptr);
|
||||
// else if (sz <= std::numeric_limits<uint16_t>::max())
|
||||
// return getLineNumberSpecialized<uint16_t>(ptr);
|
||||
// else if (sz <= std::numeric_limits<uint32_t>::max())
|
||||
// return getLineNumberSpecialized<uint32_t>(ptr);
|
||||
// else
|
||||
// return getLineNumberSpecialized<uint64_t>(ptr);
|
||||
// }
|
||||
|
||||
// We start counting line and column numbers from 1.
|
||||
if (lineNo != 0)
|
||||
--lineNo;
|
||||
// template <typename T>
|
||||
// const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(
|
||||
// unsigned lineNo) const {
|
||||
// std::vector<T> &offsets =
|
||||
// GetOrCreateOffsetCache<T>(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<uint8_t>::max())
|
||||
return getPointerForLineNumberSpecialized<uint8_t>(lineNo);
|
||||
else if (sz <= std::numeric_limits<uint16_t>::max())
|
||||
return getPointerForLineNumberSpecialized<uint16_t>(lineNo);
|
||||
else if (sz <= std::numeric_limits<uint32_t>::max())
|
||||
return getPointerForLineNumberSpecialized<uint32_t>(lineNo);
|
||||
else
|
||||
return getPointerForLineNumberSpecialized<uint64_t>(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<uint8_t>::max())
|
||||
// return getPointerForLineNumberSpecialized<uint8_t>(lineNo);
|
||||
// else if (sz <= std::numeric_limits<uint16_t>::max())
|
||||
// return getPointerForLineNumberSpecialized<uint16_t>(lineNo);
|
||||
// else if (sz <= std::numeric_limits<uint32_t>::max())
|
||||
// return getPointerForLineNumberSpecialized<uint32_t>(lineNo);
|
||||
// else
|
||||
// return getPointerForLineNumberSpecialized<uint64_t>(lineNo);
|
||||
// }
|
||||
|
||||
SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&other)
|
||||
: buffer(std::move(other.buffer)), offsetCache(other.offsetCache),
|
||||
|
@ -245,190 +260,195 @@ SourceMgr::SrcBuffer::~SrcBuffer() {
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned>
|
||||
SourceMgr::getLineAndColumn(llvm::SMLoc loc, unsigned bufferID) const {
|
||||
if (!bufferID)
|
||||
bufferID = FindBufferContainingLoc(loc);
|
||||
assert(bufferID && "Invalid location!");
|
||||
// std::pair<unsigned, unsigned>
|
||||
// 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<llvm::SMRange> ranges,
|
||||
llvm::ArrayRef<llvm::SMFixIt> fixIts) const {
|
||||
// First thing to do: find the current buffer containing the specified
|
||||
// location to pull out the source line.
|
||||
llvm::SmallVector<std::pair<unsigned, unsigned>, 4> colRanges;
|
||||
std::pair<unsigned, unsigned> lineAndCol;
|
||||
llvm::StringRef bufferID = "<unknown>";
|
||||
llvm::StringRef lineStr;
|
||||
// SMDiagnostic SourceMgr::GetMessage(llvm::SMLoc loc, SourceMgr::DiagKind kind,
|
||||
// const llvm::Twine &msg,
|
||||
// llvm::ArrayRef<llvm::SMRange> ranges,
|
||||
// llvm::ArrayRef<llvm::SMFixIt> fixIts)
|
||||
// const {
|
||||
// // First thing to do: find the current buffer containing the specified
|
||||
// // location to pull out the source line.
|
||||
// llvm::SmallVector<std::pair<unsigned, unsigned>, 4> colRanges;
|
||||
// std::pair<unsigned, unsigned> lineAndCol;
|
||||
// llvm::StringRef bufferID = "<unknown>";
|
||||
// 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<llvm::SMRange> ranges,
|
||||
llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges,
|
||||
// llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges,
|
||||
llvm::ArrayRef<llvm::SMFixIt> 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<llvm::SMRange> ranges,
|
||||
// llvm::ArrayRef<llvm::SMFixIt> fixIts,
|
||||
// bool showColors) const {
|
||||
// PrintMessage(llvm::errs(), loc, kind, msg, ranges, fixIts, showColors);
|
||||
// }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SMDiagnostic Implementation
|
||||
|
|
Loading…
Reference in New Issue