diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-10-04 09:46:03 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-04 09:46:03 -0400 |
| commit | 7c8527d20e433c3a10736136d31e4cd882a3baaa (patch) | |
| tree | 44032051a4d76c8773b8a503dae14d9c8c9e786d /source/slang/slang-check.cpp | |
| parent | 0bc7d9b0aeb77c40befeb3618240a065374216a1 (diff) | |
IR types for subset of Attributes (#1067)
* IROutputControlPointsDecoration
* IROutputTopologyDecoration
* IRPartitioningDecoration
* IRDomainDecoration
* Use IRPatchConstantDecoration alone for hlsl output.
* IRMaxVertexCountDecoration
* IRInstanceDecoration
* Removed _emitHLSLAttributeSingleString and _emitHLSLAttributeSingleInt
Removed GLSLBindingAttribute and just use NumThreadsAttribute
* Added IRNumThreadsDecoration.
* Added IRNumThreadsDecoration
* Fix build problem on x86.
Improve diagnostic text based on review.
Diffstat (limited to 'source/slang/slang-check.cpp')
| -rw-r--r-- | source/slang/slang-check.cpp | 367 |
1 files changed, 192 insertions, 175 deletions
diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp index cec6b02a2..b5069a02f 100644 --- a/source/slang/slang-check.cpp +++ b/source/slang/slang-check.cpp @@ -2781,236 +2781,253 @@ namespace Slang bool validateAttribute(RefPtr<Attribute> attr, AttributeDecl* attribClassDecl) { - if(auto numThreadsAttr = as<NumThreadsAttribute>(attr)) - { - SLANG_ASSERT(attr->args.getCount() == 3); - auto xVal = checkConstantIntVal(attr->args[0]); - auto yVal = checkConstantIntVal(attr->args[1]); - auto zVal = checkConstantIntVal(attr->args[2]); + if(auto numThreadsAttr = as<NumThreadsAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 3); - if(!xVal) return false; - if(!yVal) return false; - if(!zVal) return false; + int32_t values[3]; - numThreadsAttr->x = (int32_t) xVal->value; - numThreadsAttr->y = (int32_t) yVal->value; - numThreadsAttr->z = (int32_t) zVal->value; - } - else if (auto bindingAttr = as<GLSLBindingAttribute>(attr)) + for (int i = 0; i < 3; ++i) { - // This must be vk::binding or gl::binding (as specified in core.meta.slang under vk_binding/gl_binding) - // Must have 2 int parameters. Ideally this would all be checked from the specification - // in core.meta.slang, but that's not completely implemented. So for now we check here. - if (attr->args.getCount() != 2) - { - return false; - } + int32_t value = 1; - // TODO(JS): Prior validation currently doesn't ensure both args are ints (as specified in core.meta.slang), so check here - // to make sure they both are - auto binding = checkConstantIntVal(attr->args[0]); - auto set = checkConstantIntVal(attr->args[1]); - - if (binding == nullptr || set == nullptr) + auto arg = attr->args[i]; + if (arg) { - return false; + auto intValue = checkConstantIntVal(arg); + if (!intValue) + { + return false; + } + if (intValue->value < 1) + { + getSink()->diagnose(attr, Diagnostics::nonPositiveNumThreads, intValue->value); + return false; + } + value = int32_t(intValue->value); } - - bindingAttr->binding = int32_t(binding->value); - bindingAttr->set = int32_t(set->value); + values[i] = value; } - else if (auto maxVertexCountAttr = as<MaxVertexCountAttribute>(attr)) + + numThreadsAttr->x = values[0]; + numThreadsAttr->y = values[1]; + numThreadsAttr->z = values[2]; + } + else if (auto bindingAttr = as<GLSLBindingAttribute>(attr)) + { + // This must be vk::binding or gl::binding (as specified in core.meta.slang under vk_binding/gl_binding) + // Must have 2 int parameters. Ideally this would all be checked from the specification + // in core.meta.slang, but that's not completely implemented. So for now we check here. + if (attr->args.getCount() != 2) { - SLANG_ASSERT(attr->args.getCount() == 1); - auto val = checkConstantIntVal(attr->args[0]); + return false; + } - if(!val) return false; + // TODO(JS): Prior validation currently doesn't ensure both args are ints (as specified in core.meta.slang), so check here + // to make sure they both are + auto binding = checkConstantIntVal(attr->args[0]); + auto set = checkConstantIntVal(attr->args[1]); - maxVertexCountAttr->value = (int32_t)val->value; - } - else if(auto instanceAttr = as<InstanceAttribute>(attr)) + if (binding == nullptr || set == nullptr) { - SLANG_ASSERT(attr->args.getCount() == 1); - auto val = checkConstantIntVal(attr->args[0]); + return false; + } + + bindingAttr->binding = int32_t(binding->value); + bindingAttr->set = int32_t(set->value); + } + else if (auto maxVertexCountAttr = as<MaxVertexCountAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); + auto val = checkConstantIntVal(attr->args[0]); - if(!val) return false; + if(!val) return false; - instanceAttr->value = (int32_t)val->value; - } - else if(auto entryPointAttr = as<EntryPointAttribute>(attr)) - { - SLANG_ASSERT(attr->args.getCount() == 1); + maxVertexCountAttr->value = (int32_t)val->value; + } + else if(auto instanceAttr = as<InstanceAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); + auto val = checkConstantIntVal(attr->args[0]); - String stageName; - if(!checkLiteralStringVal(attr->args[0], &stageName)) - { - return false; - } + if(!val) return false; - auto stage = findStageByName(stageName); - if(stage == Stage::Unknown) - { - getSink()->diagnose(attr->args[0], Diagnostics::unknownStageName, stageName); - } + instanceAttr->value = (int32_t)val->value; + } + else if(auto entryPointAttr = as<EntryPointAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); - entryPointAttr->stage = stage; - } - else if ((as<DomainAttribute>(attr)) || - (as<MaxTessFactorAttribute>(attr)) || - (as<OutputTopologyAttribute>(attr)) || - (as<PartitioningAttribute>(attr)) || - (as<PatchConstantFuncAttribute>(attr))) - { - // Let it go thru iff single string attribute - if (!hasStringArgs(attr, 1)) - { - getSink()->diagnose(attr, Diagnostics::expectedSingleStringArg, attr->name); - } - } - else if (as<OutputControlPointsAttribute>(attr)) + String stageName; + if(!checkLiteralStringVal(attr->args[0], &stageName)) { - // Let it go thru iff single integral attribute - if (!hasIntArgs(attr, 1)) - { - getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); - } + return false; } - else if (as<PushConstantAttribute>(attr)) + + auto stage = findStageByName(stageName); + if(stage == Stage::Unknown) { - // Has no args - SLANG_ASSERT(attr->args.getCount() == 0); + getSink()->diagnose(attr->args[0], Diagnostics::unknownStageName, stageName); } - else if (as<ShaderRecordAttribute>(attr)) + + entryPointAttr->stage = stage; + } + else if ((as<DomainAttribute>(attr)) || + (as<MaxTessFactorAttribute>(attr)) || + (as<OutputTopologyAttribute>(attr)) || + (as<PartitioningAttribute>(attr)) || + (as<PatchConstantFuncAttribute>(attr))) + { + // Let it go thru iff single string attribute + if (!hasStringArgs(attr, 1)) { - // Has no args - SLANG_ASSERT(attr->args.getCount() == 0); + getSink()->diagnose(attr, Diagnostics::expectedSingleStringArg, attr->name); } - else if (as<EarlyDepthStencilAttribute>(attr)) + } + else if (as<OutputControlPointsAttribute>(attr)) + { + // Let it go thru iff single integral attribute + if (!hasIntArgs(attr, 1)) { - // Has no args - SLANG_ASSERT(attr->args.getCount() == 0); + getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); } - else if (auto attrUsageAttr = as<AttributeUsageAttribute>(attr)) + } + else if (as<PushConstantAttribute>(attr)) + { + // Has no args + SLANG_ASSERT(attr->args.getCount() == 0); + } + else if (as<ShaderRecordAttribute>(attr)) + { + // Has no args + SLANG_ASSERT(attr->args.getCount() == 0); + } + else if (as<EarlyDepthStencilAttribute>(attr)) + { + // Has no args + SLANG_ASSERT(attr->args.getCount() == 0); + } + else if (auto attrUsageAttr = as<AttributeUsageAttribute>(attr)) + { + uint32_t targetClassId = (uint32_t)UserDefinedAttributeTargets::None; + if (attr->args.getCount() == 1) { - uint32_t targetClassId = (uint32_t)UserDefinedAttributeTargets::None; - if (attr->args.getCount() == 1) + RefPtr<IntVal> outIntVal; + if (auto cInt = checkConstantEnumVal(attr->args[0])) { - RefPtr<IntVal> outIntVal; - if (auto cInt = checkConstantEnumVal(attr->args[0])) - { - targetClassId = (uint32_t)(cInt->value); - } - else - { - getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); - return false; - } + targetClassId = (uint32_t)(cInt->value); } - if (!getAttributeTargetSyntaxClasses(attrUsageAttr->targetSyntaxClass, targetClassId)) + else { - getSink()->diagnose(attr, Diagnostics::invalidAttributeTarget); + getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); return false; } } - else if (auto unrollAttr = as<UnrollAttribute>(attr)) + if (!getAttributeTargetSyntaxClasses(attrUsageAttr->targetSyntaxClass, targetClassId)) { - // Check has an argument. We need this because default behavior is to give an error - // if an attribute has arguments, but not handled explicitly (and the default param will come through - // as 1 arg if nothing is specified) - SLANG_ASSERT(attr->args.getCount() == 1); + getSink()->diagnose(attr, Diagnostics::invalidAttributeTarget); + return false; } - else if (auto userDefAttr = as<UserDefinedAttribute>(attr)) + } + else if (auto unrollAttr = as<UnrollAttribute>(attr)) + { + // Check has an argument. We need this because default behavior is to give an error + // if an attribute has arguments, but not handled explicitly (and the default param will come through + // as 1 arg if nothing is specified) + SLANG_ASSERT(attr->args.getCount() == 1); + } + else if (auto userDefAttr = as<UserDefinedAttribute>(attr)) + { + // check arguments against attribute parameters defined in attribClassDecl + Index paramIndex = 0; + auto params = attribClassDecl->getMembersOfType<ParamDecl>(); + for (auto paramDecl : params) { - // check arguments against attribute parameters defined in attribClassDecl - Index paramIndex = 0; - auto params = attribClassDecl->getMembersOfType<ParamDecl>(); - for (auto paramDecl : params) + if (paramIndex < attr->args.getCount()) { - if (paramIndex < attr->args.getCount()) + auto & arg = attr->args[paramIndex]; + bool typeChecked = false; + if (auto basicType = as<BasicExpressionType>(paramDecl->getType())) { - auto & arg = attr->args[paramIndex]; - bool typeChecked = false; - if (auto basicType = as<BasicExpressionType>(paramDecl->getType())) + if (basicType->baseType == BaseType::Int) { - if (basicType->baseType == BaseType::Int) + if (auto cint = checkConstantIntVal(arg)) { - if (auto cint = checkConstantIntVal(arg)) - { - attr->intArgVals[(uint32_t)paramIndex] = cint; - } - typeChecked = true; + attr->intArgVals[(uint32_t)paramIndex] = cint; } - } - if (!typeChecked) - { - arg = CheckExpr(arg); - arg = coerce(paramDecl->getType(), arg); + typeChecked = true; } } - paramIndex++; - } - if (params.getCount() < attr->args.getCount()) - { - getSink()->diagnose(attr, Diagnostics::tooManyArguments, attr->args.getCount(), params.getCount()); - } - else if (params.getCount() > attr->args.getCount()) - { - getSink()->diagnose(attr, Diagnostics::notEnoughArguments, attr->args.getCount(), params.getCount()); + if (!typeChecked) + { + arg = CheckExpr(arg); + arg = coerce(paramDecl->getType(), arg); + } } + paramIndex++; } - else if (auto formatAttr = as<FormatAttribute>(attr)) + if (params.getCount() < attr->args.getCount()) { - SLANG_ASSERT(attr->args.getCount() == 1); - - String formatName; - if(!checkLiteralStringVal(attr->args[0], &formatName)) - { - return false; - } - - ImageFormat format = ImageFormat::unknown; - if(!findImageFormatByName(formatName.getBuffer(), &format)) - { - getSink()->diagnose(attr->args[0], Diagnostics::unknownImageFormatName, formatName); - } + getSink()->diagnose(attr, Diagnostics::tooManyArguments, attr->args.getCount(), params.getCount()); + } + else if (params.getCount() > attr->args.getCount()) + { + getSink()->diagnose(attr, Diagnostics::notEnoughArguments, attr->args.getCount(), params.getCount()); + } + } + else if (auto formatAttr = as<FormatAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); - formatAttr->format = format; + String formatName; + if(!checkLiteralStringVal(attr->args[0], &formatName)) + { + return false; } - else if (auto allowAttr = as<AllowAttribute>(attr)) + + ImageFormat format = ImageFormat::unknown; + if(!findImageFormatByName(formatName.getBuffer(), &format)) { - SLANG_ASSERT(attr->args.getCount() == 1); + getSink()->diagnose(attr->args[0], Diagnostics::unknownImageFormatName, formatName); + } - String diagnosticName; - if(!checkLiteralStringVal(attr->args[0], &diagnosticName)) - { - return false; - } + formatAttr->format = format; + } + else if (auto allowAttr = as<AllowAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); - auto diagnosticInfo = findDiagnosticByName(diagnosticName.getUnownedSlice()); - if(!diagnosticInfo) - { - getSink()->diagnose(attr->args[0], Diagnostics::unknownDiagnosticName, diagnosticName); - } + String diagnosticName; + if(!checkLiteralStringVal(attr->args[0], &diagnosticName)) + { + return false; + } - allowAttr->diagnostic = diagnosticInfo; + auto diagnosticInfo = findDiagnosticByName(diagnosticName.getUnownedSlice()); + if(!diagnosticInfo) + { + getSink()->diagnose(attr->args[0], Diagnostics::unknownDiagnosticName, diagnosticName); + } + + allowAttr->diagnostic = diagnosticInfo; + } + else + { + if(attr->args.getCount() == 0) + { + // If the attribute took no arguments, then we will + // assume it is valid as written. } else { - if(attr->args.getCount() == 0) - { - // If the attribute took no arguments, then we will - // assume it is valid as written. - } - else - { - // We should be special-casing the checking of any attribute - // with a non-zero number of arguments. - SLANG_DIAGNOSE_UNEXPECTED(getSink(), attr, "unhandled attribute"); - return false; - } + // We should be special-casing the checking of any attribute + // with a non-zero number of arguments. + SLANG_DIAGNOSE_UNEXPECTED(getSink(), attr, "unhandled attribute"); + return false; } + } - return true; + return true; } RefPtr<AttributeBase> checkAttribute( |
