summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-check-expr.cpp62
-rw-r--r--source/slang/slang-diagnostic-defs.h12
2 files changed, 73 insertions, 1 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 7cb0ede2d..83b668a33 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -5311,6 +5311,10 @@ Expr* SemanticsExprVisitor::visitSPIRVAsmExpr(SPIRVAsmExpr* expr)
// We will iterate over all the operands in all the insts and check
// them
bool failed = false;
+
+ // Track %id's that have been defined in this asm block.
+ HashSet<Name*> definedIds;
+
for (auto& inst : expr->insts)
{
// It's not automatically a failure to not have info, we just won't
@@ -5327,6 +5331,52 @@ Expr* SemanticsExprVisitor::visitSPIRVAsmExpr(SPIRVAsmExpr* expr)
0);
continue;
}
+ int resultIdIndex = -1;
+ if (opInfo)
+ {
+ resultIdIndex = opInfo->resultIdIndex;
+ }
+ else if (inst.opcode.flavor == SPIRVAsmOperand::TruncateMarker)
+ {
+ // If this is __truncate, register the result id in the third operand.
+ resultIdIndex = 1;
+ }
+ else
+ {
+ // If there is no opInfo, just register all Ids as defined.
+ for (auto& operand : inst.operands)
+ {
+ if (operand.flavor == SPIRVAsmOperand::Id)
+ {
+ definedIds.add(operand.token.getName());
+ }
+ }
+ }
+
+ // Register result ID.
+ if (resultIdIndex != -1)
+ {
+ if (inst.operands.getCount() <= resultIdIndex)
+ {
+ failed = true;
+ getSink()->diagnose(
+ inst.opcode.token,
+ Diagnostics::spirvInstructionWithNotEnoughOperands,
+ inst.opcode.token);
+ continue;
+ }
+ auto& resultIdOperand = inst.operands[resultIdIndex];
+
+ if (!definedIds.add(resultIdOperand.token.getName()))
+ {
+ failed = true;
+ getSink()->diagnose(
+ inst.opcode.token,
+ Diagnostics::spirvIdRedefinition,
+ inst.opcode.token);
+ continue;
+ }
+ }
const bool isLast = &inst == &expr->insts.getLast();
for (Index operandIndex = 0; operandIndex < inst.operands.getCount(); ++operandIndex)
@@ -5438,6 +5488,18 @@ Expr* SemanticsExprVisitor::visitSPIRVAsmExpr(SPIRVAsmExpr* expr)
}
operand.knownValue = builtinVarKind.value();
}
+ else if (operand.flavor == SPIRVAsmOperand::Id)
+ {
+ if (!definedIds.contains(operand.token.getName()))
+ {
+ failed = true;
+ getSink()->diagnose(
+ operand.token,
+ Diagnostics::spirvUndefinedId,
+ operand.token);
+ return;
+ }
+ }
if (operand.bitwiseOrWith.getCount() &&
operand.flavor != SPIRVAsmOperand::Literal &&
operand.flavor != SPIRVAsmOperand::NamedValue)
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index fde04b09d..9d08d5b73 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -541,7 +541,17 @@ DIAGNOSTIC(
Error,
spirvInvalidTruncate,
"__truncate has been given a source smaller than its target")
-
+DIAGNOSTIC(29112, Error, spirvInstructionWithNotEnoughOperands, "not enough operands for $0")
+DIAGNOSTIC(
+ 29113,
+ Error,
+ spirvIdRedefinition,
+ "SPIRV id '%$0' is already defined in the current assembly block")
+DIAGNOSTIC(
+ 29114,
+ Error,
+ spirvUndefinedId,
+ "SPIRV id '%$0' is not defined in the current assembly block location")
//
// 3xxxx - Semantic analysis
//