Skip to content

Commit

Permalink
Add optional compiler directives from annex E
Browse files Browse the repository at this point in the history
Also fix error reporting locations for missing expected tokens in the preprocessor
  • Loading branch information
MikePopoloski committed May 19, 2024
1 parent 9f02fd6 commit 2cb1283
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 14 deletions.
2 changes: 2 additions & 0 deletions include/slang/parsing/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ class SLANG_EXPORT Preprocessor {
Trivia handleEndKeywordsDirective(Token directive);
Trivia handleUnconnectedDriveDirective(Token directive);
Trivia handleNoUnconnectedDriveDirective(Token directive);
Trivia handleDefaultDecayTimeDirective(Token directive);
Trivia handleDefaultTriregStrengthDirective(Token directive);
Trivia createSimpleDirective(Token directive);
std::pair<Trivia, Trivia> handlePragmaDirective(Token directive);

Expand Down
9 changes: 8 additions & 1 deletion scripts/syntax.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2185,7 +2185,8 @@ SimpleDirective base=Directive multiKind=true

kindmap<SimpleDirective>
CellDefineDirective NoUnconnectedDriveDirective EndCellDefineDirective EndKeywordsDirective
ResetAllDirective UndefineAllDirective
ResetAllDirective UndefineAllDirective DelayModeDistributedDirective DelayModePathDirective
DelayModeUnitDirective DelayModeZeroDirective

IncludeDirective base=Directive
token fileName
Expand Down Expand Up @@ -2263,6 +2264,12 @@ token netType
UnconnectedDriveDirective base=Directive
token strength

DefaultDecayTimeDirective base=Directive
token time

DefaultTriregStrengthDirective base=Directive
token strength

LineDirective base=Directive
token lineNumber
token fileName
Expand Down
8 changes: 7 additions & 1 deletion source/parsing/LexerFacts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ const static flat_hash_map<std::string_view, SyntaxKind> directiveTable = {
{ "timescale", SyntaxKind::TimeScaleDirective },
{ "unconnected_drive", SyntaxKind::UnconnectedDriveDirective },
{ "undef", SyntaxKind::UndefDirective },
{ "undefineall", SyntaxKind::UndefineAllDirective }
{ "undefineall", SyntaxKind::UndefineAllDirective },
{ "default_decay_time", SyntaxKind::DefaultDecayTimeDirective },
{ "default_trireg_strength", SyntaxKind::DefaultTriregStrengthDirective },
{ "delay_mode_distributed", SyntaxKind::DelayModeDistributedDirective },
{ "delay_mode_path", SyntaxKind::DelayModePathDirective },
{ "delay_mode_unit", SyntaxKind::DelayModeUnitDirective },
{ "delay_mode_zero", SyntaxKind::DelayModeZeroDirective }
};

const static flat_hash_map<std::string_view, KeywordVersion> keywordVersionTable = {
Expand Down
63 changes: 55 additions & 8 deletions source/parsing/Preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ Token Preprocessor::handleDirectives(Token token) {
// burn through any preprocessor directives we find and convert them to trivia
SmallVector<Trivia, 8> trivia;
while (true) {
lastConsumed = token;
switch (token.kind) {
case TokenKind::MacroQuote:
case TokenKind::MacroTripleQuote:
Expand All @@ -288,7 +287,8 @@ Token Preprocessor::handleDirectives(Token token) {
trivia.append_range(token.trivia());
return token.withTrivia(alloc, trivia.copy(alloc));
}
case TokenKind::Directive:
case TokenKind::Directive: {
auto savedLast = std::exchange(lastConsumed, token);
switch (token.directiveKind()) {
case SyntaxKind::IncludeDirective:
trivia.push_back(handleIncludeDirective(token));
Expand Down Expand Up @@ -355,15 +355,27 @@ Token Preprocessor::handleDirectives(Token token) {
case SyntaxKind::NoUnconnectedDriveDirective:
trivia.push_back(handleNoUnconnectedDriveDirective(token));
break;
case SyntaxKind::DefaultDecayTimeDirective:
trivia.push_back(handleDefaultDecayTimeDirective(token));
break;
case SyntaxKind::DefaultTriregStrengthDirective:
trivia.push_back(handleDefaultTriregStrengthDirective(token));
break;
case SyntaxKind::CellDefineDirective:
case SyntaxKind::EndCellDefineDirective:
// we don't do anything with celldefine directives
case SyntaxKind::DelayModeDistributedDirective:
case SyntaxKind::DelayModePathDirective:
case SyntaxKind::DelayModeUnitDirective:
case SyntaxKind::DelayModeZeroDirective:
// we don't do anything with these directives currently
trivia.push_back(createSimpleDirective(token));
break;
default:
SLANG_UNREACHABLE;
}
lastConsumed = savedLast;
break;
}
default:
trivia.append_range(token.trivia());
return token.withTrivia(alloc, trivia.copy(alloc));
Expand Down Expand Up @@ -912,8 +924,9 @@ Trivia Preprocessor::handleDefaultNetTypeDirective(Token directive) {
}

if (!netType) {
addDiag(diag::ExpectedNetType, peek().location());
netType = Token::createMissing(alloc, TokenKind::WireKeyword, peek().location());
auto loc = directive.location() + directive.rawText().length();
addDiag(diag::ExpectedNetType, loc);
netType = Token::createMissing(alloc, TokenKind::WireKeyword, loc);
}

auto result = alloc.emplace<DefaultNetTypeDirectiveSyntax>(directive, netType);
Expand Down Expand Up @@ -972,7 +985,7 @@ Trivia Preprocessor::handleEndKeywordsDirective(Token directive) {

std::pair<Trivia, Trivia> Preprocessor::handlePragmaDirective(Token directive) {
if (peek().kind != TokenKind::Identifier || !peek().isOnSameLine()) {
addDiag(diag::ExpectedPragmaName, directive.location());
addDiag(diag::ExpectedPragmaName, directive.location() + directive.rawText().length());
return {createSimpleDirective(directive), Trivia()};
}

Expand Down Expand Up @@ -1031,8 +1044,9 @@ Trivia Preprocessor::handleUnconnectedDriveDirective(Token directive) {
}

if (!strength) {
addDiag(diag::ExpectedDriveStrength, peek().location());
strength = Token::createMissing(alloc, TokenKind::Pull0Keyword, peek().location());
auto loc = directive.location() + directive.rawText().length();
addDiag(diag::ExpectedDriveStrength, loc);
strength = Token::createMissing(alloc, TokenKind::Pull0Keyword, loc);
}

auto result = alloc.emplace<UnconnectedDriveDirectiveSyntax>(directive, strength);
Expand All @@ -1045,6 +1059,39 @@ Trivia Preprocessor::handleNoUnconnectedDriveDirective(Token directive) {
return createSimpleDirective(directive);
}

Trivia Preprocessor::handleDefaultDecayTimeDirective(Token directive) {
checkOutsideDesignElement(directive);

Token time;
switch (peek().kind) {
case TokenKind::IntegerLiteral:
case TokenKind::RealLiteral:
time = consume();
break;
case TokenKind::Identifier:
if (peek().valueText() == "infinite")
time = consume();
break;
default:
break;
}

if (!time)
time = expect(TokenKind::IntegerLiteral);

auto result = alloc.emplace<DefaultDecayTimeDirectiveSyntax>(directive, time);
return Trivia(TriviaKind::Directive, result);
}

Trivia Preprocessor::handleDefaultTriregStrengthDirective(Token directive) {
checkOutsideDesignElement(directive);

auto strength = expect(TokenKind::IntegerLiteral);

auto result = alloc.emplace<DefaultTriregStrengthDirectiveSyntax>(directive, strength);
return Trivia(TriviaKind::Directive, result);
}

ConditionalDirectiveExpressionSyntax* Preprocessor::parseConditionalExpr() {
auto isBinaryOp = [](TokenKind kind) {
switch (kind) {
Expand Down
50 changes: 46 additions & 4 deletions tests/unittests/parsing/PreprocessorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1547,9 +1547,9 @@ TEST_CASE("Pragma expressions -- errors") {

std::string result = "\n" + reportGlobalDiags();
CHECK(result == R"(
source:2:1: error: expected pragma name
source:2:8: error: expected pragma name
`pragma
^
^
source:5:18: error: expected pragma expression
`pragma bar asdf=
^
Expand Down Expand Up @@ -1577,9 +1577,9 @@ source:16:18: error: expected pragma expression
source:16:9: warning: unknown pragma 'bar' [-Wunknown-pragma]
`pragma bar 'h 3e+2
^~~
source:17:1: error: expected pragma name
source:17:8: error: expected pragma name
`pragma /* asdf
^
^
source:20:15: error: expected pragma name
`pragma reset (asdf, asdf), foo
^~~~~~~~~~~~
Expand Down Expand Up @@ -2536,3 +2536,45 @@ TEST_CASE("Macro expansion with asterisks regress") {
CHECK(result == expected);
CHECK_DIAGNOSTICS_EMPTY;
}

TEST_CASE("Annex E optional directives") {
auto& text = R"(
`default_decay_time 100
`default_decay_time 1.0
`default_decay_time infinite
`default_decay_time
`default_trireg_strength 100
`delay_mode_distributed
`delay_mode_path
`delay_mode_unit
`delay_mode_zero
)";

preprocess(text);

REQUIRE(diagnostics.size() == 1);
CHECK(diagnostics[0].code == diag::ExpectedIntegerLiteral);
}

TEST_CASE("Locations for missing expected tokens in preprocessor") {
auto& text = R"(
`unconnected_drive
`resetall
`include
`resetall
)";

preprocess(text);

std::string result = "\n" + reportGlobalDiags();
CHECK(result == R"(
source:4:9: error: expected an include file name
`include
^
source:2:19: error: expected pull1 or pull0 strength
`unconnected_drive
^
)");
}

0 comments on commit 2cb1283

Please sign in to comment.