From a0bea07503c68160ad2e88986ba98cfc2161bdff Mon Sep 17 00:00:00 2001 From: Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:28:49 -0400 Subject: Fix several bugs with `specializeWithArgTypes()` (#5365) * Fix several bugs with `specializeWithArgTypes()` * Make all types L-values for the purposes of reflection API resolution --- source/slang/slang.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) (limited to 'source/slang/slang.cpp') diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 313e94439..7949fd9f7 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -1369,16 +1369,68 @@ DeclRef getGenericParentDeclRef( // Create substituted parent decl ref. auto decl = declRef.getDecl(); - while (!as(decl)) + while (decl && !as(decl)) { decl = decl->parentDecl; } + if (!decl) + { + // No generic parent + return DeclRef(); + } + auto genericDecl = as(decl); auto genericDeclRef = createDefaultSubstitutionsIfNeeded(astBuilder, visitor, DeclRef(genericDecl)).as(); return substituteDeclRef(SubstitutionSet(declRef), astBuilder, genericDeclRef).as(); } +bool Linkage::isSpecialized(DeclRef declRef) +{ + // For now, we only support two 'states': fully applied or not at all. + // If we add support for partial specialization, we will need to update this logic. + // + // If it's not specialized, then declRef will be the one with default substitutions. + // + SemanticsVisitor visitor(getSemanticsForReflection()); + + auto decl = declRef.getDecl(); + while (decl && !as(decl)) + { + decl = decl->parentDecl; + } + + if(!decl) + return true; // no generics => always specialized + + auto defaultArgs = getDefaultSubstitutionArgs(getASTBuilder(), &visitor, as(decl)); + auto currentArgs = SubstitutionSet(declRef).findGenericAppDeclRef(as(decl))->getArgs(); + + if (defaultArgs.getCount() != currentArgs.getCount()) // should really never happen. + return true; + + for (Index i = 0; i < defaultArgs.getCount(); ++i) + { + if (defaultArgs[i] != currentArgs[i]) + return true; + } + + return false; +} + +bool isFuncGeneric(DeclRef declRef) +{ + if (auto funcDecl = as(declRef.getDecl())) + { + if (funcDecl->parentDecl && as(funcDecl->parentDecl)) + { + return true; + } + } + + return false; +} + DeclRef Linkage::specializeWithArgTypes( Expr* funcExpr, List argTypes, @@ -1387,16 +1439,22 @@ DeclRef Linkage::specializeWithArgTypes( SemanticsVisitor visitor(getSemanticsForReflection()); visitor = visitor.withSink(sink); - ASTBuilder* astBuilder = getASTBuilder(); + SLANG_AST_BUILDER_RAII(getASTBuilder()); if (auto declRefFuncExpr = as(funcExpr)) { - auto genericDeclRefExpr = astBuilder->create(); - genericDeclRefExpr->declRef = getGenericParentDeclRef( - getASTBuilder(), - &visitor, - declRefFuncExpr->declRef); - funcExpr = genericDeclRefExpr; + if (isFuncGeneric(declRefFuncExpr->declRef) && !isSpecialized(declRefFuncExpr->declRef)) + { + if (auto genericDeclRef = getGenericParentDeclRef( + getCurrentASTBuilder(), + &visitor, + declRefFuncExpr->declRef)) + { + auto genericDeclRefExpr = getCurrentASTBuilder()->create(); + genericDeclRefExpr->declRef = genericDeclRef; + funcExpr = genericDeclRefExpr; + } + } } List argExprs; @@ -1407,17 +1465,19 @@ DeclRef Linkage::specializeWithArgTypes( // Create an 'empty' expr with the given type. Ideally, the expression itself should not matter // only its checked type. // - auto argExpr = astBuilder->create(); + auto argExpr = getCurrentASTBuilder()->create(); argExpr->type = argType; + argExpr->type.isLeftValue = true; argExprs.add(argExpr); } // Construct invoke expr. - auto invokeExpr = astBuilder->create(); + auto invokeExpr = getCurrentASTBuilder()->create(); invokeExpr->functionExpr = funcExpr; invokeExpr->arguments = argExprs; auto checkedInvokeExpr = visitor.CheckInvokeExprWithCheckedOperands(invokeExpr); + return as(as(checkedInvokeExpr)->functionExpr)->declRef; } -- cgit v1.2.3