@@ -118,10 +118,14 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
118118 take_arg!( "-fdebug-compilation-dir" , OsString , Separated , PassThrough ) ,
119119 flag!( "-fmodules" , TooHardFlag ) ,
120120 flag!( "-fno-color-diagnostics" , NoDiagnosticsColorFlag ) ,
121+ flag!( "-fno-profile-instr-generate" , TooHardFlag ) ,
122+ flag!( "-fno-profile-instr-use" , TooHardFlag ) ,
121123 take_arg!( "-fplugin" , PathBuf , CanBeConcatenated ( '=' ) , ExtraHashFile ) ,
122124 flag!( "-fprofile-instr-generate" , ProfileGenerate ) ,
123- // Can be either -fprofile-instr-use or -fprofile-instr-use=path
124- take_arg!( "-fprofile-instr-use" , OsString , Concatenated , TooHard ) ,
125+ // Note: the PathBuf argument is optional
126+ take_arg!( "-fprofile-instr-use" , PathBuf , Concatenated ( '=' ) , ClangProfileUse ) ,
127+ // Note: this overrides the -fprofile-use option in gcc.rs.
128+ take_arg!( "-fprofile-use" , PathBuf , Concatenated ( '=' ) , ClangProfileUse ) ,
125129 take_arg!( "-fsanitize-blacklist" , PathBuf , Concatenated ( '=' ) , ExtraHashFile ) ,
126130 take_arg!( "-gcc-toolchain" , OsString , Separated , PassThrough ) ,
127131 take_arg!( "-include-pch" , PathBuf , CanBeSeparated , PreprocessorArgumentPath ) ,
@@ -132,6 +136,27 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
132136 flag!( "-verify" , PreprocessorArgumentFlag ) ,
133137] ) ;
134138
139+ // Maps the `-fprofile-use` argument to the actual path of the
140+ // .profdata file Clang will try to use.
141+ pub ( crate ) fn resolve_profile_use_path ( arg : & Path , cwd : & Path ) -> PathBuf {
142+ // Note that `arg` might be empty (if no argument was given to
143+ // -fprofile-use), in which case `path` will be `cwd` after
144+ // the next statement and "./default.profdata" at the end of the
145+ // block. This matches Clang's behavior for when no argument is
146+ // given.
147+ let mut path = cwd. join ( arg) ;
148+
149+ assert ! ( !arg. as_os_str( ) . is_empty( ) || path == cwd) ;
150+
151+ // Clang allows specifying a directory here, in which case it
152+ // will look for the file `default.profdata` in that directory.
153+ if path. is_dir ( ) {
154+ path. push ( "default.profdata" ) ;
155+ }
156+
157+ path
158+ }
159+
135160#[ cfg( test) ]
136161mod test {
137162 use super :: * ;
@@ -406,4 +431,104 @@ mod test {
406431 let a = parses ! ( "-c" , "foo.c" , "-o" , "foo.o" ) ;
407432 assert_eq ! ( a. color_mode, ColorMode :: Auto ) ;
408433 }
434+
435+ #[ test]
436+ fn test_parse_arguments_profile_instr_use ( ) {
437+ let a = parses ! (
438+ "-c" ,
439+ "foo.c" ,
440+ "-o" ,
441+ "foo.o" ,
442+ "-fprofile-instr-use=foo.profdata"
443+ ) ;
444+ assert_eq ! ( ovec![ "-fprofile-instr-use=foo.profdata" ] , a. common_args) ;
445+ assert_eq ! (
446+ ovec![ std:: env:: current_dir( ) . unwrap( ) . join( "foo.profdata" ) ] ,
447+ a. extra_hash_files
448+ ) ;
449+ }
450+
451+ #[ test]
452+ fn test_parse_arguments_profile_use ( ) {
453+ let a = parses ! ( "-c" , "foo.c" , "-o" , "foo.o" , "-fprofile-use=xyz.profdata" ) ;
454+
455+ assert_eq ! ( ovec![ "-fprofile-use=xyz.profdata" ] , a. common_args) ;
456+ assert_eq ! (
457+ ovec![ std:: env:: current_dir( ) . unwrap( ) . join( "xyz.profdata" ) ] ,
458+ a. extra_hash_files
459+ ) ;
460+ }
461+
462+ #[ test]
463+ fn test_parse_arguments_profile_use_with_directory ( ) {
464+ let a = parses ! ( "-c" , "foo.c" , "-o" , "foo.o" , "-fprofile-use=." ) ;
465+
466+ assert_eq ! ( ovec![ "-fprofile-use=." ] , a. common_args) ;
467+ assert_eq ! (
468+ ovec![ std:: env:: current_dir( ) . unwrap( ) . join( "default.profdata" ) ] ,
469+ a. extra_hash_files
470+ ) ;
471+ }
472+
473+ #[ test]
474+ fn test_parse_arguments_profile_use_with_no_argument ( ) {
475+ let a = parses ! ( "-c" , "foo.c" , "-o" , "foo.o" , "-fprofile-use" ) ;
476+
477+ assert_eq ! ( ovec![ "-fprofile-use" ] , a. common_args) ;
478+ assert_eq ! (
479+ ovec![ std:: env:: current_dir( ) . unwrap( ) . join( "default.profdata" ) ] ,
480+ a. extra_hash_files
481+ ) ;
482+ }
483+
484+ #[ test]
485+ fn test_parse_arguments_pgo_cancellation ( ) {
486+ assert_eq ! (
487+ CompilerArguments :: CannotCache ( "-fno-profile-use" , None ) ,
488+ parse_arguments_( stringvec![
489+ "-c" ,
490+ "foo.c" ,
491+ "-o" ,
492+ "foo.o" ,
493+ "-fprofile-use" ,
494+ "-fno-profile-use"
495+ ] )
496+ ) ;
497+
498+ assert_eq ! (
499+ CompilerArguments :: CannotCache ( "-fno-profile-instr-use" , None ) ,
500+ parse_arguments_( stringvec![
501+ "-c" ,
502+ "foo.c" ,
503+ "-o" ,
504+ "foo.o" ,
505+ "-fprofile-instr-use" ,
506+ "-fno-profile-instr-use"
507+ ] )
508+ ) ;
509+
510+ assert_eq ! (
511+ CompilerArguments :: CannotCache ( "-fno-profile-generate" , None ) ,
512+ parse_arguments_( stringvec![
513+ "-c" ,
514+ "foo.c" ,
515+ "-o" ,
516+ "foo.o" ,
517+ "-fprofile-generate" ,
518+ "-fno-profile-generate"
519+ ] )
520+ ) ;
521+
522+ assert_eq ! (
523+ CompilerArguments :: CannotCache ( "-fno-profile-instr-generate" , None ) ,
524+ parse_arguments_( stringvec![
525+ "-c" ,
526+ "foo.c" ,
527+ "-o" ,
528+ "foo.o" ,
529+ "-fprofile-instr-generate" ,
530+ "-fno-profile-instr-generate"
531+ ] )
532+ ) ;
533+ }
409534}
0 commit comments