Improve target features support
Currently, @(enable_target_feature) enables the features globally in the project, and @(require_target_feature) seems unimplemented.
This PR aims to at a high level make @(enable_target_feature) procedure scoped, and @(require_target_feature) actually useful and implemented.
@(enable_target_feature)
Attribute that can be applied to procedure declarations, taking in a comma-seperated string of features to enable. The features in this list are only enabled for that procedure, this is useful for dynamic dispatch / runtime feature detection, allowing you to compile pieces of the project with certain features enabled.
Enable target features is not supported on WASM, it does not make sense in that context, all features have to be applied per WASM module.
Usage with #force_inline is viral due to LLVM limitations, a procedure that inlines a procedure with enabled target features is required to also set at least these enabled target features on its own declaration.
@(require_target_feature)
Attribute, much like enable target feature, that instead of enabling the feature, requires the build -target/-microarch/-target-features to support the feature. If that is not the case the compiler will error on direct calls, and disable it from any proc groups it is in.
Proc groups are also further supported by scoring the procedure based on the amount of features it lists for support, for example:
@(require_target_feature="aes,crc32")
a :: proc() {}
@(require_target_feature="aes")
b :: proc() {}
no :: proc() {}
group :: proc {
a,
b,
no,
}
Will prefer the procedure a over b over c depending on support from the target.
Having 2 procedures with 1 required feature, where both are supported is ambiguous and will error.
intrinsics.has_target_feature(...)
A new intrinsic that can be used for compile time feature detection. It takes either a constant string, or a procedure as it's argument and returns a boolean whether the features listed are supported by the -target/-microarch/-target-features.
For example:
@(require_target_feature="aes")
a :: proc() {}
main :: proc() {
when intrinsics.has_target_feature("aes") {}
// Alternatively:
when intrinsics.has_target_feature(a) {}
}
-strict-target-features
Some concern was raised by Jesse that he might not be comfortable with @(enable_target_features) and being able to compile code that is not supported by the target. For this I've added the -strict-target-features flag, this makes any @(enable_target_feature) behave exactly like it was @(require_target_feature).
Command-line help
Similar to -target:"?" and -microarch="?", -target-features:"?" is a thing.
When given (possibly in combination with a target and/or microarch) it will print out a list with all recognized features for the target architecture, if that feature is enabled based on the given -microarch, it is pointed out next to it.
For example:
$ odin build test.odin -file -target:windows_amd64 -target-features:"?"
Possible -target-features for target amd64 are:
16bit-mode
32bit-mode
3dnow
3dnowa
64bit (implied by target microarch x86-64-v2)
64bit-mode (implied by target microarch x86-64-v2)
adx
aes
# and many more...
Closes #2928 Closes #2663 Closes #3103