@@ -71,6 +71,7 @@ def cfg_parse(expr):
7171 frames = [{"fn" : "__ROOT__" , "args" : []}]
7272 pending_ident = None
7373 pending_eq_key = None
74+ uses_feature_cfg = False
7475
7576 for t in tokens :
7677 kind = t ["t" ]
@@ -90,7 +91,7 @@ def cfg_parse(expr):
9091 if not pending_eq_key :
9192 fail ("cfg parse error: string literal not expected here." )
9293 if pending_eq_key == "feature" :
93- fail ( "Feature evaluation in cfg is unsupported!" )
94+ uses_feature_cfg = True
9495 frames [- 1 ]["args" ].append ({
9596 "kind" : "eq" ,
9697 "key" : pending_eq_key ,
@@ -138,7 +139,7 @@ def cfg_parse(expr):
138139 fail ("cfg parse error: empty expression." )
139140 fail ("cfg parse error: multiple top-level expressions; wrap with all(...)/any(...)." )
140141
141- return root_args [0 ]
142+ return root_args [0 ], uses_feature_cfg
142143
143144############################################
144145# Triple → cfg attribute derivation
@@ -192,7 +193,18 @@ def _abi_from_env(env):
192193 return abi_piece
193194 return ""
194195
195- def triple_to_cfg_attrs (triple , features , target_features ):
196+ def _target_has_feature (ctx , feature ):
197+ # x86_64 baseline implies SSE2.
198+ if feature == "sse2" :
199+ return ctx ["target_arch" ] == "x86_64"
200+
201+ # AArch64 baseline implies NEON.
202+ if feature == "neon" :
203+ return ctx ["target_arch" ] == "aarch64"
204+
205+ return False
206+
207+ def triple_to_cfg_attrs (triple ):
196208 parts = triple .split ("-" )
197209 arch_part = _get (parts , 0 , "" )
198210 vendor_part = _get (parts , 1 , "unknown" )
@@ -221,22 +233,17 @@ def triple_to_cfg_attrs(triple, features, target_features):
221233 "false" : False ,
222234 "unix" : fam == "unix" ,
223235 "windows" : fam == "windows" ,
224-
225- # feature sets
226- #"__features__": dict(((f, True) for f in features)),
227- #"__tfeatures__": dict(((tf, True) for tf in target_features)),
228236 }
229237
230238############################################
231239# Evaluator (non-recursive; explicit stack)
232240############################################
233241
234- def _eval_eq (ctx , key , value ):
242+ def _eval_eq (ctx , key , value , features ):
235243 if key == "feature" :
236- return ctx . get ( "__features__" , {}). get ( value , False )
244+ return value in features
237245 if key == "target_feature" :
238- return ctx .get ("__tfeatures__" ,
239- {}).get (value , False )
246+ return _target_has_feature (ctx , value )
240247 known = [
241248 "target_os" ,"target_family" ,"target_arch" ,"target_env" ,
242249 "target_vendor" ,"target_endian" ,"target_pointer_width" ,"target_abi" ,
@@ -251,7 +258,7 @@ def _eval_pred(ctx, name):
251258 return ctx .get (name , False )
252259
253260
254- def _cfg_eval (ast , ctx ):
261+ def _cfg_eval (ast , ctx , features = [] ):
255262 todo = [{"op" : "VISIT" , "node" : ast }]
256263 results = []
257264 for _ in range (200000 ):
@@ -265,7 +272,7 @@ def _cfg_eval(ast, ctx):
265272 if kind == "pred" :
266273 results .append (_eval_pred (ctx , node ["name" ]))
267274 elif kind == "eq" :
268- results .append (_eval_eq (ctx , node ["key" ], node ["value" ]))
275+ results .append (_eval_eq (ctx , node ["key" ], node ["value" ], features ))
269276 else :
270277 children = node ["args" ]
271278 n = len (children )
@@ -299,20 +306,28 @@ def _cfg_eval(ast, ctx):
299306 fail ("cfg eval error: unexpected result stack size." )
300307 return results [0 ]
301308
302- def cfg_matches (expr , triple , features = [], target_features = [] ):
303- ast = cfg_parse (expr )
304- ctx = triple_to_cfg_attrs (triple , features , target_features )
305- return _cfg_eval (ast , ctx )
309+ def cfg_matches (expr , triple , features = []):
310+ ast , _ = cfg_parse (expr )
311+ ctx = triple_to_cfg_attrs (triple )
312+ return _cfg_eval (ast , ctx , features )
306313
307- def cfg_matches_expr_for_triples (expr , triples , features = [], target_features = [] ):
308- cfg_attrs = [triple_to_cfg_attrs (triple , features , target_features ) for triple in triples ]
309- return cfg_matches_expr_for_cfg_attrs (expr , cfg_attrs , features , target_features )
314+ def cfg_matches_expr_for_triples (expr , triples , features = []):
315+ cfg_attrs = [triple_to_cfg_attrs (triple ) for triple in triples ]
316+ return cfg_matches_expr_for_cfg_attrs (expr , cfg_attrs , features )
310317
311- def cfg_matches_expr_for_cfg_attrs (expr , cfg_attrs , features = [], target_features = [] ):
318+ def cfg_matches_expr_for_cfg_attrs (expr , cfg_attrs , features = []):
312319 if expr .startswith ("cfg(" ):
313- return cfg_matches_ast_for_triples (cfg_parse (expr ), cfg_attrs )
314- # Cargo target table keys that aren't cfg(...) are literal triples.
315- return [cfg_attr ["_triple" ] for cfg_attr in cfg_attrs if cfg_attr ["_triple" ] == expr ]
316-
317- def cfg_matches_ast_for_triples (ast , cfg_attrs ):
318- return [cfg_attr ["_triple" ] for cfg_attr in cfg_attrs if _cfg_eval (ast , cfg_attr )]
320+ ast , uses_feature_cfg = cfg_parse (expr )
321+ return struct (
322+ matches = cfg_matches_ast_for_triples (ast , cfg_attrs , features ),
323+ uses_feature_cfg = uses_feature_cfg ,
324+ )
325+ else :
326+ # Cargo target table keys that aren't cfg(...) are literal triples.
327+ return struct (
328+ matches = [cfg_attr ["_triple" ] for cfg_attr in cfg_attrs if cfg_attr ["_triple" ] == expr ],
329+ uses_feature_cfg = False ,
330+ )
331+
332+ def cfg_matches_ast_for_triples (ast , cfg_attrs , features = []):
333+ return [cfg_attr ["_triple" ] for cfg_attr in cfg_attrs if _cfg_eval (ast , cfg_attr , features )]
0 commit comments