From 3156226233133f5da9dba15c63ca560b4794b831 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 15 Jul 2021 10:36:50 -0400 Subject: verilog: save and restore overwritten macro arguments --- frontends/verilog/preproc.cc | 34 ++++++++++++++++++++++++++++++---- frontends/verilog/preproc.h | 1 + 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'frontends/verilog') diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 4b9ebe0aa..17f567587 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -36,6 +36,7 @@ #include "verilog_frontend.h" #include "kernel/log.h" #include +#include #include #include #include @@ -334,6 +335,11 @@ define_map_t::add(const std::string &name, const std::string &txt, const arg_map defines[name] = std::unique_ptr(new define_body_t(txt, args)); } +void define_map_t::add(const std::string &name, const define_body_t &body) +{ + defines[name] = std::unique_ptr(new define_body_t(body)); +} + void define_map_t::merge(const define_map_t &map) { for (const auto &pr : map.defines) { @@ -440,7 +446,17 @@ static bool read_argument(std::string &dest) } } -static bool try_expand_macro(define_map_t &defines, std::string &tok) +using macro_arg_stack_t = std::stack>; + +static void restore_macro_arg(define_map_t &defines, macro_arg_stack_t ¯o_arg_stack) +{ + log_assert(!macro_arg_stack.empty()); + auto &overwritten_arg = macro_arg_stack.top(); + defines.add(overwritten_arg.first, overwritten_arg.second); + macro_arg_stack.pop(); +} + +static bool try_expand_macro(define_map_t &defines, macro_arg_stack_t ¯o_arg_stack, std::string &tok) { if (tok == "`\"") { std::string literal("\""); @@ -450,7 +466,7 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok) if (ntok == "`\"") { insert_input(literal+"\""); return true; - } else if (!try_expand_macro(defines, ntok)) { + } else if (!try_expand_macro(defines, macro_arg_stack, ntok)) { literal += ntok; } } @@ -495,6 +511,10 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok) args.push_back(arg); } for (const auto &pr : body->args.get_vals(name, args)) { + if (const define_body_t *existing = defines.find(pr.first)) { + macro_arg_stack.push({pr.first, *existing}); + insert_input("`__restore_macro_arg "); + } defines.add(pr.first, pr.second); } } else { @@ -725,6 +745,7 @@ frontend_verilog_preproc(std::istream &f, defines.merge(pre_defines); defines.merge(global_defines_cache); + macro_arg_stack_t macro_arg_stack; std::vector filename_stack; // We are inside pass_level levels of satisfied ifdefs, and then within // fail_level levels of unsatisfied ifdefs. The unsatisfied ones are @@ -828,7 +849,7 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`include") { skip_spaces(); std::string fn = next_token(true); - while (try_expand_macro(defines, fn)) { + while (try_expand_macro(defines, macro_arg_stack, fn)) { fn = next_token(); } while (1) { @@ -935,7 +956,12 @@ frontend_verilog_preproc(std::istream &f, continue; } - if (try_expand_macro(defines, tok)) + if (tok == "`__restore_macro_arg") { + restore_macro_arg(defines, macro_arg_stack); + continue; + } + + if (try_expand_macro(defines, macro_arg_stack, tok)) continue; output_code.push_back(tok); diff --git a/frontends/verilog/preproc.h b/frontends/verilog/preproc.h index e1048156c..330855a92 100644 --- a/frontends/verilog/preproc.h +++ b/frontends/verilog/preproc.h @@ -42,6 +42,7 @@ struct define_map_t // Add a definition, overwriting any existing definition for name. void add(const std::string &name, const std::string &txt, const arg_map_t *args = nullptr); + void add(const std::string &name, const define_body_t &body); // Merge in another map of definitions (which take precedence // over anything currently defined). -- cgit v1.2.3