From 4e1ac7830b9294d7251fae8c004b446a1fde739b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 24 Jun 2025 22:14:30 +0200 Subject: [PATCH] fixup! ast, read_verilog: unify location types, reduce filename copying --- frontends/verilog/verilog_error.cc | 54 ++++++++++++++++ frontends/verilog/verilog_error.h | 25 ++++++++ frontends/verilog/verilog_location.h | 96 ++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 frontends/verilog/verilog_error.cc create mode 100644 frontends/verilog/verilog_error.h create mode 100644 frontends/verilog/verilog_location.h diff --git a/frontends/verilog/verilog_error.cc b/frontends/verilog/verilog_error.cc new file mode 100644 index 000000000..410a13580 --- /dev/null +++ b/frontends/verilog/verilog_error.cc @@ -0,0 +1,54 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * --- + * + */ + +#include "kernel/yosys_common.h" +#include "frontends/verilog/verilog_error.h" +#include "frontends/verilog/verilog_location.h" + +USING_YOSYS_NAMESPACE + +[[noreturn]] +static void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap) +{ + char buffer[1024]; + char *p = buffer; + p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); + p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); + YOSYS_NAMESPACE_PREFIX log_file_error(filename, begin_line, "%s", buffer); + exit(1); +} + +void VERILOG_FRONTEND::err_at_ast(AST::AstSrcLocType loc, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + verr_at(*loc.begin.filename, loc.begin.line, fmt, args); + va_end(args); +} + +[[noreturn]] +void VERILOG_FRONTEND::err_at_loc(location loc, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + verr_at(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line, fmt, args); +} + diff --git a/frontends/verilog/verilog_error.h b/frontends/verilog/verilog_error.h new file mode 100644 index 000000000..4cb65164b --- /dev/null +++ b/frontends/verilog/verilog_error.h @@ -0,0 +1,25 @@ +#ifndef VERILOG_ERROR_H +#define VERILOG_ERROR_H + +#include "kernel/yosys_common.h" +#include "frontends/ast/ast.h" +#include "frontends/verilog/verilog_location.h" + +#if ! defined(yyFlexLexerOnce) +#define yyFlexLexer frontend_verilog_yyFlexLexer +#include +#endif + +YOSYS_NAMESPACE_BEGIN + +namespace VERILOG_FRONTEND +{ + [[noreturn]] + void err_at_ast(AST::AstSrcLocType loc, char const *fmt, ...); + [[noreturn]] + void err_at_loc(location loc, char const *fmt, ...); +}; + +YOSYS_NAMESPACE_END + +#endif diff --git a/frontends/verilog/verilog_location.h b/frontends/verilog/verilog_location.h new file mode 100644 index 000000000..d2ef8e94c --- /dev/null +++ b/frontends/verilog/verilog_location.h @@ -0,0 +1,96 @@ +#ifndef VERILOG_LOCATION_H +#define VERILOG_LOCATION_H + +#include +#include +#include +#include + +/** + * Provide frontend-wide location tracking like what bison generates + * but using shared_ptr for filename + */ + +struct position { + std::shared_ptr filename; + int line; + int column; + + position(std::shared_ptr filename, int line = 1, int column = 1) + : filename(filename), line(line), column(column) {} + position() = default; + position(const position& other) = default; + position& operator=(const position& other) = default; + + void advance() { ++column; } + void columns(int count = 1) { + column += count; + } + + void lines(int count = 1) { + line += count; + column = 1; + } + std::string to_string() const { + std::ostringstream oss; + if (filename && !filename->empty()) { + oss << *filename << ":"; + } + oss << line << ":" << column; + return oss.str(); + } +}; + +struct location { + position begin; + position end; + + location() = default; + location(const position& b, const position& e) + : begin(b), end(e) {} + location(const location& other) = default; + location& operator=(const location& other) = default; + + void step() { begin = end; } + + void columns(int count = 1) { + end.columns(count); + } + + void lines(int count = 1) { + end.lines(count); + } + std::string to_string() const { + std::ostringstream oss; + bool same_file = (!begin.filename && !end.filename) || + (begin.filename && end.filename && + *begin.filename == *end.filename); + + if (same_file) { + if (begin.filename && !begin.filename->empty()) + oss << *begin.filename << ":"; + + if (begin.line == end.line) { + if (begin.column == end.column) { + oss << begin.line << ":" << begin.column; + } else { + oss << begin.line << ":" << begin.column + << "-" << end.column; + } + } else { + oss << begin.line << ":" << begin.column + << "-" << end.line << ":" << end.column; + } + } else { + oss << begin.to_string() << "-" << end.to_string(); + } + + return oss.str(); + } +}; + +static inline std::ostream& operator<<(std::ostream& os, const location& loc) { + return os << loc.to_string(); +} + +#endif