xref: /aosp_15_r20/external/toolchain-utils/bestflags/flags_util.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li# Copyright 2013 The ChromiumOS Authors
2*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be
3*760c253cSXin Li# found in the LICENSE file.
4*760c253cSXin Li"""Utility functions to explore the neighbor flags.
5*760c253cSXin Li
6*760c253cSXin LiPart of the Chrome build flags optimization.
7*760c253cSXin Li"""
8*760c253cSXin Li
9*760c253cSXin Li__author__ = "[email protected] (Yuheng Long)"
10*760c253cSXin Li
11*760c253cSXin Liimport flags
12*760c253cSXin Lifrom flags import Flag
13*760c253cSXin Li
14*760c253cSXin Li
15*760c253cSXin Lidef ClimbNext(flags_dict, climb_spec):
16*760c253cSXin Li    """Get the flags that are different from |flags_dict| by |climb_spec|.
17*760c253cSXin Li
18*760c253cSXin Li    Given a set of flags, |flags_dict|, return a new set of flags that are
19*760c253cSXin Li    adjacent along the flag spec |climb_spec|.
20*760c253cSXin Li
21*760c253cSXin Li    An example flags_dict is {foo=[1-9]:foo=5, bar=[1-5]:bar=2} and climb_spec is
22*760c253cSXin Li    bar=[1-5]. This method changes the flag that contains the spec bar=[1-5]. The
23*760c253cSXin Li    results are its neighbors dictionaries, i.e., {foo=[1-9]:foo=5,
24*760c253cSXin Li    bar=[1-5]:bar=1} and {foo=[1-9]:foo=5, bar=[1-5]:bar=3}.
25*760c253cSXin Li
26*760c253cSXin Li    Args:
27*760c253cSXin Li      flags_dict: The dictionary containing the original flags whose neighbors are
28*760c253cSXin Li        to be explored.
29*760c253cSXin Li      climb_spec: The spec in the flags_dict is to be changed. The spec is a
30*760c253cSXin Li        definition in the little language, a string with escaped sequences of the
31*760c253cSXin Li        form [<start>-<end>] where start and end is an positive integer for a
32*760c253cSXin Li        fillable value. An example of a spec is "foo[0-9]".
33*760c253cSXin Li
34*760c253cSXin Li    Returns:
35*760c253cSXin Li      List of dictionaries of neighbor flags.
36*760c253cSXin Li    """
37*760c253cSXin Li
38*760c253cSXin Li    # This method searches for a pattern [start-end] in the spec. If the spec
39*760c253cSXin Li    # contains this pattern, it is a numeric flag. Otherwise it is a boolean flag.
40*760c253cSXin Li    # For example, -finline-limit=[1-1000] is a numeric flag and -falign-jumps is
41*760c253cSXin Li    # a boolean flag.
42*760c253cSXin Li    numeric_flag_match = flags.Search(climb_spec)
43*760c253cSXin Li
44*760c253cSXin Li    # If the flags do not contain the spec.
45*760c253cSXin Li    if climb_spec not in flags_dict:
46*760c253cSXin Li        results = flags_dict.copy()
47*760c253cSXin Li
48*760c253cSXin Li        if numeric_flag_match:
49*760c253cSXin Li            # Numeric flags.
50*760c253cSXin Li            results[climb_spec] = Flag(
51*760c253cSXin Li                climb_spec, int(numeric_flag_match.group("start"))
52*760c253cSXin Li            )
53*760c253cSXin Li        else:
54*760c253cSXin Li            # Boolean flags.
55*760c253cSXin Li            results[climb_spec] = Flag(climb_spec)
56*760c253cSXin Li
57*760c253cSXin Li        return [results]
58*760c253cSXin Li
59*760c253cSXin Li    # The flags contain the spec.
60*760c253cSXin Li    if not numeric_flag_match:
61*760c253cSXin Li        # Boolean flags.
62*760c253cSXin Li        results = flags_dict.copy()
63*760c253cSXin Li
64*760c253cSXin Li        # Turn off the flag. A flag is turned off if it is not presented in the
65*760c253cSXin Li        # flags_dict.
66*760c253cSXin Li        del results[climb_spec]
67*760c253cSXin Li        return [results]
68*760c253cSXin Li
69*760c253cSXin Li    # Numeric flags.
70*760c253cSXin Li    flag = flags_dict[climb_spec]
71*760c253cSXin Li
72*760c253cSXin Li    # The value of the flag having spec.
73*760c253cSXin Li    value = flag.GetValue()
74*760c253cSXin Li    results = []
75*760c253cSXin Li
76*760c253cSXin Li    if value + 1 < int(numeric_flag_match.group("end")):
77*760c253cSXin Li        # If the value is not the end value, explore the value that is 1 larger than
78*760c253cSXin Li        # the current value.
79*760c253cSXin Li        neighbor = flags_dict.copy()
80*760c253cSXin Li        neighbor[climb_spec] = Flag(climb_spec, value + 1)
81*760c253cSXin Li        results.append(neighbor)
82*760c253cSXin Li
83*760c253cSXin Li    if value > int(numeric_flag_match.group("start")):
84*760c253cSXin Li        # If the value is not the start value, explore the value that is 1 lesser
85*760c253cSXin Li        # than the current value.
86*760c253cSXin Li        neighbor = flags_dict.copy()
87*760c253cSXin Li        neighbor[climb_spec] = Flag(climb_spec, value - 1)
88*760c253cSXin Li        results.append(neighbor)
89*760c253cSXin Li    else:
90*760c253cSXin Li        # Delete the value, i.e., turn off the flag. A flag is turned off if it is
91*760c253cSXin Li        # not presented in the flags_dict.
92*760c253cSXin Li        neighbor = flags_dict.copy()
93*760c253cSXin Li        del neighbor[climb_spec]
94*760c253cSXin Li        results.append(neighbor)
95*760c253cSXin Li
96*760c253cSXin Li    return results
97