@@ -8,7 +8,7 @@ use std::process::Command;
88
99use  tracing:: * ; 
1010
11- use  crate :: common:: { Config ,  Debugger ,  FailMode ,  Mode ,  PassMode } ; 
11+ use  crate :: common:: { Config ,  Debugger ,  FailMode ,  LlvmVersion ,   Mode ,  PassMode } ; 
1212use  crate :: debuggers:: { extract_cdb_version,  extract_gdb_version} ; 
1313use  crate :: header:: auxiliary:: { AuxProps ,  parse_and_update_aux} ; 
1414use  crate :: header:: cfg:: { MatchOutcome ,  parse_cfg_name_directive} ; 
@@ -1113,34 +1113,45 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
11131113    Some ( ( regex,  replacement) ) 
11141114} 
11151115
1116- pub  fn  extract_llvm_version ( version :  & str )  -> Option < u32 >  { 
1117-     let  pat = |c :  char | !c. is_ascii_digit ( )  && c != '.' ; 
1118-     let  version_without_suffix = match  version. find ( pat)  { 
1119-         Some ( pos)  => & version[ ..pos] , 
1116+ /// Given an llvm version string that looks like `1.2.3-rc1`, extract key version info into a 
1117+ /// [`LlvmVersion`]. 
1118+ /// 
1119+ /// Currently panics if the input string is malformed, though we really should not use panic as an 
1120+ /// error handling strategy. 
1121+ /// 
1122+ /// FIXME(jieyouxu): improve error handling 
1123+ pub  fn  extract_llvm_version ( version :  & str )  -> LlvmVersion  { 
1124+     // The version substring we're interested in usually looks like the `1.2.3`, without any of the 
1125+     // fancy suffix like `-rc1` or `meow`. 
1126+     let  version = version. trim ( ) ; 
1127+     let  uninterested = |c :  char | !c. is_ascii_digit ( )  && c != '.' ; 
1128+     let  version_without_suffix = match  version. split_once ( uninterested)  { 
1129+         Some ( ( prefix,  _suffix) )  => prefix, 
11201130        None  => version, 
11211131    } ; 
1132+ 
11221133    let  components:  Vec < u32 >  = version_without_suffix
11231134        . split ( '.' ) 
1124-         . map ( |s| s. parse ( ) . expect ( "Malformed  version component" ) ) 
1135+         . map ( |s| s. parse ( ) . expect ( "llvm  version component should consist of only digits " ) ) 
11251136        . collect ( ) ; 
1126-      let  version =  match   * components  { 
1127-          [ a ]  => a  *   10_000 , 
1128-         [ a ,  b ]  => a  *   10_000  + b  *   100 , 
1129-         [ a ,  b ,  c ]  => a  *   10_000  + b  *   100  + c , 
1130-         _  => panic ! ( "Malformed version" ) , 
1131-     } ; 
1132-     Some ( version ) 
1137+ 
1138+     match   & components [ .. ]   { 
1139+         [ major ]  => LlvmVersion :: new ( * major ,   0 ,   0 ) , 
1140+         [ major ,  minor ]  => LlvmVersion :: new ( * major ,   * minor ,   0 ) , 
1141+         [ major ,  minor ,  patch ]   => LlvmVersion :: new ( * major ,   * minor ,   * patch ) , 
1142+         _ =>  panic ! ( "malformed llvm version string, expected only 1-3 components: {version}" ) , 
1143+     } 
11331144} 
11341145
1135- pub  fn  extract_llvm_version_from_binary ( binary_path :  & str )  -> Option < u32 >  { 
1146+ pub  fn  extract_llvm_version_from_binary ( binary_path :  & str )  -> Option < LlvmVersion >  { 
11361147    let  output = Command :: new ( binary_path) . arg ( "--version" ) . output ( ) . ok ( ) ?; 
11371148    if  !output. status . success ( )  { 
11381149        return  None ; 
11391150    } 
11401151    let  version = String :: from_utf8 ( output. stdout ) . ok ( ) ?; 
11411152    for  line in  version. lines ( )  { 
11421153        if  let  Some ( version)  = line. split ( "LLVM version " ) . nth ( 1 )  { 
1143-             return  extract_llvm_version ( version) ; 
1154+             return  Some ( extract_llvm_version ( version) ) ; 
11441155        } 
11451156    } 
11461157    None 
@@ -1247,15 +1258,14 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
12471258    false 
12481259} 
12491260
1250- /// Takes a directive of the form `"<version1> [- <version2>]"`, 
1251- /// returns the numeric representation of `<version1>` and `<version2>` as 
1252- /// tuple: `(<version1> as u32, <version2> as u32)`. 
1261+ /// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation 
1262+ /// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`. 
12531263/// 
1254- /// If the `<version2>` part is omitted, the second component of the tuple 
1255- /// is the same as  `<version1>`. 
1256- fn  extract_version_range < F > ( line :  & str ,  parse :  F )  -> Option < ( u32 ,   u32 ) > 
1264+ /// If the `<version2>` part is omitted, the second component of the tuple is the same as  
1265+ /// `<version1>`. 
1266+ fn  extract_version_range < F ,   VersionTy :   Copy > ( line :  & str ,  parse :  F )  -> Option < ( VersionTy ,   VersionTy ) > 
12571267where 
1258-     F :  Fn ( & str )  -> Option < u32 > , 
1268+     F :  Fn ( & str )  -> Option < VersionTy > , 
12591269{ 
12601270    let  mut  splits = line. splitn ( 2 ,  "- " ) . map ( str:: trim) ; 
12611271    let  min = splits. next ( ) . unwrap ( ) ; 
@@ -1490,42 +1500,54 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
14901500        } 
14911501    } 
14921502    if  let  Some ( actual_version)  = config. llvm_version  { 
1493-         if  let  Some ( rest)  = line. strip_prefix ( "min-llvm-version:" ) . map ( str:: trim)  { 
1494-             let  min_version = extract_llvm_version ( rest) . unwrap ( ) ; 
1495-             // Ignore if actual version is smaller the minimum required 
1496-             // version 
1503+         // Note that these `min` versions will check for not just major versions. 
1504+ 
1505+         if  let  Some ( version_string)  = config. parse_name_value_directive ( line,  "min-llvm-version" )  { 
1506+             let  min_version = extract_llvm_version ( & version_string) ; 
1507+             // Ignore if actual version is smaller than the minimum required version. 
14971508            if  actual_version < min_version { 
14981509                return  IgnoreDecision :: Ignore  { 
1499-                     reason :  format ! ( "ignored when the LLVM version is older than {rest}" ) , 
1510+                     reason :  format ! ( 
1511+                         "ignored when the LLVM version {actual_version} is older than {min_version}" 
1512+                     ) , 
15001513                } ; 
15011514            } 
1502-         }  else  if  let  Some ( rest)  = line. strip_prefix ( "min-system-llvm-version:" ) . map ( str:: trim)  { 
1503-             let  min_version = extract_llvm_version ( rest) . unwrap ( ) ; 
1515+         }  else  if  let  Some ( version_string)  =
1516+             config. parse_name_value_directive ( line,  "min-system-llvm-version" ) 
1517+         { 
1518+             let  min_version = extract_llvm_version ( & version_string) ; 
15041519            // Ignore if using system LLVM and actual version 
15051520            // is smaller the minimum required version 
15061521            if  config. system_llvm  && actual_version < min_version { 
15071522                return  IgnoreDecision :: Ignore  { 
1508-                     reason :  format ! ( "ignored when the system LLVM version is older than {rest}" ) , 
1523+                     reason :  format ! ( 
1524+                         "ignored when the system LLVM version {actual_version} is older than {min_version}" 
1525+                     ) , 
15091526                } ; 
15101527            } 
1511-         }  else  if  let  Some ( rest)  = line. strip_prefix ( "ignore-llvm-version:" ) . map ( str:: trim)  { 
1528+         }  else  if  let  Some ( version_range)  =
1529+             config. parse_name_value_directive ( line,  "ignore-llvm-version" ) 
1530+         { 
15121531            // Syntax is: "ignore-llvm-version: <version1> [- <version2>]" 
15131532            let  ( v_min,  v_max)  =
1514-                 extract_version_range ( rest,  extract_llvm_version) . unwrap_or_else ( || { 
1515-                     panic ! ( "couldn't parse version range: {:?}" ,  rest) ; 
1516-                 } ) ; 
1533+                 extract_version_range ( & version_range,  |s| Some ( extract_llvm_version ( s) ) ) 
1534+                     . unwrap_or_else ( || { 
1535+                         panic ! ( "couldn't parse version range: \" {version_range}\" " ) ; 
1536+                     } ) ; 
15171537            if  v_max < v_min { 
1518-                 panic ! ( "Malformed  LLVM version range: max < min " ) 
1538+                 panic ! ( "malformed  LLVM version range where {v_max} < {v_min} " ) 
15191539            } 
15201540            // Ignore if version lies inside of range. 
15211541            if  actual_version >= v_min && actual_version <= v_max { 
15221542                if  v_min == v_max { 
15231543                    return  IgnoreDecision :: Ignore  { 
1524-                         reason :  format ! ( "ignored when the LLVM version is {rest }" ) , 
1544+                         reason :  format ! ( "ignored when the LLVM version is {actual_version }" ) , 
15251545                    } ; 
15261546                }  else  { 
15271547                    return  IgnoreDecision :: Ignore  { 
1528-                         reason :  format ! ( "ignored when the LLVM version is between {rest}" ) , 
1548+                         reason :  format ! ( 
1549+                             "ignored when the LLVM version is between {v_min} and {v_max}" 
1550+                         ) , 
15291551                    } ; 
15301552                } 
15311553            } 
0 commit comments