aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2023-12-15 17:29:59 +0900
committerYawning Angel <yawning@schwanenlied.me>2024-01-07 20:04:40 +0900
commitcd65a15d81b32636c5097200446cc6d6afc7199b (patch)
tree27d17da8cbc4eb1e9d6380e2179968b0cc87d333 /src/llvm_backend.cpp
parent9235e8245193fb891e46ee4a7daa3e101ff8032a (diff)
src: `enable_target_feature` should add features, not overwrite
`llvm_features` being empty is the default state, and implies the presence of certain features. Previously if any target features were explicitly enabled by the `enable_target_feature` attribute, they were added comma separated to `llvm_features`. For example: `lzcnt,popcnt,...,sse4.2,sse` This was causing LLVM to try to target a CPU that *ONLY* has the explicitly enabled features. This now will prefix explicitly enabled features with a `+`, and preserve the existing `llvm_features` string by appending to it if it is set.
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp41
1 files changed, 40 insertions, 1 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index ca71a0f45..b90fd8495 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -2531,7 +2531,46 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
*/
if (build_context.target_features_set.entries.count != 0) {
- llvm_features = target_features_set_to_cstring(permanent_allocator(), false);
+ // Prefix all of the features with a `+`, because we are
+ // enabling additional features.
+ char const *additional_features = target_features_set_to_cstring(permanent_allocator(), false, true);
+
+ String f_string = make_string_c(llvm_features);
+ String a_string = make_string_c(additional_features);
+ isize f_len = f_string.len;
+
+ if (f_len == 0) {
+ // The common case is that llvm_features is empty, so
+ // the target_features_set additions can be used as is.
+ llvm_features = additional_features;
+ } else {
+ // The user probably specified `-microarch:native`, so
+ // llvm_features is populated by LLVM's idea of what
+ // the host CPU supports.
+ //
+ // As far as I can tell, (which is barely better than
+ // wild guessing), a bitset is formed by parsing the
+ // string left to right.
+ //
+ // So, llvm_features + ',' + additonal_features, will
+ // makes the target_features_set override llvm_features.
+
+ char *tmp = gb_alloc_array(permanent_allocator(), char, f_len + 1 + a_string.len + 1);
+ isize len = 0;
+
+ // tmp = f_string
+ gb_memmove(tmp, f_string.text, f_string.len);
+ len += f_string.len;
+ // tmp += ','
+ tmp[len++] = ',';
+ // tmp += a_string
+ gb_memmove(tmp + len, a_string.text, a_string.len);
+ len += a_string.len;
+ // tmp += NUL
+ tmp[len++] = 0;
+
+ llvm_features = tmp;
+ }
}
// GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target));