diff options
| author | Yong He <yonghe@outlook.com> | 2024-05-29 18:01:11 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-29 18:01:11 -0700 |
| commit | efdbb954c57b89362e390f955d45f90e59d66878 (patch) | |
| tree | 7b47d6e52d2de666af99f66a2fd3a5dc387ca5cc /source/slang/slang-options.cpp | |
| parent | 83f176ba8a3bae5533470aed6a90663653f894b8 (diff) | |
Improve compile time performance. (#3857)
* Handle type check cache update on extensions more gracefully.
* Correctness fix.
* Cache implcit cast overload resolution results.
* Fix.
* More optimizations.
* Cache implicit default ctor resolution.
* Disable redundancy removal.
* Fix.
* Fix test.
* Fix.
* Correctness fix.
* Fix.
* Fix,
* Fix test.
* Small tweak.
Diffstat (limited to 'source/slang/slang-options.cpp')
| -rw-r--r-- | source/slang/slang-options.cpp | 676 |
1 files changed, 337 insertions, 339 deletions
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 2d3f35557..dcc0f521d 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -2334,199 +2334,196 @@ SlangResult OptionsParser::_parse( // If a repro has been loaded, then many of the following options will overwrite // what was set up. So for now they are ignored, and only parameters set as part // of the loop work if they are after -load-repro - if (m_hasLoadedRepro) + if (!m_hasLoadedRepro) { - return SLANG_OK; - } - - // As a compatability feature, if the user didn't list any explicit entry - // point names, *and* they are compiling a single translation unit, *and* they - // have either specified a stage, or we can assume one from the naming - // of the translation unit, then we assume they wanted to compile a single - // entry point named `main`. - // - if (m_rawEntryPoints.getCount() == 0 - && m_rawTranslationUnits.getCount() == 1 - && (m_defaultEntryPoint.stage != Stage::Unknown - || m_rawTranslationUnits[0].impliedStage != Stage::Unknown)) - { - RawEntryPoint entry; - entry.name = "main"; - entry.translationUnitIndex = 0; - m_rawEntryPoints.add(entry); - } - - // If the user (manually or implicitly) specified only a single entry point, - // then we allow the associated stage to be specified either before or after - // the entry point. This means that if there is a stage attached - // to the "default" entry point, we should copy it over to the - // explicit one. - // - if (m_rawEntryPoints.getCount() == 1) - { - if (m_defaultEntryPoint.stage != Stage::Unknown) - { - setStage(getCurrentEntryPoint(), m_defaultEntryPoint.stage); - } - - if (m_defaultEntryPoint.redundantStageSet) - getCurrentEntryPoint()->redundantStageSet = true; - if (m_defaultEntryPoint.conflictingStagesSet) - getCurrentEntryPoint()->conflictingStagesSet = true; - } - else - { - // If the "default" entry point has had a stage (or - // other state, if we add other per-entry-point state) - // specified, but there is more than one entry point, - // then that state doesn't apply to anything and we - // should issue an error to tell the user something - // funky is going on. + // As a compatability feature, if the user didn't list any explicit entry + // point names, *and* they are compiling a single translation unit, *and* they + // have either specified a stage, or we can assume one from the naming + // of the translation unit, then we assume they wanted to compile a single + // entry point named `main`. // - if (m_defaultEntryPoint.stage != Stage::Unknown) + if (m_rawEntryPoints.getCount() == 0 + && m_rawTranslationUnits.getCount() == 1 + && (m_defaultEntryPoint.stage != Stage::Unknown + || m_rawTranslationUnits[0].impliedStage != Stage::Unknown)) + { + RawEntryPoint entry; + entry.name = "main"; + entry.translationUnitIndex = 0; + m_rawEntryPoints.add(entry); + } + + // If the user (manually or implicitly) specified only a single entry point, + // then we allow the associated stage to be specified either before or after + // the entry point. This means that if there is a stage attached + // to the "default" entry point, we should copy it over to the + // explicit one. + // + if (m_rawEntryPoints.getCount() == 1) { - if (m_rawEntryPoints.getCount() == 0) + if (m_defaultEntryPoint.stage != Stage::Unknown) { - m_sink->diagnose(SourceLoc(), Diagnostics::stageSpecificationIgnoredBecauseNoEntryPoints); + setStage(getCurrentEntryPoint(), m_defaultEntryPoint.stage); } - else + + if (m_defaultEntryPoint.redundantStageSet) + getCurrentEntryPoint()->redundantStageSet = true; + if (m_defaultEntryPoint.conflictingStagesSet) + getCurrentEntryPoint()->conflictingStagesSet = true; + } + else + { + // If the "default" entry point has had a stage (or + // other state, if we add other per-entry-point state) + // specified, but there is more than one entry point, + // then that state doesn't apply to anything and we + // should issue an error to tell the user something + // funky is going on. + // + if (m_defaultEntryPoint.stage != Stage::Unknown) { - m_sink->diagnose(SourceLoc(), Diagnostics::stageSpecificationIgnoredBecauseBeforeAllEntryPoints); + if (m_rawEntryPoints.getCount() == 0) + { + m_sink->diagnose(SourceLoc(), Diagnostics::stageSpecificationIgnoredBecauseNoEntryPoints); + } + else + { + m_sink->diagnose(SourceLoc(), Diagnostics::stageSpecificationIgnoredBecauseBeforeAllEntryPoints); + } } } - } - // Slang requires that every explicit entry point indicate the translation - // unit it comes from. If there is only one translation unit specified, - // then implicitly all entry points come from it. - // - if (m_translationUnitCount == 1) - { - for (auto& entryPoint : m_rawEntryPoints) + // Slang requires that every explicit entry point indicate the translation + // unit it comes from. If there is only one translation unit specified, + // then implicitly all entry points come from it. + // + if (m_translationUnitCount == 1) { - entryPoint.translationUnitIndex = 0; + for (auto& entryPoint : m_rawEntryPoints) + { + entryPoint.translationUnitIndex = 0; + } } - } - else if (m_frontEndReq->additionalLoadedModules && - m_frontEndReq->additionalLoadedModules->getCount() == 0) - { - // Otherwise, we require that all entry points be specified after - // the translation unit to which tye belong. - bool anyEntryPointWithoutTranslationUnit = false; - for (auto& entryPoint : m_rawEntryPoints) + else if (m_frontEndReq->additionalLoadedModules && + m_frontEndReq->additionalLoadedModules->getCount() == 0) { - // Skip entry points that are already associated with a translation unit... - if (entryPoint.translationUnitIndex != -1) - continue; + // Otherwise, we require that all entry points be specified after + // the translation unit to which tye belong. + bool anyEntryPointWithoutTranslationUnit = false; + for (auto& entryPoint : m_rawEntryPoints) + { + // Skip entry points that are already associated with a translation unit... + if (entryPoint.translationUnitIndex != -1) + continue; - anyEntryPointWithoutTranslationUnit = true; - } - if (anyEntryPointWithoutTranslationUnit) - { - m_sink->diagnose(SourceLoc(), Diagnostics::entryPointsNeedToBeAssociatedWithTranslationUnits); - return SLANG_FAIL; + anyEntryPointWithoutTranslationUnit = true; + } + if (anyEntryPointWithoutTranslationUnit) + { + m_sink->diagnose(SourceLoc(), Diagnostics::entryPointsNeedToBeAssociatedWithTranslationUnits); + return SLANG_FAIL; + } } - } - // Now that entry points are associated with translation units, - // we can make one additional pass where if an entry point has - // no specified stage, but the nameing of its translation unit - // implies a stage, we will use that (a manual `-stage` annotation - // will always win out in such a case). - // - for (auto& rawEntryPoint : m_rawEntryPoints) - { - // Skip entry points that already have a stage. - if (rawEntryPoint.stage != Stage::Unknown) - continue; + // Now that entry points are associated with translation units, + // we can make one additional pass where if an entry point has + // no specified stage, but the nameing of its translation unit + // implies a stage, we will use that (a manual `-stage` annotation + // will always win out in such a case). + // + for (auto& rawEntryPoint : m_rawEntryPoints) + { + // Skip entry points that already have a stage. + if (rawEntryPoint.stage != Stage::Unknown) + continue; - // Sanity check: don't process entry points with no associated translation unit. - if (rawEntryPoint.translationUnitIndex == -1) - continue; + // Sanity check: don't process entry points with no associated translation unit. + if (rawEntryPoint.translationUnitIndex == -1) + continue; - auto impliedStage = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex].impliedStage; - if (impliedStage != Stage::Unknown) - rawEntryPoint.stage = impliedStage; - } + auto impliedStage = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex].impliedStage; + if (impliedStage != Stage::Unknown) + rawEntryPoint.stage = impliedStage; + } - // Note: it is possible that some entry points still won't have associated - // stages at this point, but we don't want to error out here, because - // those entry points might get stages later, as part of semantic checking, - // if the corresponding function has a `[shader("...")]` attribute. + // Note: it is possible that some entry points still won't have associated + // stages at this point, but we don't want to error out here, because + // those entry points might get stages later, as part of semantic checking, + // if the corresponding function has a `[shader("...")]` attribute. - // Now that we've tried to establish stages for entry points, we can - // issue diagnostics for cases where stages were set redundantly or - // in conflicting ways. - // - for (auto& rawEntryPoint : m_rawEntryPoints) - { - if (rawEntryPoint.conflictingStagesSet) - { - m_sink->diagnose(SourceLoc(), Diagnostics::conflictingStagesForEntryPoint, rawEntryPoint.name); - } - else if (rawEntryPoint.redundantStageSet) - { - m_sink->diagnose(SourceLoc(), Diagnostics::sameStageSpecifiedMoreThanOnce, rawEntryPoint.stage, rawEntryPoint.name); - } - else if (rawEntryPoint.translationUnitIndex != -1) + // Now that we've tried to establish stages for entry points, we can + // issue diagnostics for cases where stages were set redundantly or + // in conflicting ways. + // + for (auto& rawEntryPoint : m_rawEntryPoints) { - // As a quality-of-life feature, if the file name implies a particular - // stage, but the user manually specified something different for - // their entry point, give a warning in case they made a mistake. - - auto& rawTranslationUnit = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex]; - if (rawTranslationUnit.impliedStage != Stage::Unknown - && rawEntryPoint.stage != Stage::Unknown - && rawTranslationUnit.impliedStage != rawEntryPoint.stage) + if (rawEntryPoint.conflictingStagesSet) + { + m_sink->diagnose(SourceLoc(), Diagnostics::conflictingStagesForEntryPoint, rawEntryPoint.name); + } + else if (rawEntryPoint.redundantStageSet) { - m_sink->diagnose(SourceLoc(), Diagnostics::explicitStageDoesntMatchImpliedStage, rawEntryPoint.name, rawEntryPoint.stage, rawTranslationUnit.impliedStage); + m_sink->diagnose(SourceLoc(), Diagnostics::sameStageSpecifiedMoreThanOnce, rawEntryPoint.stage, rawEntryPoint.name); + } + else if (rawEntryPoint.translationUnitIndex != -1) + { + // As a quality-of-life feature, if the file name implies a particular + // stage, but the user manually specified something different for + // their entry point, give a warning in case they made a mistake. + + auto& rawTranslationUnit = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex]; + if (rawTranslationUnit.impliedStage != Stage::Unknown + && rawEntryPoint.stage != Stage::Unknown + && rawTranslationUnit.impliedStage != rawEntryPoint.stage) + { + m_sink->diagnose(SourceLoc(), Diagnostics::explicitStageDoesntMatchImpliedStage, rawEntryPoint.name, rawEntryPoint.stage, rawTranslationUnit.impliedStage); + } } } - } - // If the user is requesting code generation via pass-through, - // then any entry points they specify need to have a stage set, - // because fxc/dxc/glslang don't have a facility for taking - // a named entry point and pulling its stage from an attribute. - // - if (_passThroughRequiresStage(m_requestImpl->m_passThrough)) - { - for (auto& rawEntryPoint : m_rawEntryPoints) + // If the user is requesting code generation via pass-through, + // then any entry points they specify need to have a stage set, + // because fxc/dxc/glslang don't have a facility for taking + // a named entry point and pulling its stage from an attribute. + // + if (_passThroughRequiresStage(m_requestImpl->m_passThrough)) { - if (rawEntryPoint.stage == Stage::Unknown) + for (auto& rawEntryPoint : m_rawEntryPoints) { - m_sink->diagnose(SourceLoc(), Diagnostics::noStageSpecifiedInPassThroughMode, rawEntryPoint.name); + if (rawEntryPoint.stage == Stage::Unknown) + { + m_sink->diagnose(SourceLoc(), Diagnostics::noStageSpecifiedInPassThroughMode, rawEntryPoint.name); + } } } - } - // We now have inferred enough information to add the - // entry points to our compile request. - // - for (auto& rawEntryPoint : m_rawEntryPoints) - { - if (rawEntryPoint.translationUnitIndex < 0) - continue; + // We now have inferred enough information to add the + // entry points to our compile request. + // + for (auto& rawEntryPoint : m_rawEntryPoints) + { + if (rawEntryPoint.translationUnitIndex < 0) + continue; - auto translationUnitID = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex].translationUnitID; + auto translationUnitID = m_rawTranslationUnits[rawEntryPoint.translationUnitIndex].translationUnitID; - List<const char*> specializationArgs; - for (auto& arg : rawEntryPoint.specializationArgs) - specializationArgs.add(arg.getBuffer()); + List<const char*> specializationArgs; + for (auto& arg : rawEntryPoint.specializationArgs) + specializationArgs.add(arg.getBuffer()); - int entryPointID = m_compileRequest->addEntryPointEx( - translationUnitID, - rawEntryPoint.name.begin(), - SlangStage(rawEntryPoint.stage), - (int)specializationArgs.getCount(), - specializationArgs.getBuffer()); + int entryPointID = m_compileRequest->addEntryPointEx( + translationUnitID, + rawEntryPoint.name.begin(), + SlangStage(rawEntryPoint.stage), + (int)specializationArgs.getCount(), + specializationArgs.getBuffer()); - rawEntryPoint.entryPointID = entryPointID; - } + rawEntryPoint.entryPointID = entryPointID; + } - // We are going to build a mapping from target formats to the - // target that handles that format. - Dictionary<CodeGenTarget, int> mapFormatToTargetIndex; + // We are going to build a mapping from target formats to the + // target that handles that format. + Dictionary<CodeGenTarget, int> mapFormatToTargetIndex; // If there was no explicit `-target` specified, then we will look // at the `-o` options to see what we can infer. @@ -2547,60 +2544,60 @@ SlangResult OptionsParser::_parse( if (impliedFormat == CodeGenTarget::Unknown) continue; - int targetIndex = 0; - if (!mapFormatToTargetIndex.tryGetValue(impliedFormat, targetIndex)) - { - targetIndex = (int)m_rawTargets.getCount(); + int targetIndex = 0; + if (!mapFormatToTargetIndex.tryGetValue(impliedFormat, targetIndex)) + { + targetIndex = (int)m_rawTargets.getCount(); - RawTarget rawTarget; - rawTarget.format = impliedFormat; - m_rawTargets.add(rawTarget); + RawTarget rawTarget; + rawTarget.format = impliedFormat; + m_rawTargets.add(rawTarget); - mapFormatToTargetIndex[impliedFormat] = targetIndex; - } + mapFormatToTargetIndex[impliedFormat] = targetIndex; + } - rawOutput.targetIndex = targetIndex; + rawOutput.targetIndex = targetIndex; + } } } - } - else - { - // If there were explicit targets, then we will use those, but still - // build up our mapping. We should object if the same target format - // is specified more than once (just because of the ambiguities - // it will create). - // - int targetCount = (int)m_rawTargets.getCount(); - for (int targetIndex = 0; targetIndex < targetCount; ++targetIndex) + else { - auto format = m_rawTargets[targetIndex].format; - - if (mapFormatToTargetIndex.containsKey(format)) - { - m_sink->diagnose(SourceLoc(), Diagnostics::duplicateTargets, format); - } - else + // If there were explicit targets, then we will use those, but still + // build up our mapping. We should object if the same target format + // is specified more than once (just because of the ambiguities + // it will create). + // + int targetCount = (int)m_rawTargets.getCount(); + for (int targetIndex = 0; targetIndex < targetCount; ++targetIndex) { - mapFormatToTargetIndex[format] = targetIndex; + auto format = m_rawTargets[targetIndex].format; + + if (mapFormatToTargetIndex.containsKey(format)) + { + m_sink->diagnose(SourceLoc(), Diagnostics::duplicateTargets, format); + } + else + { + mapFormatToTargetIndex[format] = targetIndex; + } } } - } - // If we weren't able to infer any targets from output paths (perhaps - // because there were no output paths), but there was a profile specified, - // then we can try to infer a target from the profile. - // - if (m_rawTargets.getCount() == 0 - && m_defaultTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown - && !m_defaultTarget.conflictingProfilesSet) - { - // Let's see if the chosen profile allows us to infer - // the code gen target format that the user probably meant. + // If we weren't able to infer any targets from output paths (perhaps + // because there were no output paths), but there was a profile specified, + // then we can try to infer a target from the profile. // - CodeGenTarget inferredFormat = CodeGenTarget::Unknown; - auto profileVersion = m_defaultTarget.optionSet.getProfileVersion(); - switch (Profile(profileVersion).getFamily()) + if (m_rawTargets.getCount() == 0 + && m_defaultTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown + && !m_defaultTarget.conflictingProfilesSet) { + // Let's see if the chosen profile allows us to infer + // the code gen target format that the user probably meant. + // + CodeGenTarget inferredFormat = CodeGenTarget::Unknown; + auto profileVersion = m_defaultTarget.optionSet.getProfileVersion(); + switch (Profile(profileVersion).getFamily()) + { default: break; @@ -2630,128 +2627,128 @@ SlangResult OptionsParser::_parse( inferredFormat = CodeGenTarget::DXBytecode; } break; - } + } - if (inferredFormat != CodeGenTarget::Unknown) - { - RawTarget rawTarget; - rawTarget.format = inferredFormat; - m_rawTargets.add(rawTarget); + if (inferredFormat != CodeGenTarget::Unknown) + { + RawTarget rawTarget; + rawTarget.format = inferredFormat; + m_rawTargets.add(rawTarget); + } } - } - // Similar to the case for entry points, if there is a single target, - // then we allow some of its options to come from the "default" - // target state. - auto defaultTargetFloatingPointMode = m_defaultTarget.optionSet.getEnumOption<FloatingPointMode>(CompilerOptionName::FloatingPointMode); + // Similar to the case for entry points, if there is a single target, + // then we allow some of its options to come from the "default" + // target state. + auto defaultTargetFloatingPointMode = m_defaultTarget.optionSet.getEnumOption<FloatingPointMode>(CompilerOptionName::FloatingPointMode); - if (m_rawTargets.getCount() == 1) - { - m_rawTargets[0].optionSet.overrideWith(m_defaultTarget.optionSet); - } - else - { - // If the "default" target has had a profile (or other state) - // specified, but there is != 1 taget, then that state doesn't - // apply to anythign and we should give the user an error. - // - if (m_defaultTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown) + if (m_rawTargets.getCount() == 1) + { + m_rawTargets[0].optionSet.overrideWith(m_defaultTarget.optionSet); + } + else { - if (m_rawTargets.getCount() == 0) + // If the "default" target has had a profile (or other state) + // specified, but there is != 1 taget, then that state doesn't + // apply to anythign and we should give the user an error. + // + if (m_defaultTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown) { - // This should only happen if there were multiple `-profile` options, - // so we didn't try to infer a target, or if the `-profile` option - // somehow didn't imply a target. - // - m_sink->diagnose(SourceLoc(), Diagnostics::profileSpecificationIgnoredBecauseNoTargets); + if (m_rawTargets.getCount() == 0) + { + // This should only happen if there were multiple `-profile` options, + // so we didn't try to infer a target, or if the `-profile` option + // somehow didn't imply a target. + // + m_sink->diagnose(SourceLoc(), Diagnostics::profileSpecificationIgnoredBecauseNoTargets); + } + else + { + m_sink->diagnose(SourceLoc(), Diagnostics::profileSpecificationIgnoredBecauseBeforeAllTargets); + } } - else + + if (defaultTargetFloatingPointMode != FloatingPointMode::Default) { - m_sink->diagnose(SourceLoc(), Diagnostics::profileSpecificationIgnoredBecauseBeforeAllTargets); + if (m_rawTargets.getCount() == 0) + { + m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseNoTargets); + } + else + { + m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseBeforeAllTargets); + } } - } - if (defaultTargetFloatingPointMode != FloatingPointMode::Default) + } + for (auto& rawTarget : m_rawTargets) { - if (m_rawTargets.getCount() == 0) + if (rawTarget.conflictingProfilesSet) { - m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseNoTargets); + m_sink->diagnose(SourceLoc(), Diagnostics::conflictingProfilesSpecifiedForTarget, rawTarget.format); } - else + else if (rawTarget.redundantProfileSet) { - m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseBeforeAllTargets); + m_sink->diagnose(SourceLoc(), Diagnostics::sameProfileSpecifiedMoreThanOnce, rawTarget.optionSet.getProfileVersion(), rawTarget.format); } } - } - for (auto& rawTarget : m_rawTargets) - { - if (rawTarget.conflictingProfilesSet) - { - m_sink->diagnose(SourceLoc(), Diagnostics::conflictingProfilesSpecifiedForTarget, rawTarget.format); - } - else if (rawTarget.redundantProfileSet) - { - m_sink->diagnose(SourceLoc(), Diagnostics::sameProfileSpecifiedMoreThanOnce, rawTarget.optionSet.getProfileVersion(), rawTarget.format); - } - } - - // TODO: do we need to require that a target must have a profile specified, - // or will we continue to allow the profile to be inferred from the target? - - // We now have enough information to go ahead and declare the targets - // through the Slang API: - // - for (auto& rawTarget : m_rawTargets) - { - int targetID = m_compileRequest->addCodeGenTarget(SlangCompileTarget(rawTarget.format)); - rawTarget.targetID = targetID; + // TODO: do we need to require that a target must have a profile specified, + // or will we continue to allow the profile to be inferred from the target? - if (rawTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown) - { - m_compileRequest->setTargetProfile(targetID, SlangProfileID(Profile(rawTarget.optionSet.getProfileVersion()).raw)); - } - for (auto atom : rawTarget.optionSet.getArray(CompilerOptionName::Capability)) + // We now have enough information to go ahead and declare the targets + // through the Slang API: + // + for (auto& rawTarget : m_rawTargets) { - m_requestImpl->addTargetCapability(targetID, SlangCapabilityID(atom.intValue)); - } + int targetID = m_compileRequest->addCodeGenTarget(SlangCompileTarget(rawTarget.format)); + rawTarget.targetID = targetID; - auto floatingPointMode = rawTarget.optionSet.getEnumOption<FloatingPointMode>(CompilerOptionName::FloatingPointMode); - if (floatingPointMode != FloatingPointMode::Default) - { - m_compileRequest->setTargetFloatingPointMode(targetID, SlangFloatingPointMode(floatingPointMode)); - } + if (rawTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown) + { + m_compileRequest->setTargetProfile(targetID, SlangProfileID(Profile(rawTarget.optionSet.getProfileVersion()).raw)); + } + for (auto atom : rawTarget.optionSet.getArray(CompilerOptionName::Capability)) + { + m_requestImpl->addTargetCapability(targetID, SlangCapabilityID(atom.intValue)); + } - if (rawTarget.optionSet.shouldUseScalarLayout()) - { - m_compileRequest->setTargetForceGLSLScalarBufferLayout(targetID, true); + auto floatingPointMode = rawTarget.optionSet.getEnumOption<FloatingPointMode>(CompilerOptionName::FloatingPointMode); + if (floatingPointMode != FloatingPointMode::Default) + { + m_compileRequest->setTargetFloatingPointMode(targetID, SlangFloatingPointMode(floatingPointMode)); + } + + if (rawTarget.optionSet.shouldUseScalarLayout()) + { + m_compileRequest->setTargetForceGLSLScalarBufferLayout(targetID, true); + } } - } - // Next we need to sort out the output files specified with `-o`, and - // figure out which entry point and/or target they apply to. - // - // If there is only a single entry point, then that is automatically - // the entry point that should be associated with all outputs. - // - if (m_rawEntryPoints.getCount() == 1) - { - for (auto& rawOutput : m_rawOutputs) + // Next we need to sort out the output files specified with `-o`, and + // figure out which entry point and/or target they apply to. + // + // If there is only a single entry point, then that is automatically + // the entry point that should be associated with all outputs. + // + if (m_rawEntryPoints.getCount() == 1) { - rawOutput.entryPointIndex = 0; + for (auto& rawOutput : m_rawOutputs) + { + rawOutput.entryPointIndex = 0; + } } - } - // - // Similarly, if there is only one target, then all outputs must - // implicitly appertain to that target. - // - if (m_rawTargets.getCount() == 1) - { - for (auto& rawOutput : m_rawOutputs) + // + // Similarly, if there is only one target, then all outputs must + // implicitly appertain to that target. + // + if (m_rawTargets.getCount() == 1) { - rawOutput.targetIndex = 0; + for (auto& rawOutput : m_rawOutputs) + { + rawOutput.targetIndex = 0; + } } - } // If we don't have any raw outputs but do have a raw target, // add an empty' rawOutput for certain targets where the expected behavior is obvious. @@ -2773,55 +2770,55 @@ SlangResult OptionsParser::_parse( m_rawOutputs.add(rawOutput); } - // Consider the output files specified via `-o` and try to figure - // out how to deal with them. - // - for (auto& rawOutput : m_rawOutputs) - { - // For now, most output formats need to be tightly bound to - // both a target and an entry point. - - // If an output doesn't have a target associated with - // it, then search for the target with the matching format. - if (rawOutput.targetIndex == -1) + // Consider the output files specified via `-o` and try to figure + // out how to deal with them. + // + for (auto& rawOutput : m_rawOutputs) { - auto impliedFormat = rawOutput.impliedFormat; - int targetIndex = -1; + // For now, most output formats need to be tightly bound to + // both a target and an entry point. - if (impliedFormat == CodeGenTarget::Unknown) - { - - // If we hit this case, then it means that we need to pick the - // target to assocaite with this output based on its implied - // format, but the file path doesn't direclty imply a format - // (it doesn't have a suffix like `.spv` that tells us what to write). - // - m_sink->diagnose(SourceLoc(), Diagnostics::cannotDeduceOutputFormatFromPath, rawOutput.path); - } - else if (mapFormatToTargetIndex.tryGetValue(rawOutput.impliedFormat, targetIndex)) + // If an output doesn't have a target associated with + // it, then search for the target with the matching format. + if (rawOutput.targetIndex == -1) { - rawOutput.targetIndex = targetIndex; - } - else - { - m_sink->diagnose(SourceLoc(), Diagnostics::cannotMatchOutputFileToTarget, rawOutput.path, rawOutput.impliedFormat); + auto impliedFormat = rawOutput.impliedFormat; + int targetIndex = -1; + + if (impliedFormat == CodeGenTarget::Unknown) + { + + // If we hit this case, then it means that we need to pick the + // target to assocaite with this output based on its implied + // format, but the file path doesn't direclty imply a format + // (it doesn't have a suffix like `.spv` that tells us what to write). + // + m_sink->diagnose(SourceLoc(), Diagnostics::cannotDeduceOutputFormatFromPath, rawOutput.path); + } + else if (mapFormatToTargetIndex.tryGetValue(rawOutput.impliedFormat, targetIndex)) + { + rawOutput.targetIndex = targetIndex; + } + else + { + m_sink->diagnose(SourceLoc(), Diagnostics::cannotMatchOutputFileToTarget, rawOutput.path, rawOutput.impliedFormat); + } } - } - // We won't do any searching to match an output file - // with an entry point, since the case of a single entry - // point was handled above, and the user is expected to - // follow the ordering rules when using multiple entry points. - if (rawOutput.entryPointIndex == -1) - { - if (rawOutput.targetIndex != -1) + // We won't do any searching to match an output file + // with an entry point, since the case of a single entry + // point was handled above, and the user is expected to + // follow the ordering rules when using multiple entry points. + if (rawOutput.entryPointIndex == -1) { - auto outputFormat = m_rawTargets[rawOutput.targetIndex].format; - // Here we check whether the given output format supports multiple entry points - // When we add targets with support for multiple entry points, - // we should update this switch with those new formats - switch (outputFormat) + if (rawOutput.targetIndex != -1) { + auto outputFormat = m_rawTargets[rawOutput.targetIndex].format; + // Here we check whether the given output format supports multiple entry points + // When we add targets with support for multiple entry points, + // we should update this switch with those new formats + switch (outputFormat) + { case CodeGenTarget::CPPSource: case CodeGenTarget::PTX: case CodeGenTarget::CUDASource: @@ -2857,12 +2854,12 @@ SlangResult OptionsParser::_parse( m_sink->diagnose(SourceLoc(), Diagnostics::cannotMatchOutputFileToEntryPoint, rawOutput.path); } break; + } } } } } - // Now that we've diagnosed the output paths, we can add them // to the compile request at the appropriate locations. // @@ -2918,6 +2915,7 @@ SlangResult OptionsParser::_parse( } } + // Copy all settings from linkage to targets. for (auto target : linkage->targets) { |
