diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2023-08-26 01:42:34 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-25 10:42:34 -0700 |
| commit | ef4c9f1f1c297f1a33be95795a7a7561e0cc3bde (patch) | |
| tree | 9ea81689432040905772aeec447adad88f212e01 /source/slang/slang-parser.cpp | |
| parent | 036abc85ba1db9c8c06289f0a0492e9a95a228b9 (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.cpp | 120 |
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); } |
