diff options
author | Zachary Snow <zach@zachjs.com> | 2021-02-25 15:53:55 -0500 |
---|---|---|
committer | Zachary Snow <zachary.j.snow@gmail.com> | 2021-03-01 12:28:33 -0500 |
commit | 1ec5994100510d6fb9e18ff7234ede496f831a51 (patch) | |
tree | 77c8403f0ece00ad1b42e2e91f86befe0f736cac /frontends | |
parent | b6904a8e5344fcd01c1a0feea281cd7d7bf0f210 (diff) | |
download | yosys-1ec5994100510d6fb9e18ff7234ede496f831a51.tar.gz yosys-1ec5994100510d6fb9e18ff7234ede496f831a51.tar.bz2 yosys-1ec5994100510d6fb9e18ff7234ede496f831a51.zip |
verilog: fix handling of nested ifdef directives
- track depth so we know whether to consider higher-level elsifs
- error on unmatched endif/elsif/else
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/verilog/preproc.cc | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index de707593f..84966e501 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -727,7 +727,8 @@ frontend_verilog_preproc(std::istream &f, std::vector<std::string> filename_stack; int ifdef_fail_level = 0; - bool in_elseif = false; + int ifdef_pass_level = 0; + bool ifdef_already_satisfied = false; output_code.clear(); input_buffer.clear(); @@ -743,42 +744,68 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`endif") { if (ifdef_fail_level > 0) ifdef_fail_level--; - if (ifdef_fail_level == 0) - in_elseif = false; + else if (ifdef_pass_level > 0) + ifdef_already_satisfied = --ifdef_pass_level; + else + log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); continue; } if (tok == "`else") { - if (ifdef_fail_level == 0) + if (ifdef_fail_level == 0) { + if (ifdef_pass_level == 0) + log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); + log_assert(ifdef_already_satisfied); ifdef_fail_level = 1; - else if (ifdef_fail_level == 1 && !in_elseif) + } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) { ifdef_fail_level = 0; + ifdef_pass_level++; + ifdef_already_satisfied = true; + } continue; } if (tok == "`elsif") { skip_spaces(); std::string name = next_token(true); - if (ifdef_fail_level == 0) - ifdef_fail_level = 1, in_elseif = true; - else if (ifdef_fail_level == 1 && defines.find(name)) - ifdef_fail_level = 0, in_elseif = true; + if (ifdef_fail_level == 0) { + if (ifdef_pass_level == 0) + log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); + log_assert(ifdef_already_satisfied); + ifdef_fail_level = 1; + } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) { + ifdef_fail_level = 0; + ifdef_pass_level++; + ifdef_already_satisfied = true; + } continue; } if (tok == "`ifdef") { skip_spaces(); std::string name = next_token(true); - if (ifdef_fail_level > 0 || !defines.find(name)) + if (ifdef_fail_level > 0 || !defines.find(name)) { ifdef_fail_level++; + } else { + ifdef_pass_level++; + ifdef_already_satisfied = true; + } + if (ifdef_fail_level == 1) + ifdef_already_satisfied = false; continue; } if (tok == "`ifndef") { skip_spaces(); std::string name = next_token(true); - if (ifdef_fail_level > 0 || defines.find(name)) + if (ifdef_fail_level > 0 || defines.find(name)) { ifdef_fail_level++; + } else { + ifdef_pass_level++; + ifdef_already_satisfied = true; + } + if (ifdef_fail_level == 1) + ifdef_already_satisfied = false; continue; } |