diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-11-17 07:09:58 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-17 07:09:58 -0800 |
| commit | 0298a0427bbfe19700169c4e239a1b9e91baa410 (patch) | |
| tree | 659dfa11e5bc687bf8baab2a7b9f39708922671e /source/slang | |
| parent | 0e3d9ba255b86c11521a951183d38bffae008559 (diff) | |
IR: support `CompileTimeForStmt` (#286)
This statement type is a bit of a hack, to support loops that *must* be unrolled.
The AST-to-AST pass handles them by cloning the AST for the loop body N times, and it was easy enough to do the same thing for the IR: emit the instructions for the body N times.
The only thing that requires a bit of care is that now we might see the same variable declarations multiple times, so we need to play it safe and overwrite existing entries in our map from declarations to their IR values.
Of course a better answer long-term would be to do the actual unrolling in the IR. This is especially true because we might some day want to support compile-time/must-unroll loops in functions, where the loop counter comes in as a parameter (but must still be compile-time-constant at every call site).
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 827504122..326d25649 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -1637,9 +1637,37 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> SLANG_UNEXPECTED("`case` or `default` not under `switch`"); } - void visitCompileTimeForStmt(CompileTimeForStmt*) + void visitCompileTimeForStmt(CompileTimeForStmt* stmt) { - SLANG_UNIMPLEMENTED_X("IR lowering of CompileTimeForStmt"); + // The user is asking us to emit code for the loop + // body for each value in the given integer range. + // For now, we will handle this by repeatedly lowering + // the body statement, with the loop variable bound + // to a different integer literal value each time. + // + // TODO: eventually we might handle this as just an + // ordinary loop, with an `[unroll]` attribute on + // it that we would respect. + + auto rangeBeginVal = GetIntVal(stmt->rangeBeginVal); + auto rangeEndVal = GetIntVal(stmt->rangeEndVal); + + if (rangeBeginVal >= rangeEndVal) + return; + + auto varDecl = stmt->varDecl; + auto varType = varDecl->type; + + for (IntegerLiteralValue ii = rangeBeginVal; ii < rangeEndVal; ++ii) + { + auto constVal = getBuilder()->getIntValue( + varType, + ii); + + context->shared->declValues[varDecl] = LoweredValInfo::simple(constVal); + + lowerStmt(context, stmt->body); + } } // Create a basic block in the current function, @@ -2590,9 +2618,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // A global variable's SSA value is a *pointer* to // the underlying storage. auto globalVal = LoweredValInfo::ptr(irGlobal); - context->shared->declValues.Add( - DeclRef<VarDeclBase>(decl, nullptr), - globalVal); + context->shared->declValues[ + DeclRef<VarDeclBase>(decl, nullptr)] = globalVal; if( auto initExpr = decl->initExpr ) { @@ -2667,9 +2694,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> assign(context, varVal, initVal); } - context->shared->declValues.Add( - DeclRef<VarDeclBase>(decl, nullptr), - varVal); + context->shared->declValues[ + DeclRef<VarDeclBase>(decl, nullptr)] = varVal; return varVal; } @@ -3214,7 +3240,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> if( auto paramDecl = paramInfo.decl ) { DeclRef<VarDeclBase> paramDeclRef = makeDeclRef(paramDecl); - subContext->shared->declValues.Add(paramDeclRef, paramVal); + subContext->shared->declValues[paramDeclRef] = paramVal; } if (paramInfo.isThisParam) |
