diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/lower.cpp | 1007 | ||||
| -rw-r--r-- | source/slang/syntax-base-defs.h | 10 |
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). |
