1 | use crate::target::TargetInfo; |
2 | use crate::{Build, Error, ErrorKind, Tool, ToolFamily}; |
3 | use std::borrow::Cow; |
4 | use std::ffi::OsString; |
5 | |
6 | #[derive (Debug, PartialEq, Default)] |
7 | pub(crate) struct RustcCodegenFlags<'a> { |
8 | branch_protection: Option<&'a str>, |
9 | code_model: Option<&'a str>, |
10 | no_vectorize_loops: bool, |
11 | no_vectorize_slp: bool, |
12 | profile_generate: Option<&'a str>, |
13 | profile_use: Option<&'a str>, |
14 | control_flow_guard: Option<&'a str>, |
15 | lto: Option<&'a str>, |
16 | relocation_model: Option<&'a str>, |
17 | embed_bitcode: Option<bool>, |
18 | force_frame_pointers: Option<bool>, |
19 | no_redzone: Option<bool>, |
20 | soft_float: Option<bool>, |
21 | dwarf_version: Option<u32>, |
22 | } |
23 | |
24 | impl<'this> RustcCodegenFlags<'this> { |
25 | // Parse flags obtained from CARGO_ENCODED_RUSTFLAGS |
26 | pub(crate) fn parse(rustflags_env: &'this str) -> Result<Self, Error> { |
27 | fn is_flag_prefix(flag: &str) -> bool { |
28 | [ |
29 | "-Z" , |
30 | "-C" , |
31 | "--codegen" , |
32 | "-L" , |
33 | "-l" , |
34 | "-o" , |
35 | "-W" , |
36 | "--warn" , |
37 | "-A" , |
38 | "--allow" , |
39 | "-D" , |
40 | "--deny" , |
41 | "-F" , |
42 | "--forbid" , |
43 | ] |
44 | .contains(&flag) |
45 | } |
46 | |
47 | fn handle_flag_prefix<'a>(prev: &'a str, curr: &'a str) -> (&'a str, &'a str) { |
48 | match prev { |
49 | "--codegen" | "-C" => ("-C" , curr), |
50 | // Handle flags passed like --codegen=code-model=small |
51 | _ if curr.starts_with("--codegen=" ) => ("-C" , &curr[10..]), |
52 | "-Z" => ("-Z" , curr), |
53 | "-L" | "-l" | "-o" => (prev, curr), |
54 | // Handle lint flags |
55 | "-W" | "--warn" => ("-W" , curr), |
56 | "-A" | "--allow" => ("-A" , curr), |
57 | "-D" | "--deny" => ("-D" , curr), |
58 | "-F" | "--forbid" => ("-F" , curr), |
59 | _ => ("" , curr), |
60 | } |
61 | } |
62 | |
63 | let mut codegen_flags = Self::default(); |
64 | |
65 | let mut prev_prefix = None; |
66 | for curr in rustflags_env.split(" \u{1f}" ) { |
67 | let prev = prev_prefix.take().unwrap_or("" ); |
68 | if prev.is_empty() && is_flag_prefix(curr) { |
69 | prev_prefix = Some(curr); |
70 | continue; |
71 | } |
72 | |
73 | let (prefix, rustc_flag) = handle_flag_prefix(prev, curr); |
74 | codegen_flags.set_rustc_flag(prefix, rustc_flag)?; |
75 | } |
76 | |
77 | Ok(codegen_flags) |
78 | } |
79 | |
80 | fn set_rustc_flag(&mut self, prefix: &str, flag: &'this str) -> Result<(), Error> { |
81 | // Convert a textual representation of a bool-like rustc flag argument into an actual bool |
82 | fn arg_to_bool(arg: impl AsRef<str>) -> Option<bool> { |
83 | match arg.as_ref() { |
84 | "y" | "yes" | "on" | "true" => Some(true), |
85 | "n" | "no" | "off" | "false" => Some(false), |
86 | _ => None, |
87 | } |
88 | } |
89 | |
90 | fn arg_to_u32(arg: impl AsRef<str>) -> Option<u32> { |
91 | arg.as_ref().parse().ok() |
92 | } |
93 | |
94 | let (flag, value) = if let Some((flag, value)) = flag.split_once('=' ) { |
95 | (flag, Some(value)) |
96 | } else { |
97 | (flag, None) |
98 | }; |
99 | let flag = if prefix.is_empty() { |
100 | Cow::Borrowed(flag) |
101 | } else { |
102 | Cow::Owned(format!(" {prefix}{flag}" )) |
103 | }; |
104 | |
105 | fn flag_ok_or<'flag>( |
106 | flag: Option<&'flag str>, |
107 | msg: &'static str, |
108 | ) -> Result<&'flag str, Error> { |
109 | flag.ok_or(Error::new(ErrorKind::InvalidFlag, msg)) |
110 | } |
111 | |
112 | match flag.as_ref() { |
113 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#code-model |
114 | "-Ccode-model" => { |
115 | self.code_model = Some(flag_ok_or(value, "-Ccode-model must have a value" )?); |
116 | } |
117 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-loops |
118 | "-Cno-vectorize-loops" => self.no_vectorize_loops = true, |
119 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-slp |
120 | "-Cno-vectorize-slp" => self.no_vectorize_slp = true, |
121 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-generate |
122 | "-Cprofile-generate" => { |
123 | self.profile_generate = |
124 | Some(flag_ok_or(value, "-Cprofile-generate must have a value" )?); |
125 | } |
126 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-use |
127 | "-Cprofile-use" => { |
128 | self.profile_use = Some(flag_ok_or(value, "-Cprofile-use must have a value" )?); |
129 | } |
130 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#control-flow-guard |
131 | "-Ccontrol-flow-guard" => self.control_flow_guard = value.or(Some("true" )), |
132 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#lto |
133 | "-Clto" => self.lto = value.or(Some("true" )), |
134 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#relocation-model |
135 | "-Crelocation-model" => { |
136 | self.relocation_model = |
137 | Some(flag_ok_or(value, "-Crelocation-model must have a value" )?); |
138 | } |
139 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#embed-bitcode |
140 | "-Cembed-bitcode" => self.embed_bitcode = value.map_or(Some(true), arg_to_bool), |
141 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#force-frame-pointers |
142 | "-Cforce-frame-pointers" => { |
143 | self.force_frame_pointers = value.map_or(Some(true), arg_to_bool) |
144 | } |
145 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-redzone |
146 | "-Cno-redzone" => self.no_redzone = value.map_or(Some(true), arg_to_bool), |
147 | // https://doc.rust-lang.org/rustc/codegen-options/index.html#soft-float |
148 | // Note: This flag is now deprecated in rustc. |
149 | "-Csoft-float" => self.soft_float = value.map_or(Some(true), arg_to_bool), |
150 | // https://doc.rust-lang.org/beta/unstable-book/compiler-flags/branch-protection.html |
151 | // FIXME: Drop the -Z variant and update the doc link once the option is stabilised |
152 | "-Zbranch-protection" | "-Cbranch-protection" => { |
153 | self.branch_protection = |
154 | Some(flag_ok_or(value, "-Zbranch-protection must have a value" )?); |
155 | } |
156 | // https://doc.rust-lang.org/beta/unstable-book/compiler-flags/dwarf-version.html |
157 | // FIXME: Drop the -Z variant and update the doc link once the option is stablized |
158 | "-Zdwarf-version" | "-Cdwarf-version" => { |
159 | self.dwarf_version = Some(value.and_then(arg_to_u32).ok_or(Error::new( |
160 | ErrorKind::InvalidFlag, |
161 | "-Zdwarf-version must have a value" , |
162 | ))?); |
163 | } |
164 | _ => {} |
165 | } |
166 | Ok(()) |
167 | } |
168 | |
169 | // Rust and clang/cc don't agree on what equivalent flags should look like. |
170 | pub(crate) fn cc_flags(&self, build: &Build, tool: &mut Tool, target: &TargetInfo<'_>) { |
171 | let family = tool.family; |
172 | // Push `flag` to `flags` if it is supported by the currently used CC |
173 | let mut push_if_supported = |flag: OsString| { |
174 | if build |
175 | .is_flag_supported_inner(&flag, tool, target) |
176 | .unwrap_or(false) |
177 | { |
178 | tool.args.push(flag); |
179 | } else { |
180 | build.cargo_output.print_warning(&format!( |
181 | "Inherited flag {:?} is not supported by the currently used CC" , |
182 | flag |
183 | )); |
184 | } |
185 | }; |
186 | |
187 | let clang_or_gnu = |
188 | matches!(family, ToolFamily::Clang { .. }) || matches!(family, ToolFamily::Gnu { .. }); |
189 | |
190 | // Flags shared between clang and gnu |
191 | if clang_or_gnu { |
192 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mbranch-protection |
193 | // https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-mbranch-protection (Aarch64) |
194 | // https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mbranch-protection-1 (ARM) |
195 | // https://developer.arm.com/documentation/101754/0619/armclang-Reference/armclang-Command-line-Options/-mbranch-protection |
196 | if let Some(value) = self.branch_protection { |
197 | push_if_supported( |
198 | format!("-mbranch-protection= {}" , value.replace("," , "+" )).into(), |
199 | ); |
200 | } |
201 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mcmodel |
202 | // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mcmodel=`). |
203 | // FIXME(madsmtm): Parse the model, to make sure we pass the correct value (depending on arch). |
204 | if let Some(value) = self.code_model { |
205 | push_if_supported(format!("-mcmodel= {value}" ).into()); |
206 | } |
207 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-vectorize |
208 | // https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html |
209 | if self.no_vectorize_loops { |
210 | push_if_supported("-fno-vectorize" .into()); |
211 | } |
212 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-slp-vectorize |
213 | // https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html |
214 | if self.no_vectorize_slp { |
215 | push_if_supported("-fno-slp-vectorize" .into()); |
216 | } |
217 | if let Some(value) = self.relocation_model { |
218 | let cc_flag = match value { |
219 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIC |
220 | // https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIC |
221 | "pic" => Some("-fPIC" ), |
222 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIE |
223 | // https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIE |
224 | "pie" => Some("-fPIE" ), |
225 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mdynamic-no-pic |
226 | // https://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#index-mdynamic-no-pic |
227 | "dynamic-no-pic" => Some("-mdynamic-no-pic" ), |
228 | _ => None, |
229 | }; |
230 | if let Some(cc_flag) = cc_flag { |
231 | push_if_supported(cc_flag.into()); |
232 | } |
233 | } |
234 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-omit-frame-pointer |
235 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fomit-frame-pointer |
236 | // https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fomit-frame-pointer |
237 | if let Some(value) = self.force_frame_pointers { |
238 | let cc_flag = if value { |
239 | "-fno-omit-frame-pointer" |
240 | } else { |
241 | "-fomit-frame-pointer" |
242 | }; |
243 | push_if_supported(cc_flag.into()); |
244 | } |
245 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mno-red-zone |
246 | // https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mno-red-zone |
247 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mred-zone |
248 | // https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mred-zone |
249 | if let Some(value) = self.no_redzone { |
250 | let cc_flag = if value { "-mno-red-zone" } else { "-mred-zone" }; |
251 | push_if_supported(cc_flag.into()); |
252 | } |
253 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-msoft-float |
254 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mhard-float |
255 | // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-msoft-float`). |
256 | // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mhard-float`). |
257 | if let Some(value) = self.soft_float { |
258 | let cc_flag = if value { |
259 | "-msoft-float" |
260 | } else { |
261 | // Do not use -mno-soft-float, that's basically just an alias for -mno-implicit-float. |
262 | "-mhard-float" |
263 | }; |
264 | push_if_supported(cc_flag.into()); |
265 | } |
266 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-gdwarf-2 |
267 | // https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-gdwarf |
268 | if let Some(value) = self.dwarf_version { |
269 | push_if_supported(format!("-gdwarf- {value}" ).into()); |
270 | } |
271 | } |
272 | |
273 | // Compiler-exclusive flags |
274 | match family { |
275 | ToolFamily::Clang { .. } => { |
276 | // GNU and Clang compilers both support the same PGO flags, but they use different libraries and |
277 | // different formats for the profile files which are not compatible. |
278 | // clang and rustc both internally use llvm, so we want to inherit the PGO flags only for clang. |
279 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-generate |
280 | if let Some(value) = self.profile_generate { |
281 | push_if_supported(format!("-fprofile-generate= {value}" ).into()); |
282 | } |
283 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-use |
284 | if let Some(value) = self.profile_use { |
285 | push_if_supported(format!("-fprofile-use= {value}" ).into()); |
286 | } |
287 | |
288 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fembed-bitcode |
289 | if let Some(value) = self.embed_bitcode { |
290 | let cc_val = if value { "all" } else { "off" }; |
291 | push_if_supported(format!("-fembed-bitcode= {cc_val}" ).into()); |
292 | } |
293 | |
294 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-flto |
295 | if let Some(value) = self.lto { |
296 | let cc_val = match value { |
297 | "y" | "yes" | "on" | "true" | "fat" => Some("full" ), |
298 | "thin" => Some("thin" ), |
299 | _ => None, |
300 | }; |
301 | if let Some(cc_val) = cc_val { |
302 | push_if_supported(format!("-flto= {cc_val}" ).into()); |
303 | } |
304 | } |
305 | // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mguard |
306 | if let Some(value) = self.control_flow_guard { |
307 | let cc_val = match value { |
308 | "y" | "yes" | "on" | "true" | "checks" => Some("cf" ), |
309 | "nochecks" => Some("cf-nochecks" ), |
310 | "n" | "no" | "off" | "false" => Some("none" ), |
311 | _ => None, |
312 | }; |
313 | if let Some(cc_val) = cc_val { |
314 | push_if_supported(format!("-mguard= {cc_val}" ).into()); |
315 | } |
316 | } |
317 | } |
318 | ToolFamily::Gnu { .. } => {} |
319 | ToolFamily::Msvc { .. } => { |
320 | // https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard |
321 | if let Some(value) = self.control_flow_guard { |
322 | let cc_val = match value { |
323 | "y" | "yes" | "on" | "true" | "checks" => Some("cf" ), |
324 | "n" | "no" | "off" | "false" => Some("cf-" ), |
325 | _ => None, |
326 | }; |
327 | if let Some(cc_val) = cc_val { |
328 | push_if_supported(format!("/guard: {cc_val}" ).into()); |
329 | } |
330 | } |
331 | // https://learn.microsoft.com/en-us/cpp/build/reference/oy-frame-pointer-omission |
332 | if let Some(value) = self.force_frame_pointers { |
333 | // Flag is unsupported on 64-bit arches |
334 | if !target.arch.contains("64" ) { |
335 | let cc_flag = if value { "/Oy-" } else { "/Oy" }; |
336 | push_if_supported(cc_flag.into()); |
337 | } |
338 | } |
339 | } |
340 | } |
341 | } |
342 | } |
343 | |
344 | #[cfg (test)] |
345 | mod tests { |
346 | use super::*; |
347 | |
348 | #[track_caller ] |
349 | fn check(env: &str, expected: &RustcCodegenFlags) { |
350 | let actual = RustcCodegenFlags::parse(env).unwrap(); |
351 | assert_eq!(actual, *expected); |
352 | } |
353 | |
354 | #[test ] |
355 | fn codegen_type() { |
356 | let expected = RustcCodegenFlags { |
357 | code_model: Some("tiny" ), |
358 | ..RustcCodegenFlags::default() |
359 | }; |
360 | check("-Ccode-model=tiny" , &expected); |
361 | check("-C \u{1f}code-model=tiny" , &expected); |
362 | check("--codegen \u{1f}code-model=tiny" , &expected); |
363 | check("--codegen=code-model=tiny" , &expected); |
364 | } |
365 | |
366 | #[test ] |
367 | fn precedence() { |
368 | check( |
369 | "-ccode-model=tiny \u{1f}-Ccode-model=small" , |
370 | &RustcCodegenFlags { |
371 | code_model: Some("small" ), |
372 | ..RustcCodegenFlags::default() |
373 | }, |
374 | ); |
375 | } |
376 | |
377 | #[test ] |
378 | fn two_valid_prefixes() { |
379 | let expected = RustcCodegenFlags::default(); |
380 | check("-L \u{1f}-Clto" , &expected); |
381 | } |
382 | |
383 | #[test ] |
384 | fn three_valid_prefixes() { |
385 | let expected = RustcCodegenFlags { |
386 | lto: Some("true" ), |
387 | ..RustcCodegenFlags::default() |
388 | }; |
389 | check("-L \u{1f}-L \u{1f}-Clto" , &expected); |
390 | } |
391 | |
392 | #[test ] |
393 | fn all_rustc_flags() { |
394 | // Throw all possible flags at the parser to catch false positives |
395 | let flags = [ |
396 | // Set all the flags we recognise first |
397 | "-Ccode-model=tiny" , |
398 | "-Ccontrol-flow-guard=yes" , |
399 | "-Cembed-bitcode=no" , |
400 | "-Cforce-frame-pointers=yes" , |
401 | "-Clto=false" , |
402 | "-Clink-dead-code=yes" , |
403 | "-Cno-redzone=yes" , |
404 | "-Cno-vectorize-loops" , |
405 | "-Cno-vectorize-slp" , |
406 | "-Cprofile-generate=fooprofile" , |
407 | "-Cprofile-use=fooprofile" , |
408 | "-Crelocation-model=pic" , |
409 | "-Csoft-float=yes" , |
410 | "-Zbranch-protection=bti,pac-ret,leaf" , |
411 | "-Zdwarf-version=5" , |
412 | // Set flags we don't recognise but rustc supports next |
413 | // rustc flags |
414 | "--cfg" , |
415 | "a" , |
416 | "--check-cfg 'cfg(verbose)" , |
417 | "-L" , |
418 | "/usr/lib/foo" , |
419 | "-l" , |
420 | "static:+whole-archive=mylib" , |
421 | "--crate-type=dylib" , |
422 | "--crate-name=foo" , |
423 | "--edition=2021" , |
424 | "--emit=asm" , |
425 | "--print=crate-name" , |
426 | "-g" , |
427 | "-O" , |
428 | "-o" , |
429 | "foooutput" , |
430 | "--out-dir" , |
431 | "foooutdir" , |
432 | "--target" , |
433 | "aarch64-unknown-linux-gnu" , |
434 | "-W" , |
435 | "missing-docs" , |
436 | "-D" , |
437 | "unused-variables" , |
438 | "--force-warn" , |
439 | "dead-code" , |
440 | "-A" , |
441 | "unused" , |
442 | "-F" , |
443 | "unused" , |
444 | "--cap-lints" , |
445 | "warn" , |
446 | "--version" , |
447 | "--verbose" , |
448 | "-v" , |
449 | "--extern" , |
450 | "foocrate" , |
451 | "--sysroot" , |
452 | "fooroot" , |
453 | "--error-format" , |
454 | "human" , |
455 | "--color" , |
456 | "auto" , |
457 | "--diagnostic-width" , |
458 | "80" , |
459 | "--remap-path-prefix" , |
460 | "foo=bar" , |
461 | "--json=artifact" , |
462 | // Codegen flags |
463 | "-Car" , |
464 | "-Ccodegen-units=1" , |
465 | "-Ccollapse-macro-debuginfo=yes" , |
466 | "-Cdebug-assertions=yes" , |
467 | "-Cdebuginfo=1" , |
468 | "-Cdefault-linker-libraries=yes" , |
469 | "-Cdlltool=foo" , |
470 | "-Cextra-filename=foo" , |
471 | "-Cforce-unwind-tables=yes" , |
472 | "-Cincremental=foodir" , |
473 | "-Cinline-threshold=6" , |
474 | "-Cinstrument-coverage" , |
475 | "-Clink-arg=-foo" , |
476 | "-Clink-args=-foo" , |
477 | "-Clink-self-contained=yes" , |
478 | "-Clinker=lld" , |
479 | "-Clinker-flavor=ld.lld" , |
480 | "-Clinker-plugin-lto=yes" , |
481 | "-Cllvm-args=foo" , |
482 | "-Cmetadata=foo" , |
483 | "-Cno-prepopulate-passes" , |
484 | "-Cno-stack-check" , |
485 | "-Copt-level=3" , |
486 | "-Coverflow-checks=yes" , |
487 | "-Cpanic=abort" , |
488 | "-Cpasses=foopass" , |
489 | "-Cprefer-dynamic=yes" , |
490 | "-Crelro-level=partial" , |
491 | "-Cremark=all" , |
492 | "-Crpath=yes" , |
493 | "-Csave-temps=yes" , |
494 | "-Csplit-debuginfo=packed" , |
495 | "-Cstrip=symbols" , |
496 | "-Csymbol-mangling-version=v0" , |
497 | "-Ctarget-cpu=native" , |
498 | "-Ctarget-feature=+sve" , |
499 | // Unstable options |
500 | "-Ztune-cpu=machine" , |
501 | ]; |
502 | check( |
503 | &flags.join(" \u{1f}" ), |
504 | &RustcCodegenFlags { |
505 | code_model: Some("tiny" ), |
506 | control_flow_guard: Some("yes" ), |
507 | embed_bitcode: Some(false), |
508 | force_frame_pointers: Some(true), |
509 | lto: Some("false" ), |
510 | no_redzone: Some(true), |
511 | no_vectorize_loops: true, |
512 | no_vectorize_slp: true, |
513 | profile_generate: Some("fooprofile" ), |
514 | profile_use: Some("fooprofile" ), |
515 | relocation_model: Some("pic" ), |
516 | soft_float: Some(true), |
517 | branch_protection: Some("bti,pac-ret,leaf" ), |
518 | dwarf_version: Some(5), |
519 | }, |
520 | ); |
521 | } |
522 | } |
523 | |