diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 10 | ||||
| -rw-r--r-- | source/slang/slang-check-shader.cpp | 86 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 31 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-decl-defs.h | 5 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 14 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 42 | ||||
| -rw-r--r-- | source/slang/slang-parser.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-syntax.h | 3 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 6 |
14 files changed, 189 insertions, 40 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 879f1c5fa..3e0a1c618 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -49,6 +49,11 @@ namespace Slang checkVarDeclCommon(varDecl); } + void visitGlobalGenericValueParamDecl(GlobalGenericValueParamDecl* decl) + { + checkVarDeclCommon(decl); + } + void visitImportDecl(ImportDecl* decl); void visitGenericTypeParamDecl(GenericTypeParamDecl* decl); @@ -114,6 +119,11 @@ namespace Slang checkVarDeclCommon(varDecl); } + void visitGlobalGenericValueParamDecl(GlobalGenericValueParamDecl* decl) + { + checkVarDeclCommon(decl); + } + void visitEnumCaseDecl(EnumCaseDecl* decl); void visitEnumDecl(EnumDecl* decl); diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 333690b36..c229e8f96 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -52,7 +52,8 @@ namespace Slang /// Recursively walk `type` and add any existential/interface specialization parameters to `ioSpecializationParams`. static void _collectExistentialSpecializationParamsRec( SpecializationParams& ioSpecializationParams, - Type* type) + Type* type, + SourceLoc loc) { // Whether or not something is an array does not affect // the number of existential slots it introduces. @@ -66,7 +67,8 @@ namespace Slang { _collectExistentialSpecializationParamsRec( ioSpecializationParams, - parameterGroupType->getElementType()); + parameterGroupType->getElementType(), + loc); return; } @@ -81,6 +83,7 @@ namespace Slang // SpecializationParam specializationParam; specializationParam.flavor = SpecializationParam::Flavor::ExistentialType; + specializationParam.loc = loc; specializationParam.object = type; ioSpecializationParams.add(specializationParam); } @@ -112,7 +115,8 @@ namespace Slang { _collectExistentialSpecializationParamsRec( ioSpecializationParams, - GetType(paramDeclRef)); + GetType(paramDeclRef), + paramDeclRef.getLoc()); } @@ -147,6 +151,7 @@ namespace Slang { SpecializationParam param; param.flavor = SpecializationParam::Flavor::GenericType; + param.loc = genericTypeParam->loc; param.object = genericTypeParam; m_genericSpecializationParams.add(param); } @@ -154,6 +159,7 @@ namespace Slang { SpecializationParam param; param.flavor = SpecializationParam::Flavor::GenericValue; + param.loc = genericValParam->loc; param.object = genericValParam; m_genericSpecializationParams.add(param); } @@ -1020,9 +1026,21 @@ static bool doesParameterMatch( // SpecializationParam specializationParam; specializationParam.flavor = SpecializationParam::Flavor::GenericType; + specializationParam.loc = globalGenericParam->loc; specializationParam.object = globalGenericParam; m_specializationParams.add(specializationParam); } + else if( auto globalGenericValueParam = as<GlobalGenericValueParamDecl>(globalDecl) ) + { + // A global generic type parameter declaration introduces + // a suitable specialization parameter. + // + SpecializationParam specializationParam; + specializationParam.flavor = SpecializationParam::Flavor::GenericValue; + specializationParam.loc = globalGenericValueParam->loc; + specializationParam.object = globalGenericValueParam; + m_specializationParams.add(specializationParam); + } else if( auto importDecl = as<ImportDecl>(globalDecl) ) { // An `import` declaration creates a requirement dependency @@ -1425,9 +1443,6 @@ static bool doesParameterMatch( auto& arg = args[ii]; auto& param = m_specializationParams[ii]; - auto argType = arg.val.as<Type>(); - SLANG_ASSERT(argType); - switch( param.flavor ) { case SpecializationParam::Flavor::GenericType: @@ -1435,6 +1450,13 @@ static bool doesParameterMatch( auto genericTypeParamDecl = param.object.as<GlobalGenericParamDecl>(); SLANG_ASSERT(genericTypeParamDecl); + RefPtr<Type> argType = as<Type>(arg.val); + if(!argType) + { + sink->diagnose(param.loc, Diagnostics::expectedTypeForSpecializationArg, genericTypeParamDecl); + argType = getLinkage()->getSessionImpl()->getErrorType(); + } + // TODO: There is a serious flaw to this checking logic if we ever have cases where // the constraints on one `type_param` can depend on another `type_param`, e.g.: // @@ -1520,6 +1542,13 @@ static bool doesParameterMatch( auto interfaceType = param.object.as<Type>(); SLANG_ASSERT(interfaceType); + RefPtr<Type> argType = as<Type>(arg.val); + if(!argType) + { + sink->diagnose(param.loc, Diagnostics::expectedTypeForSpecializationArg, interfaceType); + argType = getLinkage()->getSessionImpl()->getErrorType(); + } + auto witness = visitor.tryGetSubtypeWitness(argType, interfaceType); if (!witness) { @@ -1539,6 +1568,29 @@ static bool doesParameterMatch( } break; + case SpecializationParam::Flavor::GenericValue: + { + auto paramDecl = param.object.as<GlobalGenericValueParamDecl>(); + SLANG_ASSERT(paramDecl); + + // Now we need to check that the argument `Val` has the + // appropriate type expected by the parameter. + + RefPtr<IntVal> intVal = as<IntVal>(arg.val); + if(!intVal) + { + sink->diagnose(param.loc, Diagnostics::expectedValueOfTypeForSpecializationArg, paramDecl->getType(), paramDecl); + intVal = new ConstantIntVal(0); + } + + ModuleSpecializationInfo::GenericArgInfo expandedArg; + expandedArg.paramDecl = paramDecl; + expandedArg.argVal = intVal; + + specializationInfo->genericArgs.add(expandedArg); + } + break; + default: SLANG_UNEXPECTED("unhandled specialization parameter flavor"); } @@ -1556,27 +1608,17 @@ static bool doesParameterMatch( { auto linkage = componentType->getLinkage(); + SharedSemanticsContext semanticsContext(linkage, sink); + SemanticsVisitor semanticsVisitor(&semanticsContext); + auto argCount = argExprs.getCount(); for(Index ii = 0; ii < argCount; ++ii ) { auto argExpr = argExprs[ii]; auto paramInfo = componentType->getSpecializationParam(ii); - // TODO: We should support non-type arguments here - - auto argType = checkProperType(linkage, TypeExp(argExpr), sink); - if( !argType ) - { - // If no witness was found, then we will be unable to satisfy - // the conformances required. - sink->diagnose(argExpr, - Diagnostics::expectedAType, - argExpr->type); - continue; - } - SpecializationArg arg; - arg.val = argType; + arg.val = semanticsVisitor.ExtractGenericArgVal(argExpr); outArgs.add(arg); } } @@ -1757,7 +1799,7 @@ static bool doesParameterMatch( RefPtr<Expr> argExpr; for (auto & s : scopesToTry) { - argExpr = linkage->parseTypeString(name, s); + argExpr = linkage->parseTermString(name, s); argExpr = semantics.CheckTerm(argExpr); if( argExpr ) { @@ -1790,7 +1832,7 @@ static bool doesParameterMatch( SemanticsVisitor visitor(&sharedSemanticsContext); SpecializationParams specializationParams; - _collectExistentialSpecializationParamsRec(specializationParams, unspecializedType); + _collectExistentialSpecializationParamsRec(specializationParams, unspecializedType, SourceLoc()); assert(specializationParams.getCount() == argCount); diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 2ab376181..3cfb845d7 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -2382,6 +2382,37 @@ SlangResult dissassembleDXILUsingDXC( BackEndCompileRequest* compileRequest, EndToEndCompileRequest* endToEndReq) { + // If we are about to generate output code, but we still + // have unspecialized generic/existential parameters, + // then there is a problem. + // + auto program = compileRequest->getProgram(); + auto specializationParamCount = program->getSpecializationParamCount(); + if( specializationParamCount != 0 ) + { + auto sink = compileRequest->getSink(); + + for( Index ii = 0; ii < specializationParamCount; ++ii ) + { + auto specializationParam = program->getSpecializationParam(ii); + if( auto decl = as<Decl>(specializationParam.object) ) + { + sink->diagnose(specializationParam.loc, Diagnostics::specializationParameterOfNameNotSpecialized, decl); + } + else if( auto type = as<Type>(specializationParam.object) ) + { + sink->diagnose(specializationParam.loc, Diagnostics::specializationParameterOfNameNotSpecialized, type); + } + else + { + sink->diagnose(specializationParam.loc, Diagnostics::specializationParameterNotSpecialized); + } + } + + return; + } + + // Go through the code-generation targets that the user // has specified, and generate code for each of them. // diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 69513ada6..a628e86a3 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1206,7 +1206,7 @@ namespace Slang /// SlangResult loadFile(String const& path, PathInfo& outPathInfo, ISlangBlob** outBlob); - RefPtr<Expr> parseTypeString(String typeStr, RefPtr<Scope> scope); + RefPtr<Expr> parseTermString(String str, RefPtr<Scope> scope); Type* specializeType( Type* unspecializedType, diff --git a/source/slang/slang-decl-defs.h b/source/slang/slang-decl-defs.h index 04c733aac..0e3159910 100644 --- a/source/slang/slang-decl-defs.h +++ b/source/slang/slang-decl-defs.h @@ -180,6 +180,11 @@ END_SYNTAX_CLASS() SYNTAX_CLASS(GlobalGenericParamDecl, AggTypeDecl) END_SYNTAX_CLASS() +// A `__generic_value_param` declaration, which defines an existential +// value parameter (not a type parameter. +SYNTAX_CLASS(GlobalGenericValueParamDecl, VarDeclBase) +END_SYNTAX_CLASS() + // A scope for local declarations (e.g., as part of a statement) SIMPLE_SYNTAX_CLASS(ScopeDecl, ContainerDecl) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 485f463e8..4e48cc95b 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -363,11 +363,16 @@ DIAGNOSTIC(38002, Note, entryPointCandidate, "see candidate declaration for entr DIAGNOSTIC(38003, Error, entryPointSymbolNotAFunction, "entry point '$0' must be declared as a function") DIAGNOSTIC(38004, Error, entryPointTypeParameterNotFound, "no type found matching entry-point type parameter name '$0'") -DIAGNOSTIC(38005, Error, globalGenericArgumentNotAType, "argument for global generic parameter '$0' must be a type") +DIAGNOSTIC(38005, Error, expectedTypeForSpecializationArg, "expected a type as argument for specialization parameter '$0'") DIAGNOSTIC(38006, Warning, specifiedStageDoesntMatchAttribute, "entry point '$0' being compiled for the '$1' stage has a '[shader(...)]' attribute that specifies the '$2' stage") DIAGNOSTIC(38007, Error, entryPointHasNoStage, "no stage specified for entry point '$0'; use either a '[shader(\"name\")]' function attribute or the '-stage <name>' command-line option to specify a stage") +DIAGNOSTIC(38008, Error, specializationParameterOfNameNotSpecialized, "no specialization argument was provided for specialization parameter '$0'") +DIAGNOSTIC(38008, Error, specializationParameterNotSpecialized, "no specialization argument was provided for specialization parameter") + +DIAGNOSTIC(38009, Error, expectedValueOfTypeForSpecializationArg, "expected a constant value of type '$0' as argument for specialization parameter '$1'") + DIAGNOSTIC(38100, Error, typeDoesntImplementInterfaceRequirement, "type '$0' does not provide required interface member '$1'") DIAGNOSTIC(38101, Error, thisExpressionOutsideOfTypeDecl, "'this' expression can only be used in members of an aggregate type") DIAGNOSTIC(38102, Error, initializerNotInsideType, "an 'init' declaration is only allowed inside a type or 'extension' declaration") @@ -388,7 +393,6 @@ DIAGNOSTIC(38025, Error, mismatchSpecializationArguments, "expected $0 specializ DIAGNOSTIC(38026, Error, globalTypeArgumentDoesNotConformToInterface, "type argument `$1` for global generic parameter `$0` does not conform to interface `$2`.") DIAGNOSTIC(38027, Error, mismatchExistentialSlotArgCount, "expected $0 existential slot arguments ($1 provided)") -DIAGNOSTIC(38028, Error, existentialSlotArgNotAType, "existential slot argument $0 was not a type") DIAGNOSTIC(38029, Error,typeArgumentDoesNotConformToInterface, "type argument '$0' does not conform to the required interface '$1'") DIAGNOSTIC(38200, Error, recursiveModuleImport, "module `$0` recursively imports itself") diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index b6a3c3e93..79f8e2b80 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -1926,7 +1926,18 @@ struct IRBuilder UInt caseArgCount, IRInst* const* caseArgs); - IRGlobalGenericParam* emitGlobalGenericParam(); + IRGlobalGenericParam* emitGlobalGenericParam( + IRType* type); + + IRGlobalGenericParam* emitGlobalGenericTypeParam() + { + return emitGlobalGenericParam(getTypeKind()); + } + + IRGlobalGenericParam* emitGlobalGenericWitnessTableParam() + { + return emitGlobalGenericParam(getWitnessTableType()); + } IRBindGlobalGenericParam* emitBindGlobalGenericParam( IRInst* param, diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 80b0cd39e..59cc625f5 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -552,7 +552,7 @@ IRGlobalGenericParam* cloneGlobalGenericParamImpl( IRGlobalGenericParam* originalVal, IROriginalValuesForClone const& originalValues) { - auto clonedVal = builder->emitGlobalGenericParam(); + auto clonedVal = builder->emitGlobalGenericParam(originalVal->getFullType()); cloneSimpleGlobalValueImpl(context, originalVal, originalValues, clonedVal); return clonedVal; } diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 31224fde2..a30445682 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -3328,12 +3328,13 @@ namespace Slang return inst; } - IRGlobalGenericParam* IRBuilder::emitGlobalGenericParam() + IRGlobalGenericParam* IRBuilder::emitGlobalGenericParam( + IRType* type) { IRGlobalGenericParam* irGenericParam = createInst<IRGlobalGenericParam>( this, kIROp_GlobalGenericParam, - nullptr); + type); addGlobalValue(this, irGenericParam); return irGenericParam; } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index e2689ffd1..ac02e1dfd 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -4211,7 +4211,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // This is a constraint on a global generic type parameters, // and so it should lower as a parameter of its own. - auto inst = getBuilder()->emitGlobalGenericParam(); + auto inst = getBuilder()->emitGlobalGenericWitnessTableParam(); addLinkageDecoration(context, inst, decl); return LoweredValInfo::simple(inst); } @@ -4227,11 +4227,21 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> LoweredValInfo visitGlobalGenericParamDecl(GlobalGenericParamDecl* decl) { - auto inst = getBuilder()->emitGlobalGenericParam(); + auto inst = getBuilder()->emitGlobalGenericTypeParam(); addLinkageDecoration(context, inst, decl); return LoweredValInfo::simple(inst); } + LoweredValInfo visitGlobalGenericValueParamDecl(GlobalGenericValueParamDecl* decl) + { + auto builder = getBuilder(); + auto type = lowerType(context, decl->type); + auto inst = builder->emitGlobalGenericParam(type); + addLinkageDecoration(context, inst, decl); + return LoweredValInfo::simple(inst); + } + + void lowerWitnessTable( IRGenContext* subContext, WitnessTable* astWitnessTable, diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index dad84a4b6..9be2e49e5 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -1788,6 +1788,11 @@ namespace Slang return taggedUnionType; } + static RefPtr<RefObject> parseTaggedUnionType(Parser* parser, void* /*unused*/) + { + return parseTaggedUnionType(parser); + } + static TypeSpec parseTypeSpec(Parser* parser) { TypeSpec typeSpec; @@ -1831,6 +1836,12 @@ namespace Slang typeSpec.expr = createDeclRefType(parser, decl); return typeSpec; } + // TODO: This case would not be needed if we had the + // code below dispatch into `parseAtomicExpr`, which + // already includes logic for keyword lookup. + // + // Leaving this case here for now to avoid breaking anything. + // else if(AdvanceIf(parser, "__TaggedUnion")) { typeSpec.expr = parseTaggedUnionType(parser); @@ -2386,7 +2397,7 @@ namespace Slang return assocTypeDecl; } - RefPtr<RefObject> parseGlobalGenericParamDecl(Parser * parser, void *) + RefPtr<RefObject> parseGlobalGenericTypeParamDecl(Parser * parser, void *) { RefPtr<GlobalGenericParamDecl> genParamDecl = new GlobalGenericParamDecl(); auto nameToken = parser->ReadToken(TokenType::Identifier); @@ -2397,6 +2408,27 @@ namespace Slang return genParamDecl; } + RefPtr<RefObject> parseGlobalGenericValueParamDecl(Parser * parser, void *) + { + RefPtr<GlobalGenericValueParamDecl> genericParamDecl = new GlobalGenericValueParamDecl(); + auto nameToken = parser->ReadToken(TokenType::Identifier); + genericParamDecl->nameAndLoc = NameLoc(nameToken); + genericParamDecl->loc = nameToken.loc; + + if(AdvanceIf(parser, TokenType::Colon)) + { + genericParamDecl->type = parser->ParseTypeExp(); + } + + if(AdvanceIf(parser, TokenType::OpAssign)) + { + genericParamDecl->initExpr = parser->ParseInitExpr(); + } + + parser->ReadToken(TokenType::Semicolon); + return genericParamDecl; + } + static RefPtr<RefObject> parseInterfaceDecl(Parser* parser, void* /*userData*/) { RefPtr<InterfaceDecl> decl = new InterfaceDecl(); @@ -4270,7 +4302,7 @@ namespace Slang return parsePrefixExpr(this); } - RefPtr<Expr> parseTypeFromSourceFile( + RefPtr<Expr> parseTermFromSourceFile( Session* session, TokenSpan const& tokens, DiagnosticSink* sink, @@ -4282,7 +4314,7 @@ namespace Slang parser.currentScope = outerScope; parser.namePool = namePool; parser.sourceLanguage = sourceLanguage; - return parser.ParseType(); + return parser.ParseExpression(); } // Parse a source file into an existing translation unit @@ -4649,7 +4681,7 @@ namespace Slang addBuiltinSyntax<Decl>(session, scope, #KEYWORD, &CALLBACK) DECL(typedef, ParseTypeDef); DECL(associatedtype, parseAssocType); - DECL(type_param, parseGlobalGenericParamDecl); + DECL(type_param, parseGlobalGenericTypeParamDecl); DECL(cbuffer, parseHLSLCBufferDecl); DECL(tbuffer, parseHLSLTBufferDecl); DECL(__generic, ParseGenericDecl); @@ -4666,6 +4698,7 @@ namespace Slang DECL(var, parseVarDecl); DECL(func, parseFuncDecl); DECL(typealias, parseTypeAliasDecl); + DECL(__generic_value_param, parseGlobalGenericValueParamDecl); #undef DECL @@ -4753,6 +4786,7 @@ namespace Slang EXPR(this, parseThisExpr); EXPR(true, parseTrueExpr); EXPR(false, parseFalseExpr); + EXPR(__TaggedUnion, parseTaggedUnionType); #undef EXPR diff --git a/source/slang/slang-parser.h b/source/slang/slang-parser.h index 98fd9ed65..1c21b9474 100644 --- a/source/slang/slang-parser.h +++ b/source/slang/slang-parser.h @@ -14,7 +14,7 @@ namespace Slang DiagnosticSink* sink, RefPtr<Scope> const& outerScope); - RefPtr<Expr> parseTypeFromSourceFile( + RefPtr<Expr> parseTermFromSourceFile( Session* session, TokenSpan const& tokens, DiagnosticSink* sink, diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h index 8c07855e4..0dd70b1f8 100644 --- a/source/slang/slang-syntax.h +++ b/source/slang/slang-syntax.h @@ -1241,7 +1241,8 @@ namespace Slang ExistentialValue, }; Flavor flavor; - RefPtr<RefObject> object; + SourceLoc loc; + RefPtr<NodeBase> object; }; typedef List<SpecializationParam> SpecializationParams; diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 6632f2fa3..98ef7400e 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -813,7 +813,7 @@ SlangResult Linkage::loadFile(String const& path, PathInfo& outPathInfo, ISlangB return SLANG_OK; } -RefPtr<Expr> Linkage::parseTypeString(String typeStr, RefPtr<Scope> scope) +RefPtr<Expr> Linkage::parseTermString(String typeStr, RefPtr<Scope> scope) { // Create a SourceManager on the stack, so any allocations for 'SourceFile'/'SourceView' etc will be cleaned up SourceManager localSourceManager; @@ -856,7 +856,7 @@ RefPtr<Expr> Linkage::parseTypeString(String typeStr, RefPtr<Scope> scope) this, nullptr); - return parseTypeFromSourceFile( + return parseTermFromSourceFile( getSessionImpl(), tokens, &sink, scope, getNamePool(), SourceLanguage::Slang); } @@ -893,7 +893,7 @@ Type* ComponentType::getTypeFromString( auto linkage = getLinkage(); for(auto& s : scopesToTry) { - RefPtr<Expr> typeExpr = linkage->parseTypeString( + RefPtr<Expr> typeExpr = linkage->parseTermString( typeStr, s); type = checkProperType(linkage, TypeExp(typeExpr), sink); if (type && !type.as<ErrorType>()) |
