in compiler_gym/envs/gcc/gcc.py [0:0]
def _gcc_parse_optimize(gcc: Gcc) -> List[Option]:
"""Parse the optimization help string from the GCC binary to find options."""
logger.debug("Parsing GCC optimization space")
# Call 'gcc --help=optimize -Q'
result = gcc("--help=optimize", "-Q", timeout=60)
# Split into lines. Ignore the first line.
out = result.split("\n")[1:]
# Regex patterns to match the different options
O_num_pat = re.compile("-O<number>")
O_pat = re.compile("-O([a-z]+)")
flag_align_eq_pat = re.compile("-f(align-[-a-z]+)=")
flag_pat = re.compile("-f([-a-z0-9]+)")
flag_enum_pat = re.compile("-f([-a-z0-9]+)=\\[([-A-Za-z_\\|]+)\\]")
flag_interval_pat = re.compile("-f([-a-z0-9]+)=<([0-9]+),([0-9]+)>")
flag_number_pat = re.compile("-f([-a-z0-9]+)=<number>")
# The list of options as it gets built up.
options = {}
# Add a -O value
def add_gcc_o(value: str):
# -O flag
name = "O"
# There are multiple -O flags. We add one value at a time.
opt = options[name] = options.get(name, GccOOption())
# There shouldn't be any way to overwrite this with the wrong type.
assert type(opt) == GccOOption
opt.values.append(value)
# Add a flag
def add_gcc_flag(name: str):
# Straight flag.
# If there is something else in its place already (like a flag enum),
# then we don't overwrite it. Straight flags always have the lowest
# priority
options[name] = options.get(name, GccFlagOption(name))
# Add an enum flag
def add_gcc_flag_enum(name: str, values: List[str]):
# Enum flag.
opt = options.get(name)
if opt:
# We should only ever be overwriting a straight flag
assert type(opt) == GccFlagOption
# Always overwrite
options[name] = GccFlagEnumOption(name, values)
# Add an integer flag
def add_gcc_flag_int(name: str, min: int, max: int):
# Int flag.
opt = options.get(name)
if opt:
# We should only ever be overwriting a straight flag
assert type(opt) == GccFlagOption
# Always overwrite
options[name] = GccFlagIntOption(name, min, max)
# Add an align flag
def add_gcc_flag_align(name: str):
# Align flag.
opt = options.get(name)
if opt:
# We should only ever be overwriting a straight flag
assert type(opt) == GccFlagOption
# Always overwrite
options[name] = GccFlagAlignOption(name)
# Parse a line from the help output
def parse_line(line: str):
# The first bit of the line is the specification
bits = line.split()
if not bits:
return
spec = bits[0]
# -O<number>
m = O_num_pat.fullmatch(spec)
if m:
for i in range(4):
add_gcc_o(str(i))
return
# -Ostr
m = O_pat.fullmatch(spec)
if m:
add_gcc_o(m.group(1))
return
# -falign-str=
# These have quite complicated semantics
m = flag_align_eq_pat.fullmatch(spec)
if m:
name = m.group(1)
add_gcc_flag_align(name)
return
# -fflag
m = flag_pat.fullmatch(spec)
if m:
name = m.group(1)
add_gcc_flag(name)
return
# -fflag=[a|b]
m = flag_enum_pat.fullmatch(spec)
if m:
name = m.group(1)
values = m.group(2).split("|")
add_gcc_flag_enum(name, values)
return
# -fflag=<min,max>
m = flag_interval_pat.fullmatch(spec)
if m:
name = m.group(1)
min = int(m.group(2))
max = int(m.group(3))
add_gcc_flag_int(name, min, max)
return
# -fflag=<number>
m = flag_number_pat.fullmatch(spec)
if m:
name = m.group(1)
min = 0
max = 2 << 31 - 1
add_gcc_flag_int(name, min, max)
return
logger.warning("Unknown GCC optimization flag spec, '%s'", line)
# Parse all the lines
for line in out:
parse_line(line.strip())
# Sort and return
return list(map(lambda x: x[1], sorted(list(options.items()))))