summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-08-09 09:16:36 -0700
committerTim Foley <tfoley@nvidia.com>2017-08-09 09:59:50 -0700
commita728612771cdaed66a0bdbfd25f8f250920f0f11 (patch)
tree4500ab6d1b6148e883988a9624936cfded61131f /source
parent9ad2b40b79907c847451891ce2716fcbcdd2e916 (diff)
Fix use of "pseudo-syntax" in current lowering pass
The so-called "lowering" pass (really a kind of AST-to-AST legalization pass right now) needs to handle some basic scalarization of structured types, and it does this by inventing what I call "pseuo-expressions" and "pseudo-declarations." For example, there is a pseudo-expression node type that represents a tuple of N other expressions, and certain operations act element-wise over such tuples. The problem was that the implementation introduced these out-of-band expression/declaration types into the existing AST hierarchy which led to a dilemma: - If these new AST nodes were declared like all the others (and integrated into the visitor dispatch approach, etc.) then every pass would need to deal with them even though they are meant to be a transient implementation detail of this one pass - But if the new nodes *aren't* declared like the others, then they can't meaningfully interact with visitor dispatch, and will just crash the compiler if they somehow "leak" through to latter passes. And because they are just ordinary AST nodes from a C++ type-system perspective, such leaking is entirely possible (if not probable) Hopefully that setup helps make the solution clear: instead of having the "lowering" pass map an expression to an expression, it needs to map an expression to a new data type (here called `LoweredExpr`) that can wrap *either* an ordinary expression (the common case) or one of the new out-of-band values. Any code that accepts a `LoweredExpr` needs to handle all the cases, or explicitly decide that it can't/won't deal with anything other than ordinary expressions. Most of the code changes are straightforward at that point, although the whole "lowering" approach is a bit fiddly right now, so gertting the tests passing took a bit of attention. I'm not sure our test coverage of all this code is great, so I wouldn't be surprised if some failures are lurking still.
Diffstat (limited to 'source')
-rw-r--r--source/slang/lower.cpp1007
-rw-r--r--source/slang/syntax-base-defs.h10
2 files changed, 649 insertions, 368 deletions
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 3449c647e..e8aa06f03 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -91,40 +91,6 @@ struct StructuralTransformVisitorBase
}
};
-#if 0
-template<typename V>
-struct StructuralTransformStmtVisitor
- : StructuralTransformVisitorBase<V>
- , StmtVisitor<StructuralTransformStmtVisitor<V>, RefPtr<StatementSyntaxNode>>
-{
- void transformFields(StatementSyntaxNode*, StatementSyntaxNode*)
- {
- }
-
-#define SYNTAX_CLASS(NAME, BASE, ...) \
- RefPtr<StatementSyntaxNode> visit(NAME* obj) { \
- RefPtr<NAME> result = new NAME(*obj); \
- transformFields(result, obj); \
- return result; \
- } \
- void transformFields(NAME* result, NAME* obj) { \
- transformFields((BASE*) result, (BASE*) obj); \
-
-#define SYNTAX_FIELD(TYPE, NAME) result->NAME = this->transformSyntaxField(obj->NAME);
-#define DECL_FIELD(TYPE, NAME) result->NAME = this->transformDeclField(obj->NAME);
-
-#define FIELD(TYPE, NAME) /* empty */
-
-#define END_SYNTAX_CLASS() \
- }
-
-#include "object-meta-begin.h"
-#include "stmt-defs.h"
-#include "object-meta-end.h"
-
-};
-#endif
-
template<typename V>
RefPtr<StatementSyntaxNode> structuralTransform(
StatementSyntaxNode* stmt,
@@ -181,34 +147,211 @@ RefPtr<ExpressionSyntaxNode> structuralTransform(
//
-// Pseudo-syntax used during lowering
-class TupleVarDecl : public VarDeclBase
+class TupleExpr;
+class TupleVarDecl;
+class VaryingTupleExpr;
+class VaryingTupleVarDecl;
+
+
+// The result of lowering a declaration will usually be a declaration,
+// but it might also be a "tuple" declaration, in cases where we needed
+// to sclarize (or partially scalarize) things to guarantee validity.
+struct LoweredDecl
{
-public:
- virtual void accept(IDeclVisitor *, void *) override
+ enum class Flavor
+ {
+ Decl, // A single declaration (the default case)
+ Tuple, // A `TupleVarDecl` representing multiple decls
+ VaryingTuple, // A `VaryingTupleVarDecl` representing multiple decls
+ };
+
+ LoweredDecl()
+ : flavor(Flavor::Decl)
+ {}
+
+ LoweredDecl(Decl* decl)
+ : value(decl)
+ , flavor(Flavor::Decl)
+ {}
+
+ LoweredDecl(TupleVarDecl* decl)
+ : value((RefObject*) decl)
+ , flavor(Flavor::Tuple)
+ {}
+
+ LoweredDecl(VaryingTupleVarDecl* decl)
+ : value((RefObject*) decl)
+ , flavor(Flavor::VaryingTuple)
+ {}
+
+ Flavor getFlavor() const { return flavor; }
+ RefObject* getValue() const { return value; }
+
+ Decl* getDecl() const
+ {
+ SLANG_ASSERT(getFlavor() == Flavor::Decl);
+ return (Decl*) value.Ptr();
+ }
+
+ TupleVarDecl* getTupleDecl() const
{
- SLANG_UNEXPECTED("tuples should not appear in lowered code");
+ SLANG_ASSERT(getFlavor() == Flavor::Tuple);
+ return (TupleVarDecl*) value.Ptr();
}
- TupleTypeModifier* tupleType;
- RefPtr<VarDeclBase> primaryDecl;
- List<RefPtr<VarDeclBase>> tupleDecls;
+ VaryingTupleVarDecl* getVaryingTupleDecl() const
+ {
+ SLANG_ASSERT(getFlavor() == Flavor::VaryingTuple);
+ return (VaryingTupleVarDecl*) value.Ptr();
+ }
+
+ Decl* asDecl() const
+ {
+ return (getFlavor() == Flavor::Decl) ? getDecl() : nullptr;
+ }
+
+ TupleVarDecl* asTupleDecl() const
+ {
+ return (getFlavor() == Flavor::Tuple) ? getTupleDecl() : nullptr;
+ }
+
+ VaryingTupleVarDecl* asVaryingTupleDecl() const
+ {
+ return (getFlavor() == Flavor::VaryingTuple) ? getVaryingTupleDecl() : nullptr;
+ }
+
+private:
+ RefPtr<RefObject> value;
+ Flavor flavor;
};
-// Pseudo-syntax used during lowering:
-// represents an ordered list of expressions as a single unit
-class TupleExpr : public ExpressionSyntaxNode
+struct LoweredDeclRef
{
public:
- virtual void accept(IExprVisitor *, void *) override
+ LoweredDecl decl;
+ RefPtr<Substitutions> substitutions;
+
+ LoweredDecl getDecl() { return decl; }
+
+ template<typename T>
+ DeclRef<T> As()
+ {
+ return DeclRef<Decl>(decl.getDecl(), substitutions).As<T>();
+ }
+};
+
+
+// The result of lowering an exrpession will usually be just a single
+// expression, but it might also be a "tuple" expression that encodes
+// multiple expressions.
+struct LoweredExpr
+{
+ enum class Flavor
{
- SLANG_UNEXPECTED("tuples should not appear in lowered code");
+ Expr,
+ Tuple,
+ VaryingTuple,
+ };
+
+ LoweredExpr()
+ : flavor(Flavor::Expr)
+ {}
+
+ LoweredExpr(ExpressionSyntaxNode* expr)
+ : value(expr)
+ , flavor(Flavor::Expr)
+ {}
+
+ LoweredExpr(TupleExpr* expr)
+ : value((RefObject*) expr)
+ , flavor(Flavor::Tuple)
+ {}
+
+ LoweredExpr(VaryingTupleExpr* expr)
+ : value((RefObject*) expr)
+ , flavor(Flavor::VaryingTuple)
+ {}
+
+ Flavor getFlavor() const { return flavor; }
+
+ ExpressionSyntaxNode* getExpr() const
+ {
+ assert(getFlavor() == Flavor::Expr);
+ return (ExpressionSyntaxNode*)value.Ptr();
}
+ TupleExpr* getTupleExpr() const
+ {
+ assert(getFlavor() == Flavor::Tuple);
+ return (TupleExpr*)value.Ptr();
+ }
+
+
+ VaryingTupleExpr* getVaryingTupleExpr() const
+ {
+ assert(getFlavor() == Flavor::VaryingTuple);
+ return (VaryingTupleExpr*)value.Ptr();
+ }
+
+ ExpressionSyntaxNode* asExpr() const
+ {
+ return (getFlavor() == Flavor::Expr) ? getExpr() : nullptr;
+ }
+
+ TupleExpr* asTuple() const
+ {
+ return (getFlavor() == Flavor::Tuple) ? getTupleExpr() : nullptr;
+ }
+
+ VaryingTupleExpr* asVaryingTuple() const
+ {
+ return (getFlavor() == Flavor::VaryingTuple) ? getVaryingTupleExpr() : nullptr;
+ }
+
+private:
+ RefPtr<RefObject> value;
+ Flavor flavor;
+};
+
+// Pseudo-syntax used during lowering
+class PseudoVarDecl : public RefObject
+{
+public:
+ Token Name;
+ CodePosition Position;
+ TypeExp Type;
+};
+
+class TupleVarDecl : public PseudoVarDecl
+{
+public:
+ struct Element
+ {
+ RefPtr<TupleVarModifier> tupleVarMod;
+ LoweredDecl decl;
+ };
+
+ TupleTypeModifier* tupleType;
+ RefPtr<VarDeclBase> primaryDecl;
+ List<Element> tupleDecls;
+};
+
+class PseudoExpr : public RefObject
+{
+public:
+ CodePosition Position;
+ QualType Type;
+};
+
+// Pseudo-syntax used during lowering:
+// represents an ordered list of expressions as a single unit
+class TupleExpr : public PseudoExpr
+{
+public:
struct Element
{
- DeclRef<VarDeclBase> tupleFieldDeclRef;
- RefPtr<ExpressionSyntaxNode> expr;
+ DeclRef<VarDeclBase> tupleFieldDeclRef;
+ LoweredExpr expr;
};
// Optional reference to the "primary" value of the tuple,
@@ -221,34 +364,40 @@ public:
};
// Pseudo-syntax used during lowering
-class VaryingTupleVarDecl : public VarDeclBase
+class VaryingTupleVarDecl : public PseudoVarDecl
{
public:
- virtual void accept(IDeclVisitor *, void *) override
- {
- SLANG_UNEXPECTED("tuples should not appear in lowered code");
- }
+ LoweredExpr expr;
};
// Pseudo-syntax used during lowering:
// represents an ordered list of expressions as a single unit
-class VaryingTupleExpr : public ExpressionSyntaxNode
+class VaryingTupleExpr : public PseudoExpr
{
public:
- virtual void accept(IExprVisitor *, void *) override
- {
- SLANG_UNEXPECTED("tuples should not appear in lowered code");
- }
-
struct Element
{
- DeclRef<VarDeclBase> originalFieldDeclRef;
- RefPtr<ExpressionSyntaxNode> expr;
+ DeclRef<VarDeclBase> originalFieldDeclRef;
+ LoweredExpr expr;
};
List<Element> elements;
};
+static CodePosition getPosition(LoweredExpr const& expr)
+{
+ switch (expr.getFlavor())
+ {
+ case LoweredExpr::Flavor::Expr: return expr.getExpr() ->Position;
+ case LoweredExpr::Flavor::Tuple: return expr.getTupleExpr() ->Position;
+ case LoweredExpr::Flavor::VaryingTuple: return expr.getVaryingTupleExpr()->Position;
+ default:
+ SLANG_UNREACHABLE("all cases handled");
+ return CodePosition();
+ }
+}
+
+
struct SharedLoweringContext
{
CompileRequest* compileRequest;
@@ -271,8 +420,8 @@ struct SharedLoweringContext
RefPtr<ProgramSyntaxNode> loweredProgram;
- Dictionary<Decl*, RefPtr<Decl>> loweredDecls;
- Dictionary<Decl*, Decl*> mapLoweredDeclToOriginal;
+ Dictionary<Decl*, LoweredDecl> loweredDecls;
+ Dictionary<RefObject*, Decl*> mapLoweredDeclToOriginal;
// Work to be done at the very start and end of the entry point
RefPtr<StatementSyntaxNode> entryPointInitializeStmt;
@@ -300,9 +449,9 @@ void requireGLSLVersion(
ProfileVersion version);
struct LoweringVisitor
- : ExprVisitor<LoweringVisitor, RefPtr<ExpressionSyntaxNode>>
+ : ExprVisitor<LoweringVisitor, LoweredExpr>
, StmtVisitor<LoweringVisitor, void>
- , DeclVisitor<LoweringVisitor, RefPtr<Decl>>
+ , DeclVisitor<LoweringVisitor, LoweredDecl>
, ValVisitor<LoweringVisitor, RefPtr<Val>, RefPtr<ExpressionType>>
{
//
@@ -562,7 +711,7 @@ struct LoweringVisitor
auto loweredDeclRef = translateDeclRef(type->declRef);
return DeclRefType::Create(
type->getSession(),
- loweredDeclRef);
+ loweredDeclRef.As<Decl>());
}
RefPtr<ExpressionType> visitNamedExpressionType(NamedExpressionType* type)
@@ -600,10 +749,10 @@ struct LoweringVisitor
// Expressions
//
- RefPtr<ExpressionSyntaxNode> lowerExprOrTuple(
+ LoweredExpr lowerExprOrTuple(
ExpressionSyntaxNode* expr)
{
- if (!expr) return nullptr;
+ if (!expr) return LoweredExpr();
return ExprVisitor::dispatch(expr);
}
@@ -629,13 +778,23 @@ struct LoweringVisitor
}
void lowerExprCommon(
- RefPtr<ExpressionSyntaxNode> loweredExpr,
- RefPtr<ExpressionSyntaxNode> expr)
+ ExpressionSyntaxNode* loweredExpr,
+ ExpressionSyntaxNode* expr)
{
loweredExpr->Position = expr->Position;
loweredExpr->Type.type = lowerType(expr->Type.type);
}
+ void lowerExprCommon(
+ LoweredExpr const& loweredExpr,
+ ExpressionSyntaxNode* expr)
+ {
+ if (auto simpleExpr = loweredExpr.asExpr())
+ {
+ lowerExprCommon(simpleExpr, expr);
+ }
+ }
+
RefPtr<ExpressionSyntaxNode> createUncheckedVarRef(
char const* name)
{
@@ -644,30 +803,41 @@ struct LoweringVisitor
return result;
}
- RefPtr<ExpressionSyntaxNode> createVarRef(
+ RefPtr<ExpressionSyntaxNode> createSimpleVarRef(
CodePosition const& loc,
VarDeclBase* decl)
{
- if (auto tupleDecl = dynamic_cast<TupleVarDecl*>(decl))
- {
- return createTupleRef(loc, tupleDecl);
- }
- else if (auto varyingTupleDecl = dynamic_cast<VaryingTupleVarDecl*>(decl))
- {
- return createVaryingTupleRef(loc, varyingTupleDecl);
- }
- else
+ RefPtr<VarExpressionSyntaxNode> result = new VarExpressionSyntaxNode();
+ result->Position = loc;
+ result->Type.type = decl->Type.type;
+ result->declRef = makeDeclRef(decl);
+ result->name = decl->getName();
+ return result;
+ }
+
+ LoweredExpr createVarRef(
+ CodePosition const& loc,
+ LoweredDecl const& decl)
+ {
+ switch (decl.getFlavor())
{
- RefPtr<VarExpressionSyntaxNode> result = new VarExpressionSyntaxNode();
- result->Position = loc;
- result->Type.type = decl->Type.type;
- result->declRef = makeDeclRef(decl);
- result->name = decl->getName();
- return result;
+ case LoweredDecl::Flavor::Decl:
+ return LoweredExpr(createSimpleVarRef(loc, decl.getDecl()->As<VarDeclBase>()));
+
+ case LoweredDecl::Flavor::Tuple:
+ return createTupleRef(loc, decl.getTupleDecl());
+
+ case LoweredDecl::Flavor::VaryingTuple:
+ return createVaryingTupleRef(loc, decl.getVaryingTupleDecl());
+
+ default:
+ SLANG_UNREACHABLE("all cases handled");
+ return LoweredExpr();
}
}
- RefPtr<ExpressionSyntaxNode> createTupleRef(
+
+ LoweredExpr createTupleRef(
CodePosition const& loc,
TupleVarDecl* decl)
{
@@ -677,12 +847,12 @@ struct LoweringVisitor
if (auto primaryDecl = decl->primaryDecl)
{
- result->primaryExpr = createVarRef(loc, primaryDecl);
+ result->primaryExpr = createSimpleVarRef(loc, primaryDecl);
}
- for (auto dd : decl->tupleDecls)
+ for (auto declElem : decl->tupleDecls)
{
- auto tupleVarMod = dd->FindModifier<TupleVarModifier>();
+ auto tupleVarMod = declElem.tupleVarMod;
SLANG_RELEASE_ASSERT(tupleVarMod);
auto tupleFieldMod = tupleVarMod->tupleField;
SLANG_RELEASE_ASSERT(tupleFieldMod);
@@ -690,21 +860,21 @@ struct LoweringVisitor
TupleExpr::Element elem;
elem.tupleFieldDeclRef = makeDeclRef(tupleFieldMod->decl);
- elem.expr = createVarRef(loc, dd);
+ elem.expr = createVarRef(loc, declElem.decl);
result->tupleElements.Add(elem);
}
- return result;
+ return LoweredExpr(result);
}
- RefPtr<ExpressionSyntaxNode> createVaryingTupleRef(
- CodePosition const& loc,
+ LoweredExpr createVaryingTupleRef(
+ CodePosition const& /*loc*/,
VaryingTupleVarDecl* decl)
{
- return decl->Expr;
+ return decl->expr;
}
- RefPtr<ExpressionSyntaxNode> visitVarExpressionSyntaxNode(
+ LoweredExpr visitVarExpressionSyntaxNode(
VarExpressionSyntaxNode* expr)
{
doSampleRateInputCheck(expr->name);
@@ -716,23 +886,23 @@ struct LoweringVisitor
auto loweredDeclRef = translateDeclRef(expr->declRef);
auto loweredDecl = loweredDeclRef.getDecl();
- if (auto tupleVarDecl = dynamic_cast<TupleVarDecl*>(loweredDecl))
+ if (auto tupleVarDecl = loweredDecl.asTupleDecl())
{
// If we are referencing a declaration that got tuple-ified,
// then we need to produce a tuple expression as well.
return createTupleRef(expr->Position, tupleVarDecl);
}
- else if (auto varyingTupleVarDecl = dynamic_cast<VaryingTupleVarDecl*>(loweredDecl))
+ else if (auto varyingTupleVarDecl = loweredDecl.asVaryingTupleDecl())
{
return createVaryingTupleRef(expr->Position, varyingTupleVarDecl);
}
RefPtr<VarExpressionSyntaxNode> loweredExpr = new VarExpressionSyntaxNode();
lowerExprCommon(loweredExpr, expr);
- loweredExpr->declRef = loweredDeclRef;
+ loweredExpr->declRef = loweredDeclRef.As<Decl>();
loweredExpr->name = expr->name;
- return loweredExpr;
+ return LoweredExpr(loweredExpr);
}
String generateName()
@@ -754,7 +924,7 @@ struct LoweringVisitor
addDecl(varDecl);
- return createVarRef(expr->Position, varDecl);
+ return createSimpleVarRef(expr->Position, varDecl);
}
// The idea of this function is to take an expression that we plan to
@@ -762,22 +932,49 @@ struct LoweringVisitor
// reference to a temporary (initialized with the expr) so that it
// can safely be re-evaluated.
RefPtr<ExpressionSyntaxNode> maybeMoveTemp(
- RefPtr<ExpressionSyntaxNode> expr)
+ ExpressionSyntaxNode* expr)
{
// TODO: actually implement this properly!
// Certain expressions are already in a form we can directly re-use,
// so there is no reason to move them.
- if (expr.As<VarExpressionSyntaxNode>())
+ if (dynamic_cast<VarExpressionSyntaxNode*>(expr))
return expr;
- if (expr.As<ConstantExpressionSyntaxNode>())
+ if (dynamic_cast<ConstantExpressionSyntaxNode*>(expr))
return expr;
- if (auto varyingTupleExpr = expr.As<VaryingTupleExpr>())
+ // In the general case, though, we need to introduce a temporary
+ return moveTemp(expr);
+ }
+
+ LoweredExpr maybeMoveTemp(
+ LoweredExpr expr)
+ {
+ if (auto tupleExpr = expr.asTuple())
+ {
+ RefPtr<TupleExpr> resultExpr = new TupleExpr();
+ resultExpr->Position = tupleExpr->Position;
+ resultExpr->Type = tupleExpr->Type;
+ if (tupleExpr->primaryExpr)
+ {
+ resultExpr->primaryExpr = maybeMoveTemp(tupleExpr->primaryExpr);
+ }
+ for (auto ee : tupleExpr->tupleElements)
+ {
+ TupleExpr::Element elem;
+ elem.tupleFieldDeclRef = ee.tupleFieldDeclRef;
+ elem.expr = maybeMoveTemp(ee.expr);
+
+ resultExpr->tupleElements.Add(elem);
+ }
+
+ return LoweredExpr(resultExpr);
+ }
+ else if (auto varyingTupleExpr = expr.asVaryingTuple())
{
RefPtr<VaryingTupleExpr> resultExpr = new VaryingTupleExpr();
- resultExpr->Position = expr->Position;
- resultExpr->Type = expr->Type;
+ resultExpr->Position = varyingTupleExpr->Position;
+ resultExpr->Type = varyingTupleExpr->Type;
for (auto ee : varyingTupleExpr->elements)
{
VaryingTupleExpr::Element elem;
@@ -787,20 +984,27 @@ struct LoweringVisitor
resultExpr->elements.Add(elem);
}
- return resultExpr;
+ return LoweredExpr(resultExpr);
+ }
+ else
+ {
+ return LoweredExpr(maybeMoveTemp(expr.getExpr()));
}
-
- // TODO: handle the tuple cases here...
-
- // In the general case, though, we need to introduce a temporary
- return moveTemp(expr);
}
// Similar to the above, this ensures that an l-value expression
// is safe to re-evaluate, by recursively moving things off
// to temporaries where needed.
RefPtr<ExpressionSyntaxNode> ensureSimpleLValue(
- RefPtr<ExpressionSyntaxNode> expr)
+ ExpressionSyntaxNode* expr)
+ {
+ // TODO: actually implement this properly!
+
+ return expr;
+ }
+
+ LoweredExpr ensureSimpleLValue(
+ LoweredExpr expr)
{
// TODO: actually implement this properly!
@@ -1039,23 +1243,38 @@ struct LoweringVisitor
return createSimpleAssignExpr(leftExpr, convertedRightExpr);
}
- RefPtr<ExpressionSyntaxNode> createAssignExpr(
- RefPtr<ExpressionSyntaxNode> leftExpr,
- RefPtr<ExpressionSyntaxNode> rightExpr,
- AssignMode mode = AssignMode::Default)
+ RefPtr<ExpressionSyntaxNode> createSimpleAssignExpr(
+ ExpressionSyntaxNode* leftExpr,
+ ExpressionSyntaxNode* rightExpr,
+ AssignMode mode)
{
- auto leftTuple = leftExpr.As<TupleExpr>();
- auto rightTuple = rightExpr.As<TupleExpr>();
+ switch (mode)
+ {
+ default:
+ return createSimpleAssignExpr(leftExpr, rightExpr);
+
+ case AssignMode::WithFixups:
+ return createSimpleAssignExprWithFixups(leftExpr, rightExpr);
+ }
+ }
+
+ LoweredExpr createAssignExpr(
+ LoweredExpr leftExpr,
+ LoweredExpr rightExpr,
+ AssignMode mode = AssignMode::Default)
+ {
+ auto leftTuple = leftExpr.asTuple();
+ auto rightTuple = rightExpr.asTuple();
if (leftTuple && rightTuple)
{
RefPtr<TupleExpr> resultTuple = new TupleExpr();
- resultTuple->Type = leftExpr->Type;
+ resultTuple->Type = leftTuple->Type;
if (leftTuple->primaryExpr)
{
SLANG_RELEASE_ASSERT(rightTuple->primaryExpr);
- resultTuple->primaryExpr = createAssignExpr(
+ resultTuple->primaryExpr = createSimpleAssignExpr(
leftTuple->primaryExpr,
rightTuple->primaryExpr,
mode);
@@ -1079,20 +1298,24 @@ struct LoweringVisitor
resultTuple->tupleElements.Add(resultElement);
}
- return resultTuple;
+ return LoweredExpr(resultTuple);
}
else
{
SLANG_RELEASE_ASSERT(!leftTuple && !rightTuple);
}
- auto leftVaryingTuple = leftExpr.As<VaryingTupleExpr>();
- auto rightVaryingTuple = rightExpr.As<VaryingTupleExpr>();
+ auto leftVaryingTuple = leftExpr.asVaryingTuple();
+ auto rightVaryingTuple = rightExpr.asVaryingTuple();
+
+ RefPtr<ExpressionSyntaxNode> leftSimpleExpr = leftExpr.asExpr();
+ RefPtr<ExpressionSyntaxNode> rightSimpleExpr = rightExpr.asExpr();
+
if (leftVaryingTuple && rightVaryingTuple)
{
RefPtr<VaryingTupleExpr> resultTuple = new VaryingTupleExpr();
- resultTuple->Type.type = lowerType(leftExpr->Type.type);
- resultTuple->Position = leftExpr->Position;
+ resultTuple->Type.type = leftVaryingTuple->Type.type;
+ resultTuple->Position = leftVaryingTuple->Position;
SLANG_RELEASE_ASSERT(resultTuple->Type.type);
@@ -1111,122 +1334,117 @@ struct LoweringVisitor
rightElem.expr,
mode);
}
+
+ return LoweredExpr(resultTuple);
}
- else if (leftVaryingTuple)
+ else if (leftVaryingTuple && rightSimpleExpr)
{
// Assigning from ordinary expression on RHS to tuple.
// This will naturally yield a tuple expression.
- //
- // TODO: need to be careful about side-effects, or
- // about dropping sub-expressions after the assignment.
- // For now this will really only work directly in
- // a statement context.
+
+ RefPtr<VaryingTupleExpr> resultTuple = new VaryingTupleExpr();
+ resultTuple->Type.type = leftVaryingTuple->Type.type;
+ resultTuple->Position = leftVaryingTuple->Position;
+
+ SLANG_RELEASE_ASSERT(resultTuple->Type.type);
UInt elementCount = leftVaryingTuple->elements.Count();
// Move everything into temps if we can
-
- rightExpr = maybeMoveTemp(rightExpr);
+ rightSimpleExpr = maybeMoveTemp(rightSimpleExpr);
for (UInt ee = 0; ee < elementCount; ++ee)
{
auto& leftElem = leftVaryingTuple->elements[ee];
leftElem.expr = ensureSimpleLValue(leftElem.expr);
}
- // We need to combine the sub-expressions into a giant sequence expression.
//
- // We will procede through thigns from last to first, to build a bunch
- // of "operator comma" expressions bottom-up.
- RefPtr<ExpressionSyntaxNode> resultExpr = leftExpr;
for (UInt ee = 0; ee < elementCount; ++ee)
{
- auto leftElem = leftVaryingTuple->elements[elementCount - ee - 1];
+ auto leftElem = leftVaryingTuple->elements[ee];
+
RefPtr<MemberExpressionSyntaxNode> rightElemExpr = new MemberExpressionSyntaxNode();
- rightElemExpr->Position = rightExpr->Position;
+ rightElemExpr->Position = rightSimpleExpr->Position;
rightElemExpr->Type.type = GetType(leftElem.originalFieldDeclRef);
rightElemExpr->declRef = leftElem.originalFieldDeclRef;
rightElemExpr->name = leftElem.originalFieldDeclRef.GetName();
- rightElemExpr->BaseExpression = rightExpr;
+ rightElemExpr->BaseExpression = rightSimpleExpr;
- auto subExpr = createAssignExpr(
+ VaryingTupleExpr::Element elem;
+ elem.originalFieldDeclRef = leftElem.originalFieldDeclRef;
+ elem.expr = createAssignExpr(
leftElem.expr,
- rightElemExpr,
+ LoweredExpr(rightElemExpr),
mode);
- RefPtr<InfixExpr> seqExpr = new InfixExpr();
- seqExpr->FunctionExpr = createUncheckedVarRef(",");
- seqExpr->Arguments.Add(subExpr);
- seqExpr->Arguments.Add(resultExpr);
-
- resultExpr = seqExpr;
+ resultTuple->elements.Add(elem);
}
- return resultExpr;
+ return LoweredExpr(resultTuple);
}
- else if (rightVaryingTuple)
+ else if (leftSimpleExpr && rightVaryingTuple)
{
// Pretty much the same as the above case, and we should
// probably try to share code eventually.
+
+ RefPtr<VaryingTupleExpr> resultTuple = new VaryingTupleExpr();
+ resultTuple->Type.type = leftSimpleExpr->Type.type;
+ resultTuple->Position = leftSimpleExpr->Position;
+
+ SLANG_RELEASE_ASSERT(resultTuple->Type.type);
+
UInt elementCount = rightVaryingTuple->elements.Count();
// Move everything into temps if we can
-
- leftExpr = ensureSimpleLValue(leftExpr);
+ leftSimpleExpr = ensureSimpleLValue(leftSimpleExpr);
for (UInt ee = 0; ee < elementCount; ++ee)
{
auto& rightElem = rightVaryingTuple->elements[ee];
rightElem.expr = maybeMoveTemp(rightElem.expr);
}
- // We need to combine the sub-expressions into a giant sequence expression.
- //
- // We will procede through thigns from last to first, to build a bunch
- // of "operator comma" expressions bottom-up.
- RefPtr<ExpressionSyntaxNode> resultExpr = leftExpr;
for (UInt ee = 0; ee < elementCount; ++ee)
{
- auto rightElem = rightVaryingTuple->elements[elementCount - ee - 1];
+ auto rightElem = rightVaryingTuple->elements[ee];
+
RefPtr<MemberExpressionSyntaxNode> leftElemExpr = new MemberExpressionSyntaxNode();
- leftElemExpr->Position = leftExpr->Position;
- leftElemExpr->Type = rightElem.expr->Type;
+ leftElemExpr->Position = leftSimpleExpr->Position;
+ leftElemExpr->Type.type = GetType(rightElem.originalFieldDeclRef);
leftElemExpr->declRef = rightElem.originalFieldDeclRef;
leftElemExpr->name = rightElem.originalFieldDeclRef.GetName();
- leftElemExpr->BaseExpression = leftExpr;
+ leftElemExpr->BaseExpression = leftSimpleExpr;
- auto subExpr = createAssignExpr(
- leftElemExpr,
+ VaryingTupleExpr::Element elem;
+ elem.originalFieldDeclRef = rightElem.originalFieldDeclRef;
+ elem.expr = createAssignExpr(
+ LoweredExpr(leftElemExpr),
rightElem.expr,
mode);
- RefPtr<InfixExpr> seqExpr = new InfixExpr();
- seqExpr->FunctionExpr = createUncheckedVarRef(",");
- seqExpr->Arguments.Add(subExpr);
- seqExpr->Arguments.Add(resultExpr);
-
- resultExpr = seqExpr;
+ resultTuple->elements.Add(elem);
}
- return resultExpr;
+ return LoweredExpr(resultTuple);
}
-
- // Default case: no tuples of any kind...
-
- switch (mode)
+ else if (leftSimpleExpr && rightSimpleExpr)
{
- default:
- return createSimpleAssignExpr(leftExpr, rightExpr);
+ // Default case: no tuples of any kind...
- case AssignMode::WithFixups:
- return createSimpleAssignExprWithFixups(leftExpr, rightExpr);
+ return LoweredExpr(createSimpleAssignExpr(leftSimpleExpr, rightSimpleExpr, mode));
+ }
+ else
+ {
+ // Some case wasn't handled: diagnose!
+ SLANG_UNEXPECTED("bad combination of tuple types");
}
}
- RefPtr<ExpressionSyntaxNode> visitAssignExpr(
+ LoweredExpr visitAssignExpr(
AssignExpr* expr)
{
auto leftExpr = lowerExprOrTuple(expr->left);
@@ -1247,24 +1465,38 @@ struct LoweringVisitor
return nullptr;
}
- RefPtr<ExpressionSyntaxNode> createSubscriptExpr(
+ RefPtr<ExpressionSyntaxNode> createSimpleSubscriptExpr(
RefPtr<ExpressionSyntaxNode> baseExpr,
RefPtr<ExpressionSyntaxNode> indexExpr)
{
+ // Default case: just reconstrut a subscript expr
+ auto loweredExpr = new IndexExpressionSyntaxNode();
+
+ loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);
+
+ loweredExpr->BaseExpression = baseExpr;
+ loweredExpr->IndexExpression = indexExpr;
+ return loweredExpr;
+ }
+
+ LoweredExpr createSubscriptExpr(
+ LoweredExpr baseExpr,
+ RefPtr<ExpressionSyntaxNode> indexExpr)
+ {
// TODO: This logic ends up duplicating the `indexExpr`
// that was given, without worrying about any side
// effects it might contain. That needs to be fixed.
- if (auto baseTuple = baseExpr.As<TupleExpr>())
+ if (auto baseTuple = baseExpr.asTuple())
{
indexExpr = maybeMoveTemp(indexExpr);
auto loweredExpr = new TupleExpr();
- loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);
+ loweredExpr->Type.type = getSubscripResultType(baseTuple->Type.type);
if (auto basePrimary = baseTuple->primaryExpr)
{
- loweredExpr->primaryExpr = createSubscriptExpr(
+ loweredExpr->primaryExpr = createSimpleSubscriptExpr(
basePrimary,
indexExpr);
}
@@ -1281,12 +1513,12 @@ struct LoweringVisitor
return loweredExpr;
}
- else if (auto baseVaryingTuple = baseExpr.As<VaryingTupleExpr>())
+ else if (auto baseVaryingTuple = baseExpr.asVaryingTuple())
{
indexExpr = maybeMoveTemp(indexExpr);
auto loweredExpr = new VaryingTupleExpr();
- loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);
+ loweredExpr->Type.type = getSubscripResultType(baseVaryingTuple->Type.type);
SLANG_RELEASE_ASSERT(loweredExpr->Type.type);
@@ -1303,18 +1535,13 @@ struct LoweringVisitor
}
else
{
- // Default case: just reconstrut a subscript expr
- auto loweredExpr = new IndexExpressionSyntaxNode();
-
-loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);
-
-loweredExpr->BaseExpression = baseExpr;
-loweredExpr->IndexExpression = indexExpr;
-return loweredExpr;
+ return LoweredExpr(createSimpleSubscriptExpr(
+ baseExpr.getExpr(),
+ indexExpr));
}
}
- RefPtr<ExpressionSyntaxNode> visitIndexExpressionSyntaxNode(
+ LoweredExpr visitIndexExpressionSyntaxNode(
IndexExpressionSyntaxNode* subscriptExpr)
{
auto baseExpr = lowerExprOrTuple(subscriptExpr->BaseExpression);
@@ -1322,11 +1549,11 @@ return loweredExpr;
// An attempt to subscript a tuple must be turned into a
// tuple of subscript expressions.
- if (auto baseTuple = baseExpr.As<TupleExpr>())
+ if (auto baseTuple = baseExpr.asTuple())
{
return createSubscriptExpr(baseExpr, indexExpr);
}
- else if (auto baseVaryingTuple = baseExpr.As<VaryingTupleExpr>())
+ else if (auto baseVaryingTuple = baseExpr.asVaryingTuple())
{
return createSubscriptExpr(baseExpr, indexExpr);
}
@@ -1335,21 +1562,21 @@ return loweredExpr;
// Default case: just reconstrut a subscript expr
RefPtr<IndexExpressionSyntaxNode> loweredExpr = new IndexExpressionSyntaxNode();
lowerExprCommon(loweredExpr, subscriptExpr);
- loweredExpr->BaseExpression = baseExpr;
+ loweredExpr->BaseExpression = baseExpr.getExpr();
loweredExpr->IndexExpression = indexExpr;
- return loweredExpr;
+ return LoweredExpr(loweredExpr);
}
}
RefPtr<ExpressionSyntaxNode> maybeReifyTuple(
- RefPtr<ExpressionSyntaxNode> expr)
+ LoweredExpr expr)
{
- if (auto tupleExpr = expr.As<TupleExpr>())
+ if (auto tupleExpr = expr.asTuple())
{
// TODO: need to diagnose
- return expr;
+ return tupleExpr->primaryExpr;
}
- else if (auto varyingTupleExpr = expr.As<VaryingTupleExpr>())
+ else if (auto varyingTupleExpr = expr.asVaryingTuple())
{
// Need to pass an ordinary (non-tuple) expression of
// the corresponding type here.
@@ -1372,7 +1599,7 @@ return loweredExpr;
}
// Default case: nothing special to this expression
- return expr;
+ return expr.getExpr();
}
bool needGlslangBug988Workaround(
@@ -1453,22 +1680,40 @@ return loweredExpr;
return false;
}
- void addArgs(
+ void addArg(
ExprWithArgsBase* callExpr,
RefPtr<ExpressionSyntaxNode> argExpr)
{
- if (auto argTuple = argExpr.As<TupleExpr>())
+ // This should be the default case where we have a perfectly
+ // ordinary expression, but we need to work around a glslang
+ // but here, where passing a member of a `uniform` block
+ // that has `struct` type directly to a function call causes
+ // invalid SPIR-V to be generated.
+ if (needGlslangBug988Workaround(argExpr))
+ {
+ argExpr = moveTemp(argExpr);
+ }
+
+ // Here's the actual default case where we just add an argment
+ callExpr->Arguments.Add(argExpr);
+ }
+
+ void addArgs(
+ ExprWithArgsBase* callExpr,
+ LoweredExpr argExpr)
+ {
+ if (auto argTuple = argExpr.asTuple())
{
if (argTuple->primaryExpr)
{
- addArgs(callExpr, argTuple->primaryExpr);
+ addArg(callExpr, argTuple->primaryExpr);
}
for (auto elem : argTuple->tupleElements)
{
addArgs(callExpr, elem.expr);
}
}
- else if (auto varyingArgTuple = argExpr.As<VaryingTupleExpr>())
+ else if (auto varyingArgTuple = argExpr.asVaryingTuple())
{
// Need to pass an ordinary (non-tuple) expression of
// the corresponding type here.
@@ -1477,18 +1722,7 @@ return loweredExpr;
}
else
{
- // This should be the default case where we have a perfectly
- // ordinary expression, but we need to work around a glslang
- // but here, where passing a member of a `uniform` block
- // that has `struct` type directly to a function call causes
- // invalid SPIR-V to be generated.
- if (needGlslangBug988Workaround(argExpr))
- {
- argExpr = moveTemp(argExpr);
- }
-
- // Here's the actual default case where we just add an argment
- callExpr->Arguments.Add(argExpr);
+ addArg(callExpr, argExpr.getExpr());
}
}
@@ -1509,45 +1743,58 @@ return loweredExpr;
return loweredExpr;
}
- RefPtr<ExpressionSyntaxNode> visitInvokeExpressionSyntaxNode(
+ LoweredExpr visitInvokeExpressionSyntaxNode(
InvokeExpressionSyntaxNode* expr)
{
- return lowerCallExpr(new InvokeExpressionSyntaxNode(), expr);
+ return LoweredExpr(lowerCallExpr(new InvokeExpressionSyntaxNode(), expr));
}
- RefPtr<ExpressionSyntaxNode> visitInfixExpr(
+ LoweredExpr visitInfixExpr(
InfixExpr* expr)
{
- return lowerCallExpr(new InfixExpr(), expr);
+ return LoweredExpr(lowerCallExpr(new InfixExpr(), expr));
}
- RefPtr<ExpressionSyntaxNode> visitPrefixExpr(
+ LoweredExpr visitPrefixExpr(
PrefixExpr* expr)
{
- return lowerCallExpr(new PrefixExpr(), expr);
+ return LoweredExpr(lowerCallExpr(new PrefixExpr(), expr));
}
- RefPtr<ExpressionSyntaxNode> visitSelectExpressionSyntaxNode(
+ LoweredExpr visitSelectExpressionSyntaxNode(
SelectExpressionSyntaxNode* expr)
{
// TODO: A tuple needs to be special-cased here
- return lowerCallExpr(new SelectExpressionSyntaxNode(), expr);
+ return LoweredExpr(lowerCallExpr(new SelectExpressionSyntaxNode(), expr));
}
- RefPtr<ExpressionSyntaxNode> visitPostfixExpr(
+ LoweredExpr visitPostfixExpr(
PostfixExpr* expr)
{
- return lowerCallExpr(new PostfixExpr(), expr);
+ return LoweredExpr(lowerCallExpr(new PostfixExpr(), expr));
}
- RefPtr<ExpressionSyntaxNode> visitDerefExpr(
+ LoweredExpr visitDerefExpr(
DerefExpr* expr)
{
auto loweredBase = lowerExprOrTuple(expr->base);
- if (auto baseTuple = loweredBase.As<TupleExpr>())
+ if (auto baseTuple = loweredBase.asTuple())
{
+ // In the case of a tuple created for "resources in structs" reasons,
+ // only the primary expression (if any) needs to be dereferenced.
+ //
+ // We cheat a bit here and re-use the same tuple we already have,
+ // and just insert the deref into its primary.
+ //
+ // More or less we are lowering:
+ //
+ // *(P, T0, T1, ...)
+ //
+ // into:
+ // (*P, T0, T1, ...)
+ //
if (auto primaryExpr = baseTuple->primaryExpr)
{
RefPtr<DerefExpr> loweredPrimary = new DerefExpr();
@@ -1557,11 +1804,22 @@ return loweredExpr;
return baseTuple;
}
}
+ else if (auto baseVaryingTuple = loweredBase.asVaryingTuple())
+ {
+ // We don't expect to see this case arise for a "varying"
+ // tuple, since there aren't pointer-like varyings, but
+ // the desugaring seems natural: just dereference each
+ // field.
+ //
+ // TODO: implement this.
+ }
+ // Default case is just to lower a dereference opertion
+ // into another dereference.
RefPtr<DerefExpr> loweredExpr = new DerefExpr();
lowerExprCommon(loweredExpr, expr);
- loweredExpr->base = loweredBase;
- return loweredExpr;
+ loweredExpr->base = loweredBase.getExpr();
+ return LoweredExpr(loweredExpr);
}
DiagnosticSink* getSink()
@@ -1569,7 +1827,7 @@ return loweredExpr;
return &shared->compileRequest->mSink;
}
- RefPtr<ExpressionSyntaxNode> visitMemberExpressionSyntaxNode(
+ LoweredExpr visitMemberExpressionSyntaxNode(
MemberExpressionSyntaxNode* expr)
{
auto loweredBase = lowerExprOrTuple(expr->BaseExpression);
@@ -1578,17 +1836,18 @@ return loweredExpr;
// Are we extracting an element from a tuple?
- if (auto baseTuple = loweredBase.As<TupleExpr>())
+ if (auto baseTuple = loweredBase.asTuple())
{
- auto tupleFieldMod = loweredDeclRef.getDecl()->FindModifier<TupleFieldModifier>();
+ auto loweredFieldDecl = loweredDeclRef.As<Decl>().getDecl();
+ auto tupleFieldMod = loweredFieldDecl->FindModifier<TupleFieldModifier>();
if (tupleFieldMod)
{
// This field has a tuple part to it, so we need to search for it
- RefPtr<ExpressionSyntaxNode> tupleFieldExpr;
+ LoweredExpr tupleFieldExpr;
for (auto elem : baseTuple->tupleElements)
{
- if (loweredDeclRef.getDecl() == elem.tupleFieldDeclRef.getDecl())
+ if (loweredFieldDecl == elem.tupleFieldDeclRef.getDecl())
{
tupleFieldExpr = elem.expr;
break;
@@ -1598,7 +1857,7 @@ return loweredExpr;
if (!tupleFieldMod->hasAnyNonTupleFields)
return tupleFieldExpr;
- auto tupleFieldTupleExpr = tupleFieldExpr.As<TupleExpr>();
+ auto tupleFieldTupleExpr = tupleFieldExpr.asTuple();
SLANG_RELEASE_ASSERT(tupleFieldTupleExpr);
SLANG_RELEASE_ASSERT(!tupleFieldTupleExpr->primaryExpr);
@@ -1606,18 +1865,18 @@ return loweredExpr;
RefPtr<MemberExpressionSyntaxNode> loweredPrimaryExpr = new MemberExpressionSyntaxNode();
lowerExprCommon(loweredPrimaryExpr, expr);
loweredPrimaryExpr->BaseExpression = baseTuple->primaryExpr;
- loweredPrimaryExpr->declRef = loweredDeclRef;
+ loweredPrimaryExpr->declRef = loweredDeclRef.As<Decl>();
loweredPrimaryExpr->name = expr->name;
tupleFieldTupleExpr->primaryExpr = loweredPrimaryExpr;
return tupleFieldTupleExpr;
}
- // If the field was a non-tupe field, then we can
+ // If the field was a non-tuple field, then we can
// simply fall through to the ordinary case below.
- loweredBase = baseTuple->primaryExpr;
+ loweredBase = LoweredExpr(baseTuple->primaryExpr);
}
- else if (auto baseVaryingTuple = loweredBase.As<VaryingTupleExpr>())
+ else if (auto baseVaryingTuple = loweredBase.asVaryingTuple())
{
// Search for the element corresponding to this field
for(auto elem : baseVaryingTuple->elements)
@@ -1633,15 +1892,14 @@ return loweredExpr;
}
// Default handling:
- SLANG_RELEASE_ASSERT(!dynamic_cast<TupleVarDecl*>(loweredDeclRef.getDecl()));
RefPtr<MemberExpressionSyntaxNode> loweredExpr = new MemberExpressionSyntaxNode();
lowerExprCommon(loweredExpr, expr);
- loweredExpr->BaseExpression = loweredBase;
- loweredExpr->declRef = loweredDeclRef;
+ loweredExpr->BaseExpression = loweredBase.getExpr();
+ loweredExpr->declRef = loweredDeclRef.As<Decl>();
loweredExpr->name = expr->name;
- return loweredExpr;
+ return LoweredExpr(loweredExpr);
}
//
@@ -1711,11 +1969,11 @@ return loweredExpr;
StmtVisitor::dispatch(stmt);
}
- RefPtr<ScopeDecl> visitScopeDecl(ScopeDecl* decl)
+ LoweredDecl visitScopeDecl(ScopeDecl* decl)
{
RefPtr<ScopeDecl> loweredDecl = new ScopeDecl();
lowerDeclCommon(loweredDecl, decl);
- return loweredDecl;
+ return LoweredDecl(loweredDecl);
}
LoweringVisitor pushScope(
@@ -1773,31 +2031,10 @@ return loweredExpr;
addStmtImpl(stmtBeingBuilt, stmt);
}
- void addExprStmt(
+ void addSimpleExprStmt(
RefPtr<ExpressionSyntaxNode> expr)
{
- // Desugar tuples in statement position
- if (auto tupleExpr = expr.As<TupleExpr>())
- {
- if (tupleExpr->primaryExpr)
- {
- addExprStmt(tupleExpr->primaryExpr);
- }
- for (auto ee : tupleExpr->tupleElements)
- {
- addExprStmt(ee.expr);
- }
- return;
- }
- else if (auto varyingTupleExpr = expr.As<VaryingTupleExpr>())
- {
- for (auto ee : varyingTupleExpr->elements)
- {
- addExprStmt(ee.expr);
- }
- return;
- }
- else if (auto infixExpr = expr.As<InfixExpr>())
+ if (auto infixExpr = expr.As<InfixExpr>())
{
if (auto varExpr = infixExpr->FunctionExpr.As<VarExpressionSyntaxNode>())
{
@@ -1806,7 +2043,7 @@ return loweredExpr;
// Call to "operator comma"
for (auto aa : infixExpr->Arguments)
{
- addExprStmt(aa);
+ addSimpleExprStmt(aa);
}
return;
}
@@ -1823,6 +2060,36 @@ return loweredExpr;
addStmt(stmt);
}
+ void addExprStmt(
+ LoweredExpr expr)
+ {
+ // Desugar tuples in statement position
+ if (auto tupleExpr = expr.asTuple())
+ {
+ if (tupleExpr->primaryExpr)
+ {
+ addSimpleExprStmt(tupleExpr->primaryExpr);
+ }
+ for (auto ee : tupleExpr->tupleElements)
+ {
+ addExprStmt(ee.expr);
+ }
+ return;
+ }
+ else if (auto varyingTupleExpr = expr.asVaryingTuple())
+ {
+ for (auto ee : varyingTupleExpr->elements)
+ {
+ addExprStmt(ee.expr);
+ }
+ return;
+ }
+ else
+ {
+ addSimpleExprStmt(expr.getExpr());
+ }
+ }
+
void visitBlockStmt(BlockStmt* stmt)
{
RefPtr<BlockStmt> loweredStmt = new BlockStmt();
@@ -2019,9 +2286,9 @@ return loweredExpr;
RefPtr<VaryingTupleVarDecl> loweredVarDecl = new VaryingTupleVarDecl();
loweredVarDecl->Position = varDecl->Position;
loweredVarDecl->Type = varType;
- loweredVarDecl->Expr = constExpr;
+ loweredVarDecl->expr = LoweredExpr(constExpr);
- shared->loweredDecls[varDecl] = loweredVarDecl;
+ shared->loweredDecls[varDecl] = LoweredDecl(loweredVarDecl);
lowerStmtImpl(stmt->body);
}
@@ -2064,22 +2331,22 @@ return loweredExpr;
}
void assign(
- RefPtr<ExpressionSyntaxNode> destExpr,
- RefPtr<ExpressionSyntaxNode> srcExpr,
- AssignMode mode = AssignMode::Default)
+ LoweredExpr destExpr,
+ LoweredExpr srcExpr,
+ AssignMode mode = AssignMode::Default)
{
auto assignExpr = createAssignExpr(destExpr, srcExpr, mode);
addExprStmt(assignExpr);
}
- void assign(VarDeclBase* varDecl, RefPtr<ExpressionSyntaxNode> expr)
+ void assign(VarDeclBase* varDecl, LoweredExpr expr)
{
- assign(createVarRef(expr->Position, varDecl), expr);
+ assign(LoweredExpr(createVarRef(getPosition(expr), varDecl)), expr);
}
- void assign(RefPtr<ExpressionSyntaxNode> expr, VarDeclBase* varDecl)
+ void assign(LoweredExpr expr, VarDeclBase* varDecl)
{
- assign(expr, createVarRef(expr->Position, varDecl));
+ assign(expr, LoweredExpr(createVarRef(getPosition(expr), varDecl)));
}
RefPtr<ExpressionSyntaxNode> createCastExpr(
@@ -2098,20 +2365,20 @@ return loweredExpr;
// where the types don't actually line up, because of
// differences in how something is declared in HLSL vs. GLSL
void assignWithFixups(
- RefPtr<ExpressionSyntaxNode> destExpr,
- RefPtr<ExpressionSyntaxNode> srcExpr)
+ LoweredExpr destExpr,
+ LoweredExpr srcExpr)
{
assign(destExpr, srcExpr, AssignMode::WithFixups);
}
- void assignWithFixups(VarDeclBase* varDecl, RefPtr<ExpressionSyntaxNode> expr)
+ void assignWithFixups(VarDeclBase* varDecl, LoweredExpr expr)
{
- assignWithFixups(createVarRef(expr->Position, varDecl), expr);
+ assignWithFixups(LoweredExpr(createVarRef(getPosition(expr), varDecl)), expr);
}
- void assignWithFixups(RefPtr<ExpressionSyntaxNode> expr, VarDeclBase* varDecl)
+ void assignWithFixups(LoweredExpr expr, VarDeclBase* varDecl)
{
- assignWithFixups(expr, createVarRef(expr->Position, varDecl));
+ assignWithFixups(expr, LoweredExpr(createVarRef(getPosition(expr), varDecl)));
}
void visitReturnStatementSyntaxNode(ReturnStatementSyntaxNode* stmt)
@@ -2173,19 +2440,19 @@ return loweredExpr;
return decl;
}
- DeclRef<Decl> translateDeclRef(
+ LoweredDeclRef translateDeclRef(
DeclRef<Decl> const& decl)
{
- DeclRef<Decl> result;
+ LoweredDeclRef result;
result.decl = translateDeclRef(decl.decl);
result.substitutions = translateSubstitutions(decl.substitutions);
return result;
}
- RefPtr<Decl> translateDeclRef(
+ LoweredDecl translateDeclRef(
Decl* decl)
{
- if (!decl) return nullptr;
+ if (!decl) return LoweredDecl();
// We don't want to translate references to built-in declarations,
// since they won't be subtituted anyway.
@@ -2203,7 +2470,7 @@ return loweredExpr;
if (getModifiedDecl(decl)->HasModifier<BuiltinModifier>())
return decl;
- RefPtr<Decl> loweredDecl;
+ LoweredDecl loweredDecl;
if (shared->loweredDecls.TryGetValue(decl, loweredDecl))
return loweredDecl;
@@ -2214,10 +2481,10 @@ return loweredExpr;
RefPtr<ContainerDecl> translateDeclRef(
ContainerDecl* decl)
{
- return translateDeclRef((Decl*)decl).As<ContainerDecl>();
+ return translateDeclRef((Decl*)decl).getDecl()->As<ContainerDecl>();
}
- RefPtr<DeclBase> lowerDeclBase(
+ LoweredDecl lowerDeclBase(
DeclBase* declBase)
{
if (Decl* decl = dynamic_cast<Decl*>(declBase))
@@ -2230,10 +2497,10 @@ return loweredExpr;
}
}
- RefPtr<Decl> lowerDecl(
+ LoweredDecl lowerDecl(
Decl* decl)
{
- RefPtr<Decl> loweredDecl = DeclVisitor::dispatch(decl).As<Decl>();
+ LoweredDecl loweredDecl = DeclVisitor::dispatch(decl);
return loweredDecl;
}
@@ -2268,11 +2535,11 @@ return loweredExpr;
addMember(parentDecl, decl);
}
- void registerLoweredDecl(Decl* loweredDecl, Decl* decl)
+ void registerLoweredDecl(LoweredDecl loweredDecl, Decl* decl)
{
shared->loweredDecls.Add(decl, loweredDecl);
- shared->mapLoweredDeclToOriginal.Add(loweredDecl, decl);
+ shared->mapLoweredDeclToOriginal.Add(loweredDecl.getValue(), decl);
}
// If the name of the declarations collides with a reserved word
@@ -2366,64 +2633,64 @@ return loweredExpr;
// Catch-all
- RefPtr<Decl> visitModifierDecl(ModifierDecl*)
+ LoweredDecl visitModifierDecl(ModifierDecl*)
{
// should not occur in user code
SLANG_UNEXPECTED("modifiers shouldn't occur in user code");
}
- RefPtr<Decl> visitGenericValueParamDecl(GenericValueParamDecl*)
+ LoweredDecl visitGenericValueParamDecl(GenericValueParamDecl*)
{
SLANG_UNEXPECTED("generics should be lowered to specialized decls");
}
- RefPtr<Decl> visitGenericTypeParamDecl(GenericTypeParamDecl*)
+ LoweredDecl visitGenericTypeParamDecl(GenericTypeParamDecl*)
{
SLANG_UNEXPECTED("generics should be lowered to specialized decls");
}
- RefPtr<Decl> visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*)
+ LoweredDecl visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*)
{
SLANG_UNEXPECTED("generics should be lowered to specialized decls");
}
- RefPtr<Decl> visitGenericDecl(GenericDecl*)
+ LoweredDecl visitGenericDecl(GenericDecl*)
{
SLANG_UNEXPECTED("generics should be lowered to specialized decls");
}
- RefPtr<Decl> visitProgramSyntaxNode(ProgramSyntaxNode*)
+ LoweredDecl visitProgramSyntaxNode(ProgramSyntaxNode*)
{
SLANG_UNEXPECTED("module decls should be lowered explicitly");
}
- RefPtr<Decl> visitSubscriptDecl(SubscriptDecl*)
+ LoweredDecl visitSubscriptDecl(SubscriptDecl*)
{
// We don't expect to find direct references to a subscript
// declaration, but rather to the underlying accessors
- return nullptr;
+ return LoweredDecl();
}
- RefPtr<Decl> visitInheritanceDecl(InheritanceDecl*)
+ LoweredDecl visitInheritanceDecl(InheritanceDecl*)
{
// We should deal with these explicitly, as part of lowering
// the type that contains them.
- return nullptr;
+ return LoweredDecl();
}
- RefPtr<Decl> visitExtensionDecl(ExtensionDecl*)
+ LoweredDecl visitExtensionDecl(ExtensionDecl*)
{
// Extensions won't exist in the lowered code: their members
// will turn into ordinary functions that get called explicitly
- return nullptr;
+ return LoweredDecl();
}
- RefPtr<Decl> visitTypeDefDecl(TypeDefDecl* decl)
+ LoweredDecl visitTypeDefDecl(TypeDefDecl* decl)
{
if (shared->target == CodeGenTarget::GLSL)
{
// GLSL does not support `typedef`, so we will lower it out of existence here
- return nullptr;
+ return LoweredDecl();
}
RefPtr<TypeDefDecl> loweredDecl = new TypeDefDecl();
@@ -2432,10 +2699,10 @@ return loweredExpr;
loweredDecl->Type = lowerType(decl->Type);
addMember(shared->loweredProgram, loweredDecl);
- return loweredDecl;
+ return LoweredDecl(loweredDecl);
}
- RefPtr<ImportDecl> visitImportDecl(ImportDecl*)
+ LoweredDecl visitImportDecl(ImportDecl*)
{
// We could unconditionally output the declarations in the
// imported code, but this could cause problems if any
@@ -2454,10 +2721,10 @@ return loweredExpr;
// Don't actually include a representation of
// the import declaration in the output
- return nullptr;
+ return LoweredDecl();
}
- RefPtr<EmptyDecl> visitEmptyDecl(EmptyDecl* decl)
+ LoweredDecl visitEmptyDecl(EmptyDecl* decl)
{
// Empty declarations are really only useful in GLSL,
// where they are used to hold metadata that doesn't
@@ -2471,7 +2738,7 @@ return loweredExpr;
addDecl(loweredDecl);
- return loweredDecl;
+ return LoweredDecl(loweredDecl);
}
TupleTypeModifier* isTupleType(ExpressionType* type)
@@ -2559,7 +2826,7 @@ return loweredExpr;
for (auto field : decl->getMembersOfType<VarDeclBase>())
{
// We lower the field, which will involve lowering the field type
- auto loweredField = translateDeclRef(field).As<VarDeclBase>();
+ auto loweredField = translateDeclRef(field).getDecl()->As<VarDeclBase>();
// Add the field to the result declaration
addMember(loweredDecl, loweredField);
@@ -2659,6 +2926,7 @@ return loweredExpr;
return loweredDecl;
}
+
RefPtr<VarDeclBase> lowerSimpleVarDeclCommon(
RefPtr<VarDeclBase> loweredDecl,
VarDeclBase* decl)
@@ -2798,7 +3066,7 @@ return loweredExpr;
}
- RefPtr<VarDeclBase> fieldVarOrTupleDecl;
+ LoweredDecl fieldVarOrTupleDecl;
if (auto fieldTupleTypeMod = isTupleTypeOrArrayOfTupleType(fieldType))
{
// If the field is itself a tuple, then recurse
@@ -2818,7 +3086,7 @@ return loweredExpr;
fieldTupleDecl->tupleType = fieldTupleTypeMod;
createTupleTypeSecondaryVarDecls(fieldInfo);
- fieldVarOrTupleDecl = fieldTupleDecl;
+ fieldVarOrTupleDecl = LoweredDecl(fieldTupleDecl);
}
else
{
@@ -2847,18 +3115,21 @@ return loweredExpr;
addModifier(fieldVarDecl, layoutMod);
}
- fieldVarOrTupleDecl = fieldVarDecl;
+ fieldVarOrTupleDecl = LoweredDecl(fieldVarDecl);
}
RefPtr<TupleVarModifier> fieldTupleVarMod = new TupleVarModifier();
fieldTupleVarMod->tupleField = tupleFieldMod;
- addModifier(fieldVarOrTupleDecl, fieldTupleVarMod);
- info.tupleDecl->tupleDecls.Add(fieldVarOrTupleDecl);
+ TupleVarDecl::Element elem;
+ elem.decl = fieldVarOrTupleDecl;
+ elem.tupleVarMod = fieldTupleVarMod;
+
+ info.tupleDecl->tupleDecls.Add(elem);
}
}
- RefPtr<VarDeclBase> createTupleTypeVarDecls(
+ LoweredDecl createTupleTypeVarDecls(
SyntaxClass<VarDeclBase> varDeclClass,
RefPtr<VarDeclBase> originalVarDecl,
String const& name,
@@ -2910,7 +3181,7 @@ return loweredExpr;
createTupleTypeSecondaryVarDecls(info);
- return tupleDecl;
+ return LoweredDecl(tupleDecl);
}
RefPtr<StructTypeLayout> getBodyStructTypeLayout(RefPtr<TypeLayout> typeLayout)
@@ -2936,7 +3207,7 @@ return loweredExpr;
return nullptr;
}
- RefPtr<VarDeclBase> createTupleTypeVarDecls(
+ LoweredDecl createTupleTypeVarDecls(
SyntaxClass<VarDeclBase> varDeclClass,
RefPtr<VarDeclBase> originalVarDecl,
String const& name,
@@ -2964,7 +3235,7 @@ return loweredExpr;
tupleTypeLayout);
}
- RefPtr<VarDeclBase> lowerVarDeclCommonInner(
+ LoweredDecl lowerVarDeclCommonInner(
VarDeclBase* decl,
SyntaxClass<VarDeclBase> loweredDeclClass)
{
@@ -3027,10 +3298,10 @@ return loweredExpr;
auto result = lowerSimpleVarDeclCommon(loweredDecl, decl, loweredType);
addDecl(loweredDecl);
- return result;
+ return LoweredDecl(result);
}
- RefPtr<VarDeclBase> lowerVarDeclCommon(
+ LoweredDecl lowerVarDeclCommon(
VarDeclBase* decl,
SyntaxClass<VarDeclBase> loweredDeclClass)
{
@@ -3141,7 +3412,7 @@ return loweredExpr;
return false;
}
- RefPtr<VarDeclBase> visitVariable(
+ LoweredDecl visitVariable(
Variable* decl)
{
// Global variable? Check if it is a sample-rate input.
@@ -3168,7 +3439,7 @@ return loweredExpr;
// We can't easily support `in out` declarations with this approach
SLANG_RELEASE_ASSERT(!(inRes && outRes));
- RefPtr<ExpressionSyntaxNode> loweredExpr;
+ LoweredExpr loweredExpr;
if (inRes)
{
loweredExpr = lowerShaderParameterToGLSLGLobals(
@@ -3185,54 +3456,54 @@ return loweredExpr;
VaryingParameterDirection::Output);
}
- SLANG_RELEASE_ASSERT(loweredExpr);
+// SLANG_RELEASE_ASSERT(loweredExpr);
auto loweredDecl = createVaryingTupleVarDecl(
decl,
loweredExpr);
- registerLoweredDecl(loweredDecl, decl);
- return loweredDecl;
+ registerLoweredDecl(LoweredDecl(loweredDecl), decl);
+ return LoweredDecl(loweredDecl);
}
}
}
auto loweredDecl = lowerVarDeclCommon(decl, getClass<Variable>());
- if(!loweredDecl)
- return nullptr;
+ if(!loweredDecl.getValue())
+ return LoweredDecl();
return loweredDecl;
}
- RefPtr<VarDeclBase> visitStructField(
+ LoweredDecl visitStructField(
StructField* decl)
{
- return lowerSimpleVarDeclCommon(new StructField(), decl);
+ return LoweredDecl(lowerSimpleVarDeclCommon(new StructField(), decl));
}
- RefPtr<VarDeclBase> visitParameterSyntaxNode(
+ LoweredDecl visitParameterSyntaxNode(
ParameterSyntaxNode* decl)
{
auto loweredDecl = lowerVarDeclCommon(decl, getClass<ParameterSyntaxNode>());
return loweredDecl;
}
- RefPtr<DeclBase> transformSyntaxField(DeclBase* decl)
+ LoweredDecl transformSyntaxField(DeclBase* decl)
{
return lowerDeclBase(decl);
}
- RefPtr<Decl> visitDeclGroup(
+ LoweredDecl visitDeclGroup(
DeclGroup* group)
{
for (auto decl : group->decls)
{
lowerDecl(decl);
}
- return nullptr;
+ return LoweredDecl();
}
- RefPtr<FunctionSyntaxNode> visitFunctionDeclBase(
+ LoweredDecl visitFunctionDeclBase(
FunctionDeclBase* decl)
{
// TODO: need to generate a name
@@ -3265,7 +3536,7 @@ return loweredExpr;
// even if it had been a member function when declared.
addMember(shared->loweredProgram, loweredDecl);
- return loweredDecl;
+ return LoweredDecl(loweredDecl);
}
//
@@ -3458,7 +3729,7 @@ return loweredExpr;
return Slang::getArrayType(elementType, getConstantIntVal(elementCount));
}
- RefPtr<ExpressionSyntaxNode> lowerSimpleShaderParameterToGLSLGlobal(
+ LoweredExpr lowerSimpleShaderParameterToGLSLGlobal(
VaryingParameterInfo const& info,
RefPtr<ExpressionType> varType,
RefPtr<VarLayout> varLayout)
@@ -3736,10 +4007,10 @@ return loweredExpr;
globalVarExpr = globalVarRef;
}
- return globalVarExpr;
+ return LoweredExpr(globalVarExpr);
}
- RefPtr<ExpressionSyntaxNode> lowerShaderParameterToGLSLGLobalsRec(
+ LoweredExpr lowerShaderParameterToGLSLGLobalsRec(
VaryingParameterInfo const& info,
RefPtr<ExpressionType> varType,
RefPtr<VarLayout> varLayout)
@@ -3835,7 +4106,7 @@ return loweredExpr;
}
// Okay, we are done with this parameter
- return tupleExpr;
+ return LoweredExpr(tupleExpr);
}
}
@@ -3843,7 +4114,7 @@ return loweredExpr;
return lowerSimpleShaderParameterToGLSLGlobal(info, varType, varLayout);
}
- RefPtr<ExpressionSyntaxNode> lowerShaderParameterToGLSLGLobals(
+ LoweredExpr lowerShaderParameterToGLSLGLobals(
RefPtr<VarDeclBase> originalVarDecl,
RefPtr<VarLayout> paramLayout,
VaryingParameterDirection direction)
@@ -3893,21 +4164,21 @@ return loweredExpr;
}
RefPtr<VaryingTupleVarDecl> createVaryingTupleVarDecl(
- RefPtr<VarDeclBase> originalVarDecl,
- TypeExp const& loweredType,
- RefPtr<ExpressionSyntaxNode> loweredExpr)
+ RefPtr<VarDeclBase> originalVarDecl,
+ TypeExp const& loweredType,
+ LoweredExpr loweredExpr)
{
RefPtr<VaryingTupleVarDecl> loweredDecl = new VaryingTupleVarDecl();
loweredDecl->Name = originalVarDecl->Name;
loweredDecl->Type = loweredType;
- loweredDecl->Expr = loweredExpr;
+ loweredDecl->expr = loweredExpr;
return loweredDecl;
}
RefPtr<VaryingTupleVarDecl> createVaryingTupleVarDecl(
- RefPtr<VarDeclBase> originalVarDecl,
- RefPtr<ExpressionSyntaxNode> loweredExpr)
+ RefPtr<VarDeclBase> originalVarDecl,
+ LoweredExpr loweredExpr)
{
auto loweredType = lowerType(originalVarDecl->Type);
return createVaryingTupleVarDecl(originalVarDecl, loweredType, loweredExpr);
@@ -3925,7 +4196,7 @@ return loweredExpr;
RefPtr<EntryPointLayout> entryPointLayout)
{
// First, loer the entry-point function as an ordinary function:
- auto loweredEntryPointFunc = visitFunctionDeclBase(entryPointDecl);
+ auto loweredEntryPointFunc = visitFunctionDeclBase(entryPointDecl).getDecl()->As<FunctionDeclBase>();
// Now we will generate a `void main() { ... }` function to call the lowered code.
RefPtr<FunctionSyntaxNode> mainDecl = new FunctionSyntaxNode();
@@ -4007,7 +4278,7 @@ return loweredExpr;
}
// Now generate a call to the entry-point function, using the local variables
- auto entryPointDeclRef = makeDeclRef(loweredEntryPointFunc.Ptr());
+ auto entryPointDeclRef = makeDeclRef(loweredEntryPointFunc);
auto entryPointType = getFuncType(
getSession(),
@@ -4038,12 +4309,12 @@ return loweredExpr;
if (resultVarDecl)
{
// Non-`void` return type, so we need to store it
- subVisitor.assign(resultVarDecl, callExpr);
+ subVisitor.assign(resultVarDecl, LoweredExpr(callExpr));
}
else
{
// `void` return type: just call it
- subVisitor.addExprStmt(callExpr);
+ subVisitor.addExprStmt(LoweredExpr(callExpr));
}
@@ -4079,8 +4350,8 @@ return loweredExpr;
if (shared->requiresCopyGLPositionToPositionPerView)
{
subVisitor.assign(
- createSimpleVarExpr("gl_PositionPerViewNV[0]"),
- createSimpleVarExpr("gl_Position"));
+ LoweredExpr(createSimpleVarExpr("gl_PositionPerViewNV[0]")),
+ LoweredExpr(createSimpleVarExpr("gl_Position")));
}
bodyStmt->body = subVisitor.stmtBeingBuilt;
@@ -4151,7 +4422,7 @@ return loweredExpr;
{
// Default case: lower an entry point just like any other function
default:
- return visitFunctionDeclBase(entryPointDecl);
+ return visitFunctionDeclBase(entryPointDecl).getDecl()->As<FunctionSyntaxNode>();
// For Slang->GLSL translation, we need to lower things from HLSL-style
// declarations over to GLSL conventions
@@ -4276,7 +4547,7 @@ LoweredEntryPoint lowerEntryPoint(
// of the existing translation unit declaration.
visitor.registerLoweredDecl(
- loweredProgram,
+ LoweredDecl(loweredProgram),
translationUnit->SyntaxNode);
// We also need to register the lowered program as the lowered version
@@ -4286,7 +4557,7 @@ LoweredEntryPoint lowerEntryPoint(
{
sharedContext.loweredDecls.Add(
rr,
- loweredProgram);
+ LoweredDecl(loweredProgram));
}
// We also want to remember the layout information for
diff --git a/source/slang/syntax-base-defs.h b/source/slang/syntax-base-defs.h
index eda554988..bcb37de09 100644
--- a/source/slang/syntax-base-defs.h
+++ b/source/slang/syntax-base-defs.h
@@ -10,6 +10,16 @@ ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, RefObject)
// The primary source location associated with this AST node
FIELD(CodePosition, Position)
+
+ RAW(
+ // Allow dynamic casting with a convenient syntax
+ template<typename T>
+ T* As()
+ {
+ return dynamic_cast<T*>(this);
+ }
+ )
+
END_SYNTAX_CLASS()
// Base class for compile-time values (most often a type).