From a08a3140716b89146bf0a22dc014c5470e90e910 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Tue, 22 Jan 2019 14:57:25 -0800 Subject: Clean up variable declaration class hierarchy (#787) The AST class hierarchy for variable declarations had a few messy bits. First, there are more subclasses of `VarDeclBase` than seem strictly necessary; especially for stuff like `struct` member variable which use `StructField` even for `static` fields (which are effectively globals). Second, the AST node type for the "cases" within an `enum` was made a subclass of `VarDeclBase` for expediency, but this isn't really semantically accurate (and doesn't seem to be paying off much in deduplication of code). This change tries to address both of those problems. First, we replace the existing `Variable` and `StructField` cases with a single `VarDecl` case that covers globals, locals, and member variables. I haven't gone so far as to replace function parameters or generic value parameters, but that might be worth considering as a further clean-up. Second, we change `EnumCaseDecl` to inherit directly from `Decl` instead of `VarDeclBase` and add an explicit case for handling them where they were previously handled as if they were variable declarations (this was done by manually surveying all locations in the code that referenced `VarDeclBase`). --- source/slang/lower-to-ir.cpp | 71 ++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'source/slang/lower-to-ir.cpp') diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 3e981dbc5..082f16b22 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -768,17 +768,17 @@ LoweredValInfo emitCallToDeclRef( } IRInst* getFieldKey( - IRGenContext* context, - DeclRef field) + IRGenContext* context, + DeclRef field) { return getSimpleVal(context, emitDeclRef(context, field, context->irBuilder->getKeyType())); } LoweredValInfo extractField( - IRGenContext* context, - IRType* fieldType, - LoweredValInfo base, - DeclRef field) + IRGenContext* context, + IRType* fieldType, + LoweredValInfo base, + DeclRef field) { IRBuilder* builder = context->irBuilder; @@ -900,7 +900,7 @@ top: auto base = materialize(context, boundMemberInfo->base); auto declRef = boundMemberInfo->declRef; - if( auto fieldDeclRef = declRef.As() ) + if( auto fieldDeclRef = declRef.As() ) { lowered = extractField(context, boundMemberInfo->type, base, fieldDeclRef); goto top; @@ -1871,7 +1871,7 @@ struct ExprLoweringVisitorBase : ExprVisitor auto loweredBase = lowerRValueExpr(context, expr->BaseExpression); auto declRef = expr->declRef; - if (auto fieldDeclRef = declRef.As()) + if (auto fieldDeclRef = declRef.As()) { // Okay, easy enough: we have a reference to a field of a struct type... return extractField(loweredType, loweredBase, fieldDeclRef); @@ -2032,7 +2032,7 @@ struct ExprLoweringVisitorBase : ExprVisitor if (auto aggTypeDeclRef = declRef.As()) { List args; - for (auto ff : getMembersOfType(aggTypeDeclRef)) + for (auto ff : getMembersOfType(aggTypeDeclRef)) { if (ff.getDecl()->HasModifier()) continue; @@ -2050,7 +2050,7 @@ struct ExprLoweringVisitorBase : ExprVisitor UNREACHABLE_RETURN(LoweredValInfo()); } - LoweredValInfo getDefaultVal(StructField* decl) + LoweredValInfo getDefaultVal(VarDeclBase* decl) { if(auto initExpr = decl->initExpr) { @@ -2156,7 +2156,7 @@ struct ExprLoweringVisitorBase : ExprVisitor if (auto aggTypeDeclRef = declRef.As()) { UInt argCounter = 0; - for (auto ff : getMembersOfType(aggTypeDeclRef)) + for (auto ff : getMembersOfType(aggTypeDeclRef)) { if (ff.getDecl()->HasModifier()) continue; @@ -2596,9 +2596,9 @@ struct ExprLoweringVisitorBase : ExprVisitor } LoweredValInfo extractField( - IRType* fieldType, - LoweredValInfo base, - DeclRef field) + IRType* fieldType, + LoweredValInfo base, + DeclRef field) { return Slang::extractField(context, fieldType, base, field); } @@ -3713,7 +3713,7 @@ LoweredValInfo tryGetAddress( // we care about, and then write it back. auto declRef = boundMemberInfo->declRef; - if( auto fieldDeclRef = declRef.As() ) + if( auto fieldDeclRef = declRef.As() ) { auto baseVal = boundMemberInfo->base; auto basePtr = tryGetAddress(context, baseVal, TryGetAddressMode::Aggressive); @@ -3955,7 +3955,7 @@ top: // we care about, and then write it back. auto declRef = boundMemberInfo->declRef; - if( auto fieldDeclRef = declRef.As() ) + if( auto fieldDeclRef = declRef.As() ) { // materialize the base value and move it into // a mutable temporary if needed @@ -4321,7 +4321,7 @@ struct DeclLoweringVisitor : DeclVisitor return LoweredValInfo(); } - bool isGlobalVarDecl(VarDeclBase* decl) + bool isGlobalVarDecl(VarDecl* decl) { auto parent = decl->ParentDecl; if (dynamic_cast(parent)) @@ -4329,11 +4329,31 @@ struct DeclLoweringVisitor : DeclVisitor // Variable declared at global scope? -> Global. return true; } + else if(dynamic_cast(parent)) + { + if(decl->HasModifier()) + { + // A `static` member variable is effectively global. + return true; + } + } + + return false; + } + + bool isMemberVarDecl(VarDecl* decl) + { + auto parent = decl->ParentDecl; + if (dynamic_cast(parent)) + { + // A variable declared inside of an aggregate type declaration is a member. + return true; + } return false; } - LoweredValInfo lowerGlobalShaderParam(VarDeclBase* decl) + LoweredValInfo lowerGlobalShaderParam(VarDecl* decl) { IRType* paramType = lowerType(context, decl->getType()); @@ -4361,7 +4381,7 @@ struct DeclLoweringVisitor : DeclVisitor return paramVal; } - LoweredValInfo lowerGlobalVarDecl(VarDeclBase* decl) + LoweredValInfo lowerGlobalVarDecl(VarDecl* decl) { if(isGlobalShaderParameter(decl)) { @@ -4716,7 +4736,7 @@ struct DeclLoweringVisitor : DeclVisitor lowerType(context, decl->type)); } - LoweredValInfo visitVarDeclBase(VarDeclBase* decl) + LoweredValInfo visitVarDecl(VarDecl* decl) { // Detect global (or effectively global) variables // and handle them differently. @@ -4730,6 +4750,11 @@ struct DeclLoweringVisitor : DeclVisitor return lowerFunctionStaticVarDecl(decl); } + if(isMemberVarDecl(decl)) + { + return lowerMemberVarDecl(decl); + } + // A user-defined variable declaration will usually turn into // an `alloca` operation for the variable's storage, // plus some code to initialize it and then store to the variable. @@ -4838,7 +4863,7 @@ struct DeclLoweringVisitor : DeclVisitor // Emit any generics that should wrap the actual type. emitOuterGenerics(subContext, decl, decl); - return lowerRValueExpr(subContext, decl->initExpr); + return lowerRValueExpr(subContext, decl->tagExpr); } LoweredValInfo visitEnumDecl(EnumDecl* decl) @@ -4902,7 +4927,7 @@ struct DeclLoweringVisitor : DeclVisitor subBuilder->setInsertInto(irStruct); - for (auto fieldDecl : decl->getMembersOfType()) + for (auto fieldDecl : decl->getMembersOfType()) { if (fieldDecl->HasModifier()) { @@ -4946,7 +4971,7 @@ struct DeclLoweringVisitor : DeclVisitor return LoweredValInfo::simple(finishOuterGenerics(subBuilder, irStruct)); } - LoweredValInfo visitStructField(StructField* fieldDecl) + LoweredValInfo lowerMemberVarDecl(VarDecl* fieldDecl) { // Each field declaration in the AST translates into // a "key" that can be used to extract field values -- cgit v1.2.3