summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/check.cpp42
-rw-r--r--source/slang/lower.cpp35
-rw-r--r--source/slang/parser.cpp65
-rw-r--r--source/slang/slang-stdlib.cpp2
-rw-r--r--source/slang/stmt-defs.h10
-rw-r--r--tests/cross-compile/compile-time-loop.slang14
-rw-r--r--tests/cross-compile/compile-time-loop.slang.glsl33
-rw-r--r--tools/glslang/glslang.cpp2
8 files changed, 201 insertions, 2 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 1c1c6d5d3..26d28d495 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -1735,6 +1735,48 @@ namespace Slang
PopOuterStmt(stmt);
}
+
+ RefPtr<ExpressionSyntaxNode> checkExpressionAndExpectIntegerConstant(RefPtr<ExpressionSyntaxNode> expr, RefPtr<IntVal>* outIntVal)
+ {
+ expr = CheckExpr(expr);
+ auto intVal = CheckIntegerConstantExpression(expr);
+ if (outIntVal)
+ *outIntVal = intVal;
+ return expr;
+ }
+
+ void visitCompileTimeForStmt(CompileTimeForStmt* stmt)
+ {
+ PushOuterStmt(stmt);
+
+ stmt->varDecl->Type.type = ExpressionType::GetInt();
+ addModifier(stmt->varDecl, new ConstModifier());
+
+ RefPtr<IntVal> rangeBeginVal;
+ RefPtr<IntVal> rangeEndVal;
+
+ if (stmt->rangeBeginExpr)
+ {
+ stmt->rangeBeginExpr = checkExpressionAndExpectIntegerConstant(stmt->rangeBeginExpr, &rangeBeginVal);
+ }
+ else
+ {
+ RefPtr<ConstantIntVal> rangeBeginConst = new ConstantIntVal();
+ rangeBeginConst->value = 0;
+ rangeBeginVal = rangeBeginConst;
+ }
+
+ stmt->rangeEndExpr = checkExpressionAndExpectIntegerConstant(stmt->rangeEndExpr, &rangeEndVal);
+
+ stmt->rangeBeginVal = rangeBeginVal;
+ stmt->rangeEndVal = rangeEndVal;
+
+ checkStmt(stmt->body);
+
+
+ PopOuterStmt(stmt);
+ }
+
void visitSwitchStmt(SwitchStmt* stmt)
{
PushOuterStmt(stmt);
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index bbbfe724b..127ef75ca 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -1628,6 +1628,41 @@ struct LoweringVisitor
lowerForStmtCommon(new UnscopedForStmt(), stmt);
}
+ void visitCompileTimeForStmt(CompileTimeForStmt* stmt)
+ {
+ // We can either lower this here, so that emit logic doesn't have to deal with it,
+ // or else just translate it and then let emit deal with it.
+ //
+ // The right answer is really to lower it here, I guess.
+
+ auto rangeBeginVal = GetIntVal(stmt->rangeBeginVal);
+ auto rangeEndVal = GetIntVal(stmt->rangeEndVal);
+
+ if (rangeBeginVal >= rangeEndVal)
+ return;
+
+ auto varDecl = stmt->varDecl;
+
+ auto varType = lowerType(varDecl->Type);
+
+ for (IntegerLiteralValue ii = rangeBeginVal; ii < rangeEndVal; ++ii)
+ {
+ RefPtr<ConstantExpressionSyntaxNode> constExpr = new ConstantExpressionSyntaxNode();
+ constExpr->Type.type = varType.type;
+ constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Int;
+ constExpr->integerValue = ii;
+
+ RefPtr<VaryingTupleVarDecl> loweredVarDecl = new VaryingTupleVarDecl();
+ loweredVarDecl->Position = varDecl->Position;
+ loweredVarDecl->Type = varType;
+ loweredVarDecl->Expr = constExpr;
+
+ shared->loweredDecls[varDecl] = loweredVarDecl;
+
+ lowerStmtImpl(stmt->body);
+ }
+ }
+
void visitWhileStatementSyntaxNode(WhileStatementSyntaxNode* stmt)
{
RefPtr<WhileStatementSyntaxNode> loweredStmt = new WhileStatementSyntaxNode();
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index 1ad0c6b94..b821555a9 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -2555,6 +2555,67 @@ namespace Slang
return isTypeName(parser, name);
}
+ RefPtr<StatementSyntaxNode> parseCompileTimeForStmt(
+ Parser* parser)
+ {
+ RefPtr<ScopeDecl> scopeDecl = new ScopeDecl();
+ RefPtr<CompileTimeForStmt> stmt = new CompileTimeForStmt();
+ stmt->scopeDecl = scopeDecl;
+
+
+ parser->ReadToken("for");
+ parser->ReadToken(TokenType::LParent);
+
+ Token varNameToken = parser->ReadToken(TokenType::Identifier);
+ RefPtr<Variable> varDecl = new Variable();
+ varDecl->Name = varNameToken;
+ varDecl->Position = varNameToken.Position;
+
+ stmt->varDecl = varDecl;
+
+ parser->ReadToken("in");
+ parser->ReadToken("Range");
+ parser->ReadToken(TokenType::LParent);
+
+ RefPtr<ExpressionSyntaxNode> rangeBeginExpr;
+ RefPtr<ExpressionSyntaxNode> rangeEndExpr = parser->ParseArgExpr();
+ if (AdvanceIf(parser, TokenType::Comma))
+ {
+ rangeBeginExpr = rangeEndExpr;
+ rangeEndExpr = parser->ParseArgExpr();
+ }
+
+ stmt->rangeBeginExpr = rangeBeginExpr;
+ stmt->rangeEndExpr = rangeEndExpr;
+
+ parser->ReadToken(TokenType::RParent);
+ parser->ReadToken(TokenType::RParent);
+
+ parser->PushScope(scopeDecl);
+ AddMember(parser->currentScope, varDecl);
+
+ stmt->body = parser->ParseStatement();
+
+ parser->PopScope();
+
+ return stmt;
+ }
+
+ RefPtr<StatementSyntaxNode> parseCompileTimeStmt(
+ Parser* parser)
+ {
+ parser->ReadToken(TokenType::Dollar);
+ if (parser->LookAheadToken("for"))
+ {
+ return parseCompileTimeForStmt(parser);
+ }
+ else
+ {
+ Unexpected(parser);
+ return nullptr;
+ }
+ }
+
RefPtr<StatementSyntaxNode> Parser::ParseStatement()
{
auto modifiers = ParseModifiers(this);
@@ -2591,6 +2652,10 @@ namespace Slang
statement = ParseCaseStmt(this);
else if (LookAheadToken("default"))
statement = ParseDefaultStmt(this);
+ else if (LookAheadToken(TokenType::Dollar))
+ {
+ statement = parseCompileTimeStmt(this);
+ }
else if (LookAheadToken(TokenType::Identifier))
{
// We might be looking at a local declaration, or an
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index 3062112c6..b26fc8a8e 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -1603,7 +1603,7 @@ namespace Slang
if( baseShape != TextureType::ShapeCube )
{
- sb << "__intrinsic(glsl, \"textureOffset($p, $1)\")\n";
+ sb << "__intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n";
sb << "__intrinsic\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
diff --git a/source/slang/stmt-defs.h b/source/slang/stmt-defs.h
index 9dea40fbf..80e3cd60d 100644
--- a/source/slang/stmt-defs.h
+++ b/source/slang/stmt-defs.h
@@ -96,6 +96,16 @@ SYNTAX_CLASS(DoWhileStatementSyntaxNode, LoopStmt)
SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Predicate)
END_SYNTAX_CLASS()
+// A compile-time, range-based `for` loop, which will not appear in the output code
+SYNTAX_CLASS(CompileTimeForStmt, ScopeStmt)
+ SYNTAX_FIELD(RefPtr<Variable>, varDecl)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, rangeBeginExpr)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, rangeEndExpr)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, body)
+ SYNTAX_FIELD(RefPtr<IntVal>, rangeBeginVal)
+ SYNTAX_FIELD(RefPtr<IntVal>, rangeEndVal)
+END_SYNTAX_CLASS()
+
// The case of child statements that do control flow relative
// to their parent statement.
ABSTRACT_SYNTAX_CLASS(JumpStmt, ChildStmt)
diff --git a/tests/cross-compile/compile-time-loop.slang b/tests/cross-compile/compile-time-loop.slang
new file mode 100644
index 000000000..aae35f09e
--- /dev/null
+++ b/tests/cross-compile/compile-time-loop.slang
@@ -0,0 +1,14 @@
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+
+Texture2D t;
+SamplerState s;
+
+float4 main(float2 uv) : SV_Target
+{
+ float4 result = 0;
+ $for(i in Range(0,5))
+ {
+ result += t.Sample(s, uv, int2(i - 2, 0));
+ }
+ return result;
+}
diff --git a/tests/cross-compile/compile-time-loop.slang.glsl b/tests/cross-compile/compile-time-loop.slang.glsl
new file mode 100644
index 000000000..a1f87be65
--- /dev/null
+++ b/tests/cross-compile/compile-time-loop.slang.glsl
@@ -0,0 +1,33 @@
+//TEST_IGNORE_FILE:
+
+layout(binding = 0)
+uniform texture2D t;
+
+layout(binding = 1)
+uniform sampler s;
+
+vec4 main_(vec2 uv)
+{
+ vec4 result = vec4(0);
+
+ result += textureOffset(sampler2D(t,s), uv, ivec2(0 - 2, 0));
+ result += textureOffset(sampler2D(t,s), uv, ivec2(1 - 2, 0));
+ result += textureOffset(sampler2D(t,s), uv, ivec2(2 - 2, 0));
+ result += textureOffset(sampler2D(t,s), uv, ivec2(3 - 2, 0));
+ result += textureOffset(sampler2D(t,s), uv, ivec2(4 - 2, 0));
+
+ return result;
+}
+
+layout(location = 0)
+in vec2 SLANG_in_uv;
+
+layout(location = 0)
+out vec4 SLANG_out_main_result;
+
+void main()
+{
+ vec2 uv = SLANG_in_uv;
+ vec4 main_result = main_(uv);
+ SLANG_out_main_result = main_result;
+} \ No newline at end of file
diff --git a/tools/glslang/glslang.cpp b/tools/glslang/glslang.cpp
index 2890a98ad..19c130329 100644
--- a/tools/glslang/glslang.cpp
+++ b/tools/glslang/glslang.cpp
@@ -38,7 +38,7 @@
static TBuiltInResource gResources =
{
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
- UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
+ UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,-UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,