diff options
| author | Yawning Angel <yawning@schwanenlied.me> | 2023-12-15 17:29:59 +0900 |
|---|---|---|
| committer | Yawning Angel <yawning@schwanenlied.me> | 2024-01-07 20:04:40 +0900 |
| commit | cd65a15d81b32636c5097200446cc6d6afc7199b (patch) | |
| tree | 27d17da8cbc4eb1e9d6380e2179968b0cc87d333 /src/llvm_backend.cpp | |
| parent | 9235e8245193fb891e46ee4a7daa3e101ff8032a (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.cpp | 41 |
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)); |