3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-27 10:55:51 +00:00

verilog: fix handling of nested ifdef directives

- track depth so we know whether to consider higher-level elsifs
- error on unmatched endif/elsif/else
This commit is contained in:
Zachary Snow 2021-02-25 15:53:55 -05:00 committed by Zachary Snow
parent b6904a8e53
commit 1ec5994100
8 changed files with 197 additions and 11 deletions

View file

@ -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;
}