| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
AST-parent has target+set the AST-child does not (#8175)
Fixes: #8174
Changes:
* To determine if we propagate capabilities, we need to ensure that a
`join` will do nothing (optimization since `join` is expensive + caching
data for the `join` adds up to be expensive). This logic was changed in
`slang-check-decl.cpp` since the current logic was incorrect.
* A parent could have the set `metal+glsl` and the use-site could have
`glsl`. In this case, we will not remove `metal` from the parent since
`{metal+glsl}.implies({glsl})` is true.
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes: #7410
Changes:
1. super-type capabilities must be a super-set of sub-type capabilities
(and support the same shader stages/targets)
* InheritanceDecl visits super-type to inherit it's capabilities;
validate InheritanceDecl capabilities against sub-type
* visit all container decl's with a default case
* clean up functionDeclBase visitor
* Simplify `diagnoseUndeclaredCapability` by moving logic into
capability checking (more correct*)
3. added changed behavior to documentation
4. fixed some incorrect capabilities
5. **we do not** diagnose capability errors on interface
requirement-to-implementation if both lack explicit capability
requirements. This change is to work around a slangpy regression (test
case for the failing situation is in
`tests\language-feature\capability\capability-interface-extension-1.slang`),
Note: maybe for slang-2026 we don't do this?
6. requirement & implementation must support the same shader
stage/target. This was changed because otherwise we can have cases where
`X` inherits from `Y`, but `Y` is only expected to be used in `glsl`
whilst `X` is expected to be used in `hlsl | glsl`
7. removed
`tests/language-feature/capability/capabilitySimplification3.slang`
because it tests nothing special (redundant)
Note: not using rebase due to separate branches depending on this PR
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
|
| |
|
|
|
|
|
| |
This allows checking capabilities in any stage, needed specifically for
the hlsl_2018 capability which is defined for sm_5_1 and above. Stage
specific capabilities such as cs_5_1 would not find this in any stage
other than compute, so we need to restrict the check to only desired
stages.
|
| |
|
|
|
|
|
|
|
| |
* Support stage_switch.
* Update proposal status.
* Fix gl_InstanceID.
* Fix.
|
| |
|
|
|
|
|
| |
* format
* Minor test fixes
* enable checking cpp format in ci
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Add `_Internal`/`External` atom validation and use enforcement.
Fixes: #4676
Changes:
* Added `validateInternalAtomExternalAtomPair` to the capability generator to ensure all `_Internal` atoms have a corresponding `External` atom.
* Validation of 'RequireCapabilityAttribute' warns if a user uses an '_Internal' atom.
* Added 'External' atoms to atoms with an already existing '_Internal' atom.
* Printing an atom removes '_'.
* Fixed some incorrect which were checking for the incorrect warning/error (capability4.slang, capability5.slang, capability6.slang).
* switch capability name to use `UnownedStringSlice` instead of `const char*`
switch capability name to use `UnownedStringSlice` instead of `const char*`, this includes using functions like `.startsWith`.
* grammer
---------
Co-authored-by: Yong He <yonghe@outlook.com>
|
| |
|
| |
Co-authored-by: Jay Kwak <82421531+jkwak-work@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes: #4675
Fixes: #4683
Fixes: #4443
Fixes: #4585
Fixes: #4172
Made the following changes:
1. All capability diagnostic printing logic tries to simplify before printing. This means that we do not print atoms which imply another atom.
2. Do not print the `_` prefix part of atom names since it is misleading users on what they should use to solve a capability issue encountered. (`_Internal` `External` atom changes are not in this PR)
3. Bundle together printing of all sets which contain exactly the same atoms (excluding abstract atoms). This allows printing the following `vertex/fragment/hull/domain/... + glsl` instead of `vertex + glsl | fragment + glsl | hull + glsl | domain + glsl | ....`
4. Rework how entry-point errors are reported to users (example at bottom of PR comment)
5. Rework how atom-provenance data is collected to be leaner and more useful so we can rework the errors. There are 2 notable changes here:
* We no longer store a list which describes where the first of an `CapabilityAtom` comes from. This heavily simplifies AST logic for the capability system. AST parsing of capabilities is much faster. The trade-off is faster AST parsing and correct AST node data for slower diagnostics if an error is found
* atom-provenance data now stores a reference to an atom's use-site to provide information on **where** and **what** is wrong with user code versus only sharing **what** and not where.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
entry-point (#4670)
* Fixes #4656
Changes:
1. Setting a profile via slangc no-longer sets an entry-point target-stage, this is to allow slangc to follow how the SLANG-API works (else `main` is assumed to be the default entry-point)
2. If the stage specified by a profile is not equal to the stage specified by a entry-point, we throw a capability error.
3. Resolving the stage of an entry point was changed to function (mostly) equally for when 0 entry-points are specified versus to when there are 1 or more.
4. changed capabilitySet Iterator so it is invalid if backing data is nullptr (although this should never happen, it would stop crashes in the worst case).
* remove the breaking change since it likely is going to be a lot more than just a simple change due to the implicit `main` and stage through `profile` code.
* print out profile name with errors
* use target's profile for printing
* change logic to print warning in a different method (account for more cases)
* set unknown stages
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* capability upgrade warning/error
adjusted implementation + tests to support a warning/error if capabilities are implicitly upgraded and test accordingly.
* add glsl profile caps
* add GLSL and HLSL capabilities to the associated capability
* syntax error in capdef
* only error if user explicitly enables capabilities
1. changed testing infrastructure to not set a `profile` explicitly,
2. Added tests to be sure this works as intended with user API and with slangc command line
* Change capability atom definitions and how Slang manages them to fix errors
1. most `glsl_spirv` version atoms have been removed from `.capdef`, instead we will translate `spirv` version atoms into `glsl_spirv` since there is no point in writing the same code twice in `.capdef` files to define `spirv` versions.
2. add spirv version, and hlsl sm version (and equivlent) capability dependencies
3. removed some stage requirments which were set on objects, keep the wrapper capabilities. I am keeping the wrapper capabilities since I am unaware on if there are stage limitations (spec says code in practice does not work).
* check internal version instead of version profile (_spirv_1_5 vs. spirv_1_5)
* remove unused OpCapability. adjust SPIRV version'ing again for glsl_spirv
* apply workaround for glslang bug with rayquery usage
* ensure capabilities targetted by a profile and added together by a user are valid
* remove additions to `spirv_1_*` wrapper
* spirv_* -> glsl_spirv fix
* fix bug where incompatable profiles would cause invalid target caps
* try to avoid joining invalid capabilities
* fix the warning/error & printing
* run through tests to fix capability system and test mistakes
many mistakes were mesh shaders doing `-profile glsl_450+spirv_1_4`. This is not allowed for a few reasons
1. the test tooling does not handle arguments the same as `slangc`
2. glsl_450 core profile does not support mesh shaders, nor does spirv_1_4. sm_6_5 does work in this senario
* set some sm_4_1 intrinsics to sm_4_0
* replace `GLSL_` defs with `glsl_`
* swap the unsupported render-test syntax for working syntax
* set d3d11/d3d12 profile defaults
this is required since sm version changes compiled code & behavior
* adjusted nvapi capabilities with atomics + d3d11 set to use sm_5_0 as per default
* cleanup
* address review
* incorrect styling
* change `bitscanForward` to work as intended on 32 bit targets
---------
Co-authored-by: Yong He <yonghe@outlook.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* SPIRV `Block` decoration fixes.
- SPIRV does not allow duplicate `Block` decorations. So we shouldn't be generating them.
- Also fixes duplication of OpName.
- SPIRV and HLSL do not allow ConstantBuffer with trailing unsized arrays. Added a check in the front-end against such code.
* Convert failing cross-compile tests to filecheck.
---------
Co-authored-by: Jay Kwak <82421531+jkwak-work@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* fixes: #4163
Precompute UIntSet from individual capabilities inside generator (removes intermediate form of capabilities).
note:
1. I still expand capabilities which are missing `target` and `stage` atoms.
* fix compile warning<->error with clang
* address review
preallocate the pregenerated UIntSet's
* disable incorrect warning of 'unreachable code'
The warning is wrong since, when `out` has 0 elements (does not start `for` loop), the `return` is reached.
* fix clang warnings
1. use unsigned long for the buffer serializer
2. braces around scalar init
* address review
added work around to avoid warning with `for(...) return; return;` pattern
`else if constexpr` addition instead of cascading blocks
* push fix for use of `_BitScanForward`
* cleanup
* move around assert for proper checking
* syntax error
* use SLANG_ASSERT instead of assert
* test for why SLANG_ASSERT caused CI to fail with linux-arm builds
* test if `SLANG_ASSERT` really is causing a build issue for linux-arm
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Capabilities System, Backing Logic Overhaul
Fixes #4015
Problems to address:
1. Currently the capabilities system spends anywhere from 25-50% of compile time on the CapabilityVisitor. Most of this time is spent on join logic: 1. Finding abstract atoms 2. Comparing list1<->list2. This should and can be made significantly faster.
2. Error system does not produce errors with auxiliary information. This will require a partial redesign to provide more useful semantic information for debugging.
What was addressed:
1. Array backed `CapabilityConjunctionSet` was replaced in-favor for a `UIntSet` backed `CapabilityTargetSets`. The design is described below.
Design:
* `CapabilityTargetSets` is a `Dictionary<targetAtom, CapabilityTargetSet>`. This is not an array for 2 reasons: 1. Easy to figure out which target is missing between two `CapabilityTargetSets` 2. To statically allocate an array requires the preprocessor to manually annotate which Capability is a target and link that Capability to an index. This means a dictionary is required for lookup regardless of implementation.
* `CapabilityTargetSet` is an intermediate representation of all capabilities for a singular `target` atom (`glsl`, `hlsl`, `metal`, ...). This structure contains a dictionary to all stage specific capability sets for fast lookup of stage capabilities supported by a `CapabilitySet` for a `target` atom. This reduces number of sets searched.
* `CapabilityStageSet` is an intermediate representation of all capabilities for a singular `stage` atom (`vertex`, `fragment`, ...). This structure holds all disjoint capability sets for a `stage`. A disjoint set is rare, but may exist in some scenarios (as an example): `{glsl, EXT_GL_FOO}{glsl, _GLSL_130, _GLSL_150}`. This reduces the number of sets searched.
* `UIntSet` is the main reason for the redesign for better performance and memory usage. All set operations only require a few operations, making all set logic trivial and with minimal cost to run. All algorithms were modified to focus around `UIntSet` operations.
2. Errors
* Semantic information are now better linked to the calling function to provide a connection of function<->function_body for when saving semantic information for errors.
* Missing targets now print errors much like other error code by finding code which could be a cause of incompatibility.
What is missing:
1. Add non naive support for non-stage specific capabilities such as `{hlsl, _sm_5_0}`. Currently non stage specific targets emulate the behavior through assigning such capabilities to every stage: `{hlsl, _sm_5_0, vertex} {hlsl, _sm_5_0, fragment}...`. Removal of this behavior would remove redundant shader stage sets being made at construction time (~80% of new implementation runtime). This is an addition, not an overhaul.
2. Optionally: `UIntSet` should be modified to support SIMD operations for significantly faster operations. This is not required immediately since `UIntSet` is already not a performance constraint.
Notes:
* UIntSet had implementation bugs which were fixed in this PR.
* The old capabilities system had bugs which were fixed in this PR when transforming to the new implementation.
* fix .natvis debug view
* Small optimizations I found while working on the addition
the AST building pass looks like so now:
1% = ~capabilitySet
2% = capabilitySet()
1.5% capabilitySet::unionWith()
0.8% capabilitySet::join()
1.5% auxillary info for debugging
~0.5-1% extra visitor overhead
~5% total for the visitor
~6.5% for total runtime costs
* fix caps which were wrong but worked
* push minor syntax fix (still looking for why other tests fail)
* perf & bug fixes
1. did not properly remake isBetterForTarget for this->empty case with that as Invalid. This is best case in this senario.
2. Remade seralizer for stdlib generation. Faster (more direct) & cleaner code.
NOTE: did not address review comments
* fix glsl.meta caps error
* fixing findBest logic again & UIntSet wrapper
findBest was not checking for 'more specialized' targets & was element counter was flawed
* faster getElements algorithm + natvis for UIntSet + wrong warning
* type incompatability of bitscanForward implementations
* try to fix warnings again
* remove ptr for clang intrinsic
* add missing header
* ifdef to allow clang compile
* compiler hackery to fix up platform/type independent operations
* bracket
* fix MSVC error
* missing template
* change types out again
* changes to fix compiling
* adjustment to parameter for Clang/GCC
* added iterator to delay processing all atomSets of a CapabilitySet
* add a few missing consts's
* ensure we never have more than 1 disjointSet
Added a wrapper + assert + union functionality to all possible disjoint sets. This was done in favor of a removal of the LinkedList for 2 reasons:
1. We still need 0-1 set functionality.
2. Might as well keep the code, just disallow the problematic functionality.
* address review comments
non linked-list refactor review comments addressed; add doc comments + remove redundant code
* comments + remove isValid for bool operator
* push removal of linkedlist for capabilities
* add missing break
* address review comments
minor adjustments of syntax
* push a fix to the `CapabilitySet({shader, missing target})` code
* quality + error
1. add iterator to UIntSet
2. do not specialize target_switch if profile is derived from case (GLSL_150 is not compatable with GLSL_400)
* fix target_switch erroring + temporarily remove UIntSet::Interator
temporarily remove UIntSet::Interator. It will be added after, testing code on CI first so I can multi-task fixing the UIntSet Iterator
* fix the UIntSet iterator
* Revert "fix the UIntSet iterator" temporarily to pull from master
* add metal error as per texture.slang
(took a while I realize this was why things were breaking, likely should adjust errors to reflect this)
* Rework UIntSet to have a template for output type
This is done so it is reasonable to debug the iterator output and not just dealing with messy int's
Fix problems with the iterators implemented + invalid capabilities handling
* removed incorrect `__target_switch` capability
barycentric was being used with anticipation of `profile glsl450`, this does not expand into `GL_EXT_fragment_shader_barycentric`, this instead caused an error which is hidden during cross-compile.
* remove some uses of getElements
* remove undeclared_stage for now
* remove redundant code associated with `undeclared_stage`
* remove unused variable
* address review
specifically to note removed static in a thread dangerous scope. Now using a `const static` for read only (thread safe) which precompile steps generate
* move GLSL_150 capdef change to sm_4_1 (more accurate)
* address most review comments
did not address: https://github.com/shader-slang/slang/pull/4145#discussion_r1602256776
* revert incorrect code review suggestion
* push changes for all code review suggestions
|
| | |
|
| |
|
|
|
|
|
|
|
| |
* Capability type checking.
* Fix.
---------
Co-authored-by: Yong He <yhe@nvidia.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Capability def parsing & codegen + disjoint sets
This change adds a capability definition file, and a code generator
to produce C++ code that defines the capability enums and necessary
data structures around the capabilities.
Extends the existing CapabilitySet class to support expressing
disjoint sets of capabilities. This sets up for the next change
that will enhance our type checking with reasoning of capability
requirements.
* Fix cmake.
* Fix warning.
* Fix.
* Fix isBetterForTarget to prefer less specialized option.
* Fix.
* Fix premake.
* Fix intrinsic.
* Fix vs sln file.
---------
Co-authored-by: Yong He <yhe@nvidia.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* WIP CommandOptions
* Fix some output issues.
* Simplify word wrapping.
* Add file extensions.
* Change how lookup takes place.
Add appendSplit functions to StringUtil.
Make Categories hold the index range of their options.
* Small improvement.
* Lookup with partial option names.
* Associate user values.
* Encoding flags in the name.
* Refactor setting up of command options.
* Use CommandOptions in slang-options.
* Remove old help text.
* Cache the CommandOptions on the Session.
* Range checking.
Fix bug in the Options handling.
* Extra checks for validity.
* Get categories directly.
* Slight improvements over output.
* Added NameValue types.
* Fix typo.
Remove some now unused diagnostics.
Fix diagnostic in testing, as output has changed.
* Add minimal usage message.
* Remove platform executable extension from diagnostics output.
* Some improvements around getting names from NameValue types.
* Improve some option descriptions.
* Small fixes.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
* #include an absolute path didn't work - because paths were taken to always be relative.
* Use capability system in docs.
Simplify how requirements/availability is produced.
* Small fixes in output of availablity.
* Updated stdlib doc.
* Small improvements.
Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
| |
* Fill in some missing bits of capability API
* Make invalid/unknown capability have a zero value (this aligns it better with the public API for `SlangProfileID`, so that the two can be merged down the line)
* Actually provide an implementation of `spFindCapability()` public API
* fixup: bug fixes for renumbering invalid capability atom
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Use "capability" system to select VKRT extension
Slang currently supports translation of ray tracing shader code to Vulkan GLSL code that uses the `GL_NV_ray_tracing` extension. A multi-vendor equivalent of that extension has been released as `GL_EXT_ray_tracing` and we want Slang to support that extension as well.
At the simplest, making the change from one extension to the other is just a matter of changing a few strings, since it does not appear that anything of significance was changed at the GLSL level (or even in SPIR-V). Where this gets trickier is when we have users who want us to support *both* extensions, and to be able to switch between them.
The solution we've implemented here more or less amounts to:
* If you don't tell the compiler which extension to use, it will default to `GL_EXT_ray_tracing` (the newer multi-vendor one).
* If you explicitly want the older extension, you can opt into it using the `-profile` option or via a new API for explicitly adding capabilities to your target.
Making that work required a few different kinds of changes:
* The options parsing and public API needed ways to add optional capabilities to a target.
* During GLSL code emit, we can check the capabilities that were added to the target to see if the `GL_NV_ray_tracing` extension was explicitly enabled and, if not, default to using the `GL_EXT_ray_tracing` names for things. This step is needed because some of the modifiers/attributes involved in the extension have to be handled explicitly in the code generator rather than implicitly as part of mapping intrinsic functions.
* We add two different translations to the relevant operatiosn in the stdlib, one marked with each of the extensions. If profile/capability-based overload resolution can be relied on to pick the right one, this should Just Work.
* Next, a bunch of work had to go into making capability-based overloading Just Work for the purposes of this change. There's been a nearly complete reworking of the implementation of `CapabilitySet` here to make it more suitable for our needs.
* The tests that were using ray tracing translation for Vulkan needed to be updated. For some of them I updated their baselines to use `GL_EXT_ray_tracing` so that they can test the new path. For others, I updated the command line for the test case so that it explicitly opts into using `GL_NV_ray_tracing`. The result is that we have some coverage of each extension. I would have liked to have each test run in both modes, but our pass-through glslang support doesn't support `-D` options, so I couldn't take that step easily.
This change does *not* add support for `GL_EXT_ray_query`, the extension that supports "DXR 1.1" style queries under Vulkan. Adding support for that extension should hopefully be a smaller step because it doesn't have the same multiple-extensions issue.
This change does *not* address a lot of possible avenues for improvement or cleanup around the capability system. It focuses only on those changes that are necessary to make the ray tracing feature work and leaves the rest for future work.
* fixup: infinite loop
* Comment-only change to retrigger TC build
|
|
|
* Add first steps toward a "capability" system
We already have cases in the stdlib where we mark declarations as being specific to certain targets, e.g.:
```
// My ordinary function to add two numbers.
// Works everywhere.
//
void myFunc(int a, int b) { return a + b; }
// On the "coolgpu" target, we can use a secret intrinsic
// that adds numbers even faster!
//
__specialized_for_target(coolgpu)
void myFunc(int a, int b) { return __secretIntrinsic(a, b); }
```
The existing logic for dealing with these modifiers (`__specialized_for_target` and `__target_intrinsic`) was almost entirely string-based. We would turn the chosen compilation target into a string, and then use that to try and search for the "best" definition of a function at a few steps:
* During IR linking, we always pick one definition of an `[import]`ed function, and that definition will be the one with the "best" target-specialization modifier (if any)
* During final code generation, we always look up the "best" target-intrinsic modifier, and use it as the template for the code we output.
This change preserves the basic flow there, but replaces the ad hoc string-based logic with something a bit more principled, in terms of a new `CapabilitySet` type.
A `CapabilitySet` represents a set of zero or more atomic features (here represented as `CapabilityAtom`s). What a `CapabilitySet` means depends on how and where it is used:
* A compilation target implies a `CapabilitySet` where the contents of the set are the features the target *supports*.
* A `CapabilitySet` attached to a declaration (or a modifier on that declaration) describes a set of feature that declaration *requires*.
The current implementation of `CapabilitySet` is wasteful and inefficient, but that is something we can iterate on over time.
In practice, most of the current code only ever uses capability sets that are either empty (because they represent a function with no specific requirements) or singleton (because they represent asingle atomic capability like "is a GLSL target," "is an HLSL target," etc.).
The main goal here was to put in the skeleton of a new system, including some of the features it might need down the line, and then to leave changes that eventually use the greater flexibility for later. Eventually, the capability system should encompass:
* Differences between shader model versions, GLSL versions, SPIR-V versions, etc. (currently tracked with other modifiers)
* Optional extensions, and functions that are made available only with certain extensions (currently tracked with other modifiers)
* Front-end checking that the call graph of a program doesn't violate any capability-requirements (e.g., having a GLSL+HLSL portable function call a GLSL-only subroutine)
* Hypothetically we can also try to fold stage-specific (vertex-only, fragment-only, etc.) functions into this system, but doing so would require more linker cleverness if we allow overloading on stages (since we might have to clone a caller if it calls through to a callee with multiple stage-specific versions)
One important complication that the system has to deal with just because of the "do what I mean" nature of the current compiler is that somethings a current Slang user might compile for target X and specify version N, but then use a function that actually requires version N+1 of that target. Currently the Slang compiler silently "upgrades" the version(s) used by user code in these cases, because it is often what users want in cross-compilation scenarios.
Dealing with the "silent upgrade" situation requires us to be a little careful and sometimes pick a "best" capability set that doesn't appear to be supported on our target. Refining that system and potentially getting rid of the "do what I mean" behavior over time could be a goal for future changes.
* fixup: handle case where value is incompatible during linking
|