From a728612771cdaed66a0bdbfd25f8f250920f0f11 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Wed, 9 Aug 2017 09:16:36 -0700 Subject: 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. --- source/slang/lower.cpp | 1007 +++++++++++++++++++++++++-------------- source/slang/syntax-base-defs.h | 10 + 2 files changed, 649 insertions(+), 368 deletions(-) (limited to 'source') 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 -struct StructuralTransformStmtVisitor - : StructuralTransformVisitorBase - , StmtVisitor, RefPtr> -{ - void transformFields(StatementSyntaxNode*, StatementSyntaxNode*) - { - } - -#define SYNTAX_CLASS(NAME, BASE, ...) \ - RefPtr visit(NAME* obj) { \ - RefPtr 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 RefPtr structuralTransform( StatementSyntaxNode* stmt, @@ -181,34 +147,211 @@ RefPtr 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 primaryDecl; - List> 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 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; + + LoweredDecl getDecl() { return decl; } + + template + DeclRef As() + { + return DeclRef(decl.getDecl(), substitutions).As(); + } +}; + + +// 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 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 tupleVarMod; + LoweredDecl decl; + }; + + TupleTypeModifier* tupleType; + RefPtr primaryDecl; + List 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 tupleFieldDeclRef; - RefPtr expr; + DeclRef 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 originalFieldDeclRef; - RefPtr expr; + DeclRef originalFieldDeclRef; + LoweredExpr expr; }; List 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 loweredProgram; - Dictionary> loweredDecls; - Dictionary mapLoweredDeclToOriginal; + Dictionary loweredDecls; + Dictionary mapLoweredDeclToOriginal; // Work to be done at the very start and end of the entry point RefPtr entryPointInitializeStmt; @@ -300,9 +449,9 @@ void requireGLSLVersion( ProfileVersion version); struct LoweringVisitor - : ExprVisitor> + : ExprVisitor , StmtVisitor - , DeclVisitor> + , DeclVisitor , ValVisitor, RefPtr> { // @@ -562,7 +711,7 @@ struct LoweringVisitor auto loweredDeclRef = translateDeclRef(type->declRef); return DeclRefType::Create( type->getSession(), - loweredDeclRef); + loweredDeclRef.As()); } RefPtr visitNamedExpressionType(NamedExpressionType* type) @@ -600,10 +749,10 @@ struct LoweringVisitor // Expressions // - RefPtr 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 loweredExpr, - RefPtr 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 createUncheckedVarRef( char const* name) { @@ -644,30 +803,41 @@ struct LoweringVisitor return result; } - RefPtr createVarRef( + RefPtr createSimpleVarRef( CodePosition const& loc, VarDeclBase* decl) { - if (auto tupleDecl = dynamic_cast(decl)) - { - return createTupleRef(loc, tupleDecl); - } - else if (auto varyingTupleDecl = dynamic_cast(decl)) - { - return createVaryingTupleRef(loc, varyingTupleDecl); - } - else + RefPtr 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 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())); + + 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 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(); + 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 createVaryingTupleRef( - CodePosition const& loc, + LoweredExpr createVaryingTupleRef( + CodePosition const& /*loc*/, VaryingTupleVarDecl* decl) { - return decl->Expr; + return decl->expr; } - RefPtr 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(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(loweredDecl)) + else if (auto varyingTupleVarDecl = loweredDecl.asVaryingTupleDecl()) { return createVaryingTupleRef(expr->Position, varyingTupleVarDecl); } RefPtr loweredExpr = new VarExpressionSyntaxNode(); lowerExprCommon(loweredExpr, expr); - loweredExpr->declRef = loweredDeclRef; + loweredExpr->declRef = loweredDeclRef.As(); 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 maybeMoveTemp( - RefPtr 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()) + if (dynamic_cast(expr)) return expr; - if (expr.As()) + if (dynamic_cast(expr)) return expr; - if (auto varyingTupleExpr = expr.As()) + // In the general case, though, we need to introduce a temporary + return moveTemp(expr); + } + + LoweredExpr maybeMoveTemp( + LoweredExpr expr) + { + if (auto tupleExpr = expr.asTuple()) + { + RefPtr 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 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 ensureSimpleLValue( - RefPtr 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 createAssignExpr( - RefPtr leftExpr, - RefPtr rightExpr, - AssignMode mode = AssignMode::Default) + RefPtr createSimpleAssignExpr( + ExpressionSyntaxNode* leftExpr, + ExpressionSyntaxNode* rightExpr, + AssignMode mode) { - auto leftTuple = leftExpr.As(); - auto rightTuple = rightExpr.As(); + 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 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(); - auto rightVaryingTuple = rightExpr.As(); + auto leftVaryingTuple = leftExpr.asVaryingTuple(); + auto rightVaryingTuple = rightExpr.asVaryingTuple(); + + RefPtr leftSimpleExpr = leftExpr.asExpr(); + RefPtr rightSimpleExpr = rightExpr.asExpr(); + if (leftVaryingTuple && rightVaryingTuple) { RefPtr 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 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 resultExpr = leftExpr; for (UInt ee = 0; ee < elementCount; ++ee) { - auto leftElem = leftVaryingTuple->elements[elementCount - ee - 1]; + auto leftElem = leftVaryingTuple->elements[ee]; + RefPtr 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 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 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 resultExpr = leftExpr; for (UInt ee = 0; ee < elementCount; ++ee) { - auto rightElem = rightVaryingTuple->elements[elementCount - ee - 1]; + auto rightElem = rightVaryingTuple->elements[ee]; + RefPtr 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 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 visitAssignExpr( + LoweredExpr visitAssignExpr( AssignExpr* expr) { auto leftExpr = lowerExprOrTuple(expr->left); @@ -1247,24 +1465,38 @@ struct LoweringVisitor return nullptr; } - RefPtr createSubscriptExpr( + RefPtr createSimpleSubscriptExpr( RefPtr baseExpr, RefPtr 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 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()) + 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()) + 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 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()) + if (auto baseTuple = baseExpr.asTuple()) { return createSubscriptExpr(baseExpr, indexExpr); } - else if (auto baseVaryingTuple = baseExpr.As()) + else if (auto baseVaryingTuple = baseExpr.asVaryingTuple()) { return createSubscriptExpr(baseExpr, indexExpr); } @@ -1335,21 +1562,21 @@ return loweredExpr; // Default case: just reconstrut a subscript expr RefPtr loweredExpr = new IndexExpressionSyntaxNode(); lowerExprCommon(loweredExpr, subscriptExpr); - loweredExpr->BaseExpression = baseExpr; + loweredExpr->BaseExpression = baseExpr.getExpr(); loweredExpr->IndexExpression = indexExpr; - return loweredExpr; + return LoweredExpr(loweredExpr); } } RefPtr maybeReifyTuple( - RefPtr expr) + LoweredExpr expr) { - if (auto tupleExpr = expr.As()) + if (auto tupleExpr = expr.asTuple()) { // TODO: need to diagnose - return expr; + return tupleExpr->primaryExpr; } - else if (auto varyingTupleExpr = expr.As()) + 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 argExpr) { - if (auto argTuple = argExpr.As()) + // 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()) + 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 visitInvokeExpressionSyntaxNode( + LoweredExpr visitInvokeExpressionSyntaxNode( InvokeExpressionSyntaxNode* expr) { - return lowerCallExpr(new InvokeExpressionSyntaxNode(), expr); + return LoweredExpr(lowerCallExpr(new InvokeExpressionSyntaxNode(), expr)); } - RefPtr visitInfixExpr( + LoweredExpr visitInfixExpr( InfixExpr* expr) { - return lowerCallExpr(new InfixExpr(), expr); + return LoweredExpr(lowerCallExpr(new InfixExpr(), expr)); } - RefPtr visitPrefixExpr( + LoweredExpr visitPrefixExpr( PrefixExpr* expr) { - return lowerCallExpr(new PrefixExpr(), expr); + return LoweredExpr(lowerCallExpr(new PrefixExpr(), expr)); } - RefPtr 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 visitPostfixExpr( + LoweredExpr visitPostfixExpr( PostfixExpr* expr) { - return lowerCallExpr(new PostfixExpr(), expr); + return LoweredExpr(lowerCallExpr(new PostfixExpr(), expr)); } - RefPtr visitDerefExpr( + LoweredExpr visitDerefExpr( DerefExpr* expr) { auto loweredBase = lowerExprOrTuple(expr->base); - if (auto baseTuple = loweredBase.As()) + 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 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 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 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()) + if (auto baseTuple = loweredBase.asTuple()) { - auto tupleFieldMod = loweredDeclRef.getDecl()->FindModifier(); + auto loweredFieldDecl = loweredDeclRef.As().getDecl(); + auto tupleFieldMod = loweredFieldDecl->FindModifier(); if (tupleFieldMod) { // This field has a tuple part to it, so we need to search for it - RefPtr 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(); + auto tupleFieldTupleExpr = tupleFieldExpr.asTuple(); SLANG_RELEASE_ASSERT(tupleFieldTupleExpr); SLANG_RELEASE_ASSERT(!tupleFieldTupleExpr->primaryExpr); @@ -1606,18 +1865,18 @@ return loweredExpr; RefPtr loweredPrimaryExpr = new MemberExpressionSyntaxNode(); lowerExprCommon(loweredPrimaryExpr, expr); loweredPrimaryExpr->BaseExpression = baseTuple->primaryExpr; - loweredPrimaryExpr->declRef = loweredDeclRef; + loweredPrimaryExpr->declRef = loweredDeclRef.As(); 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()) + 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(loweredDeclRef.getDecl())); RefPtr loweredExpr = new MemberExpressionSyntaxNode(); lowerExprCommon(loweredExpr, expr); - loweredExpr->BaseExpression = loweredBase; - loweredExpr->declRef = loweredDeclRef; + loweredExpr->BaseExpression = loweredBase.getExpr(); + loweredExpr->declRef = loweredDeclRef.As(); loweredExpr->name = expr->name; - return loweredExpr; + return LoweredExpr(loweredExpr); } // @@ -1711,11 +1969,11 @@ return loweredExpr; StmtVisitor::dispatch(stmt); } - RefPtr visitScopeDecl(ScopeDecl* decl) + LoweredDecl visitScopeDecl(ScopeDecl* decl) { RefPtr 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 expr) { - // Desugar tuples in statement position - if (auto tupleExpr = expr.As()) - { - if (tupleExpr->primaryExpr) - { - addExprStmt(tupleExpr->primaryExpr); - } - for (auto ee : tupleExpr->tupleElements) - { - addExprStmt(ee.expr); - } - return; - } - else if (auto varyingTupleExpr = expr.As()) - { - for (auto ee : varyingTupleExpr->elements) - { - addExprStmt(ee.expr); - } - return; - } - else if (auto infixExpr = expr.As()) + if (auto infixExpr = expr.As()) { if (auto varExpr = infixExpr->FunctionExpr.As()) { @@ -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 loweredStmt = new BlockStmt(); @@ -2019,9 +2286,9 @@ return loweredExpr; RefPtr 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 destExpr, - RefPtr 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 expr) + void assign(VarDeclBase* varDecl, LoweredExpr expr) { - assign(createVarRef(expr->Position, varDecl), expr); + assign(LoweredExpr(createVarRef(getPosition(expr), varDecl)), expr); } - void assign(RefPtr expr, VarDeclBase* varDecl) + void assign(LoweredExpr expr, VarDeclBase* varDecl) { - assign(expr, createVarRef(expr->Position, varDecl)); + assign(expr, LoweredExpr(createVarRef(getPosition(expr), varDecl))); } RefPtr 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 destExpr, - RefPtr srcExpr) + LoweredExpr destExpr, + LoweredExpr srcExpr) { assign(destExpr, srcExpr, AssignMode::WithFixups); } - void assignWithFixups(VarDeclBase* varDecl, RefPtr expr) + void assignWithFixups(VarDeclBase* varDecl, LoweredExpr expr) { - assignWithFixups(createVarRef(expr->Position, varDecl), expr); + assignWithFixups(LoweredExpr(createVarRef(getPosition(expr), varDecl)), expr); } - void assignWithFixups(RefPtr 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 translateDeclRef( + LoweredDeclRef translateDeclRef( DeclRef const& decl) { - DeclRef result; + LoweredDeclRef result; result.decl = translateDeclRef(decl.decl); result.substitutions = translateSubstitutions(decl.substitutions); return result; } - RefPtr 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()) return decl; - RefPtr loweredDecl; + LoweredDecl loweredDecl; if (shared->loweredDecls.TryGetValue(decl, loweredDecl)) return loweredDecl; @@ -2214,10 +2481,10 @@ return loweredExpr; RefPtr translateDeclRef( ContainerDecl* decl) { - return translateDeclRef((Decl*)decl).As(); + return translateDeclRef((Decl*)decl).getDecl()->As(); } - RefPtr lowerDeclBase( + LoweredDecl lowerDeclBase( DeclBase* declBase) { if (Decl* decl = dynamic_cast(declBase)) @@ -2230,10 +2497,10 @@ return loweredExpr; } } - RefPtr lowerDecl( + LoweredDecl lowerDecl( Decl* decl) { - RefPtr loweredDecl = DeclVisitor::dispatch(decl).As(); + 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 visitModifierDecl(ModifierDecl*) + LoweredDecl visitModifierDecl(ModifierDecl*) { // should not occur in user code SLANG_UNEXPECTED("modifiers shouldn't occur in user code"); } - RefPtr visitGenericValueParamDecl(GenericValueParamDecl*) + LoweredDecl visitGenericValueParamDecl(GenericValueParamDecl*) { SLANG_UNEXPECTED("generics should be lowered to specialized decls"); } - RefPtr visitGenericTypeParamDecl(GenericTypeParamDecl*) + LoweredDecl visitGenericTypeParamDecl(GenericTypeParamDecl*) { SLANG_UNEXPECTED("generics should be lowered to specialized decls"); } - RefPtr visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*) + LoweredDecl visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*) { SLANG_UNEXPECTED("generics should be lowered to specialized decls"); } - RefPtr visitGenericDecl(GenericDecl*) + LoweredDecl visitGenericDecl(GenericDecl*) { SLANG_UNEXPECTED("generics should be lowered to specialized decls"); } - RefPtr visitProgramSyntaxNode(ProgramSyntaxNode*) + LoweredDecl visitProgramSyntaxNode(ProgramSyntaxNode*) { SLANG_UNEXPECTED("module decls should be lowered explicitly"); } - RefPtr 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 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 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 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 loweredDecl = new TypeDefDecl(); @@ -2432,10 +2699,10 @@ return loweredExpr; loweredDecl->Type = lowerType(decl->Type); addMember(shared->loweredProgram, loweredDecl); - return loweredDecl; + return LoweredDecl(loweredDecl); } - RefPtr 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 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()) { // We lower the field, which will involve lowering the field type - auto loweredField = translateDeclRef(field).As(); + auto loweredField = translateDeclRef(field).getDecl()->As(); // Add the field to the result declaration addMember(loweredDecl, loweredField); @@ -2659,6 +2926,7 @@ return loweredExpr; return loweredDecl; } + RefPtr lowerSimpleVarDeclCommon( RefPtr loweredDecl, VarDeclBase* decl) @@ -2798,7 +3066,7 @@ return loweredExpr; } - RefPtr 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 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 createTupleTypeVarDecls( + LoweredDecl createTupleTypeVarDecls( SyntaxClass varDeclClass, RefPtr originalVarDecl, String const& name, @@ -2910,7 +3181,7 @@ return loweredExpr; createTupleTypeSecondaryVarDecls(info); - return tupleDecl; + return LoweredDecl(tupleDecl); } RefPtr getBodyStructTypeLayout(RefPtr typeLayout) @@ -2936,7 +3207,7 @@ return loweredExpr; return nullptr; } - RefPtr createTupleTypeVarDecls( + LoweredDecl createTupleTypeVarDecls( SyntaxClass varDeclClass, RefPtr originalVarDecl, String const& name, @@ -2964,7 +3235,7 @@ return loweredExpr; tupleTypeLayout); } - RefPtr lowerVarDeclCommonInner( + LoweredDecl lowerVarDeclCommonInner( VarDeclBase* decl, SyntaxClass loweredDeclClass) { @@ -3027,10 +3298,10 @@ return loweredExpr; auto result = lowerSimpleVarDeclCommon(loweredDecl, decl, loweredType); addDecl(loweredDecl); - return result; + return LoweredDecl(result); } - RefPtr lowerVarDeclCommon( + LoweredDecl lowerVarDeclCommon( VarDeclBase* decl, SyntaxClass loweredDeclClass) { @@ -3141,7 +3412,7 @@ return loweredExpr; return false; } - RefPtr 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 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()); - if(!loweredDecl) - return nullptr; + if(!loweredDecl.getValue()) + return LoweredDecl(); return loweredDecl; } - RefPtr visitStructField( + LoweredDecl visitStructField( StructField* decl) { - return lowerSimpleVarDeclCommon(new StructField(), decl); + return LoweredDecl(lowerSimpleVarDeclCommon(new StructField(), decl)); } - RefPtr visitParameterSyntaxNode( + LoweredDecl visitParameterSyntaxNode( ParameterSyntaxNode* decl) { auto loweredDecl = lowerVarDeclCommon(decl, getClass()); return loweredDecl; } - RefPtr transformSyntaxField(DeclBase* decl) + LoweredDecl transformSyntaxField(DeclBase* decl) { return lowerDeclBase(decl); } - RefPtr visitDeclGroup( + LoweredDecl visitDeclGroup( DeclGroup* group) { for (auto decl : group->decls) { lowerDecl(decl); } - return nullptr; + return LoweredDecl(); } - RefPtr 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 lowerSimpleShaderParameterToGLSLGlobal( + LoweredExpr lowerSimpleShaderParameterToGLSLGlobal( VaryingParameterInfo const& info, RefPtr varType, RefPtr varLayout) @@ -3736,10 +4007,10 @@ return loweredExpr; globalVarExpr = globalVarRef; } - return globalVarExpr; + return LoweredExpr(globalVarExpr); } - RefPtr lowerShaderParameterToGLSLGLobalsRec( + LoweredExpr lowerShaderParameterToGLSLGLobalsRec( VaryingParameterInfo const& info, RefPtr varType, RefPtr 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 lowerShaderParameterToGLSLGLobals( + LoweredExpr lowerShaderParameterToGLSLGLobals( RefPtr originalVarDecl, RefPtr paramLayout, VaryingParameterDirection direction) @@ -3893,21 +4164,21 @@ return loweredExpr; } RefPtr createVaryingTupleVarDecl( - RefPtr originalVarDecl, - TypeExp const& loweredType, - RefPtr loweredExpr) + RefPtr originalVarDecl, + TypeExp const& loweredType, + LoweredExpr loweredExpr) { RefPtr loweredDecl = new VaryingTupleVarDecl(); loweredDecl->Name = originalVarDecl->Name; loweredDecl->Type = loweredType; - loweredDecl->Expr = loweredExpr; + loweredDecl->expr = loweredExpr; return loweredDecl; } RefPtr createVaryingTupleVarDecl( - RefPtr originalVarDecl, - RefPtr loweredExpr) + RefPtr originalVarDecl, + LoweredExpr loweredExpr) { auto loweredType = lowerType(originalVarDecl->Type); return createVaryingTupleVarDecl(originalVarDecl, loweredType, loweredExpr); @@ -3925,7 +4196,7 @@ return loweredExpr; RefPtr entryPointLayout) { // First, loer the entry-point function as an ordinary function: - auto loweredEntryPointFunc = visitFunctionDeclBase(entryPointDecl); + auto loweredEntryPointFunc = visitFunctionDeclBase(entryPointDecl).getDecl()->As(); // Now we will generate a `void main() { ... }` function to call the lowered code. RefPtr 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(); // 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 + T* As() + { + return dynamic_cast(this); + } + ) + END_SYNTAX_CLASS() // Base class for compile-time values (most often a type). -- cgit v1.2.3