summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-parser.cpp
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-08-26 01:42:34 +0800
committerGitHub <noreply@github.com>2023-08-25 10:42:34 -0700
commitef4c9f1f1c297f1a33be95795a7a7561e0cc3bde (patch)
tree9ea81689432040905772aeec447adad88f212e01 /source/slang/slang-parser.cpp
parent036abc85ba1db9c8c06289f0a0492e9a95a228b9 (diff)
Initial version of spirv_asm block (#3151)
* Initial version of spirv_asm block * Correct indentation of parent instruction dumping * neater dumping for spirv_asm instructions * Add $$ DollarDollar token * Allow passing addresses to spirv_asm blocks * spirv OpUndef * String literals in spirv asm * OpName for spirv_asm ids * Correct failure in lower spirv_asm * correct position for spirv_asm idents * comment correct * several more tests for spirv_asm blocks * Fill out some unimplemented functions for spirv_asm expressions --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source/slang/slang-parser.cpp')
-rw-r--r--source/slang/slang-parser.cpp120
1 files changed, 119 insertions, 1 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index fabf1ffb4..442ddbce6 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -2,6 +2,7 @@
#include <assert.h>
#include <float.h>
+#include <optional>
#include "slang-compiler.h"
#include "slang-lookup.h"
@@ -6147,6 +6148,120 @@ namespace Slang
}
}
+ static std::optional<SPIRVAsmOperand> parseSPIRVAsmOperand(Parser* parser)
+ {
+ const auto slangIdentOperand = [&](auto flavor){
+ const auto tok = parser->ReadToken(TokenType::Identifier);
+
+ VarExpr* varExpr = parser->astBuilder->create<VarExpr>();
+ varExpr->scope = parser->currentScope;
+ varExpr->loc = tok.getLoc();
+ varExpr->name = tok.getName();
+ return SPIRVAsmOperand{flavor, tok, varExpr};
+ };
+
+ // A regular identifier
+ if(parser->LookAheadToken(TokenType::Identifier))
+ {
+ return SPIRVAsmOperand{SPIRVAsmOperand::NamedValue, parser->ReadToken()};
+ }
+ // A literal integer or string
+ else if(parser->LookAheadToken(TokenType::IntegerLiteral)
+ || parser->LookAheadToken(TokenType::StringLiteral))
+ {
+ return SPIRVAsmOperand{SPIRVAsmOperand::Literal, parser->ReadToken()};
+ }
+ // A %foo id
+ else if(AdvanceIf(parser, TokenType::OpMod))
+ {
+ if(parser->LookAheadToken(TokenType::IntegerLiteral)
+ || parser->LookAheadToken(TokenType::Identifier))
+ {
+ return SPIRVAsmOperand{SPIRVAsmOperand::Id, parser->ReadToken()};
+ }
+ }
+ // A &foo variable reference (for the address of foo)
+ else if(AdvanceIf(parser, TokenType::OpBitAnd))
+ {
+ return slangIdentOperand(SPIRVAsmOperand::SlangValueAddr);
+ }
+ // A $foo variable
+ else if(AdvanceIf(parser, TokenType::Dollar))
+ {
+ return slangIdentOperand(SPIRVAsmOperand::SlangValue);
+ }
+ // A $$foo type
+ else if(AdvanceIf(parser, TokenType::DollarDollar))
+ {
+ return slangIdentOperand(SPIRVAsmOperand::SlangType);
+ }
+
+ Unexpected(parser);
+ return std::nullopt;
+ }
+
+ static std::optional<SPIRVAsmInst> parseSPIRVAsmInst(Parser* parser)
+ {
+ SPIRVAsmInst ret;
+
+ const auto resultOrOpcode = parseSPIRVAsmOperand(parser);
+ if(!resultOrOpcode)
+ return std::nullopt;
+
+ // We can enable this when we have a way of determining the index of
+ // the result id operand to each instruction, otherwise we don't know
+ // at which position in the operand list to insert this.
+#if 0
+ if(AdvanceIf(parser, TokenType::OpEql))
+ {
+ const auto opcode = parseSPIRVAsmOperand(parser);
+ if(!opcode)
+ return std::nullopt;
+ ret.opcode = *opcode;
+ ret.operands.insert(???, *resultOrOpcode);
+ }
+ else
+#endif
+ {
+ ret.opcode = *resultOrOpcode;
+ }
+
+ // TODO: diagnose wrong opcode flavor here
+
+ while(!(parser->LookAheadToken(TokenType::RBrace)
+ || parser->LookAheadToken(TokenType::Semicolon)))
+ {
+ if(const auto operand = parseSPIRVAsmOperand(parser))
+ ret.operands.add(*operand);
+ else
+ return std::nullopt;
+ }
+
+ return ret;
+ }
+
+ static Expr* parseSPIRVAsmExpr(Parser* parser)
+ {
+ SPIRVAsmExpr* asmExpr = parser->astBuilder->create<SPIRVAsmExpr>();
+
+ parser->ReadToken(TokenType::LBrace);
+ while(!parser->tokenReader.isAtEnd())
+ {
+ if(parser->LookAheadToken(TokenType::RBrace))
+ break;
+ if(const auto inst = parseSPIRVAsmInst(parser))
+ asmExpr->insts.add(*inst);
+ else
+ return nullptr;
+ if(parser->LookAheadToken(TokenType::RBrace))
+ break;
+ parser->ReadToken(TokenType::Semicolon);
+ }
+ parser->ReadToken(TokenType::RBrace);
+
+ return asmExpr;
+ }
+
static Expr* parsePrefixExpr(Parser* parser)
{
auto tokenType = peekTokenType(parser);
@@ -6179,7 +6294,10 @@ namespace Slang
}
return newExpr;
}
-
+ else if (AdvanceIf(parser, "spirv_asm"))
+ {
+ return parseSPIRVAsmExpr(parser);
+ }
return parsePostfixExpr(parser);
}