From ef4c9f1f1c297f1a33be95795a7a7561e0cc3bde Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Sat, 26 Aug 2023 01:42:34 +0800 Subject: 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 --- source/slang/slang-parser.cpp | 120 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'source/slang/slang-parser.cpp') 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 #include +#include #include "slang-compiler.h" #include "slang-lookup.h" @@ -6147,6 +6148,120 @@ namespace Slang } } + static std::optional parseSPIRVAsmOperand(Parser* parser) + { + const auto slangIdentOperand = [&](auto flavor){ + const auto tok = parser->ReadToken(TokenType::Identifier); + + VarExpr* varExpr = parser->astBuilder->create(); + 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 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(); + + 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); } -- cgit v1.2.3