| 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 | |