xref: /aosp_15_r20/external/google-benchmark/tools/strip_asm.py (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
1*dbb99499SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*dbb99499SAndroid Build Coastguard Worker
3*dbb99499SAndroid Build Coastguard Worker"""
4*dbb99499SAndroid Build Coastguard Workerstrip_asm.py - Cleanup ASM output for the specified file
5*dbb99499SAndroid Build Coastguard Worker"""
6*dbb99499SAndroid Build Coastguard Worker
7*dbb99499SAndroid Build Coastguard Workerimport os
8*dbb99499SAndroid Build Coastguard Workerimport re
9*dbb99499SAndroid Build Coastguard Workerimport sys
10*dbb99499SAndroid Build Coastguard Workerfrom argparse import ArgumentParser
11*dbb99499SAndroid Build Coastguard Worker
12*dbb99499SAndroid Build Coastguard Worker
13*dbb99499SAndroid Build Coastguard Workerdef find_used_labels(asm):
14*dbb99499SAndroid Build Coastguard Worker    found = set()
15*dbb99499SAndroid Build Coastguard Worker    label_re = re.compile(r"\s*j[a-z]+\s+\.L([a-zA-Z0-9][a-zA-Z0-9_]*)")
16*dbb99499SAndroid Build Coastguard Worker    for line in asm.splitlines():
17*dbb99499SAndroid Build Coastguard Worker        m = label_re.match(line)
18*dbb99499SAndroid Build Coastguard Worker        if m:
19*dbb99499SAndroid Build Coastguard Worker            found.add(".L%s" % m.group(1))
20*dbb99499SAndroid Build Coastguard Worker    return found
21*dbb99499SAndroid Build Coastguard Worker
22*dbb99499SAndroid Build Coastguard Worker
23*dbb99499SAndroid Build Coastguard Workerdef normalize_labels(asm):
24*dbb99499SAndroid Build Coastguard Worker    decls = set()
25*dbb99499SAndroid Build Coastguard Worker    label_decl = re.compile("^[.]{0,1}L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
26*dbb99499SAndroid Build Coastguard Worker    for line in asm.splitlines():
27*dbb99499SAndroid Build Coastguard Worker        m = label_decl.match(line)
28*dbb99499SAndroid Build Coastguard Worker        if m:
29*dbb99499SAndroid Build Coastguard Worker            decls.add(m.group(0))
30*dbb99499SAndroid Build Coastguard Worker    if len(decls) == 0:
31*dbb99499SAndroid Build Coastguard Worker        return asm
32*dbb99499SAndroid Build Coastguard Worker    needs_dot = next(iter(decls))[0] != "."
33*dbb99499SAndroid Build Coastguard Worker    if not needs_dot:
34*dbb99499SAndroid Build Coastguard Worker        return asm
35*dbb99499SAndroid Build Coastguard Worker    for ld in decls:
36*dbb99499SAndroid Build Coastguard Worker        asm = re.sub(r"(^|\s+)" + ld + r"(?=:|\s)", "\\1." + ld, asm)
37*dbb99499SAndroid Build Coastguard Worker    return asm
38*dbb99499SAndroid Build Coastguard Worker
39*dbb99499SAndroid Build Coastguard Worker
40*dbb99499SAndroid Build Coastguard Workerdef transform_labels(asm):
41*dbb99499SAndroid Build Coastguard Worker    asm = normalize_labels(asm)
42*dbb99499SAndroid Build Coastguard Worker    used_decls = find_used_labels(asm)
43*dbb99499SAndroid Build Coastguard Worker    new_asm = ""
44*dbb99499SAndroid Build Coastguard Worker    label_decl = re.compile(r"^\.L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
45*dbb99499SAndroid Build Coastguard Worker    for line in asm.splitlines():
46*dbb99499SAndroid Build Coastguard Worker        m = label_decl.match(line)
47*dbb99499SAndroid Build Coastguard Worker        if not m or m.group(0) in used_decls:
48*dbb99499SAndroid Build Coastguard Worker            new_asm += line
49*dbb99499SAndroid Build Coastguard Worker            new_asm += "\n"
50*dbb99499SAndroid Build Coastguard Worker    return new_asm
51*dbb99499SAndroid Build Coastguard Worker
52*dbb99499SAndroid Build Coastguard Worker
53*dbb99499SAndroid Build Coastguard Workerdef is_identifier(tk):
54*dbb99499SAndroid Build Coastguard Worker    if len(tk) == 0:
55*dbb99499SAndroid Build Coastguard Worker        return False
56*dbb99499SAndroid Build Coastguard Worker    first = tk[0]
57*dbb99499SAndroid Build Coastguard Worker    if not first.isalpha() and first != "_":
58*dbb99499SAndroid Build Coastguard Worker        return False
59*dbb99499SAndroid Build Coastguard Worker    for i in range(1, len(tk)):
60*dbb99499SAndroid Build Coastguard Worker        c = tk[i]
61*dbb99499SAndroid Build Coastguard Worker        if not c.isalnum() and c != "_":
62*dbb99499SAndroid Build Coastguard Worker            return False
63*dbb99499SAndroid Build Coastguard Worker    return True
64*dbb99499SAndroid Build Coastguard Worker
65*dbb99499SAndroid Build Coastguard Worker
66*dbb99499SAndroid Build Coastguard Workerdef process_identifiers(line):
67*dbb99499SAndroid Build Coastguard Worker    """
68*dbb99499SAndroid Build Coastguard Worker    process_identifiers - process all identifiers and modify them to have
69*dbb99499SAndroid Build Coastguard Worker    consistent names across all platforms; specifically across ELF and MachO.
70*dbb99499SAndroid Build Coastguard Worker    For example, MachO inserts an additional understore at the beginning of
71*dbb99499SAndroid Build Coastguard Worker    names. This function removes that.
72*dbb99499SAndroid Build Coastguard Worker    """
73*dbb99499SAndroid Build Coastguard Worker    parts = re.split(r"([a-zA-Z0-9_]+)", line)
74*dbb99499SAndroid Build Coastguard Worker    new_line = ""
75*dbb99499SAndroid Build Coastguard Worker    for tk in parts:
76*dbb99499SAndroid Build Coastguard Worker        if is_identifier(tk):
77*dbb99499SAndroid Build Coastguard Worker            if tk.startswith("__Z"):
78*dbb99499SAndroid Build Coastguard Worker                tk = tk[1:]
79*dbb99499SAndroid Build Coastguard Worker            elif (
80*dbb99499SAndroid Build Coastguard Worker                tk.startswith("_")
81*dbb99499SAndroid Build Coastguard Worker                and len(tk) > 1
82*dbb99499SAndroid Build Coastguard Worker                and tk[1].isalpha()
83*dbb99499SAndroid Build Coastguard Worker                and tk[1] != "Z"
84*dbb99499SAndroid Build Coastguard Worker            ):
85*dbb99499SAndroid Build Coastguard Worker                tk = tk[1:]
86*dbb99499SAndroid Build Coastguard Worker        new_line += tk
87*dbb99499SAndroid Build Coastguard Worker    return new_line
88*dbb99499SAndroid Build Coastguard Worker
89*dbb99499SAndroid Build Coastguard Worker
90*dbb99499SAndroid Build Coastguard Workerdef process_asm(asm):
91*dbb99499SAndroid Build Coastguard Worker    """
92*dbb99499SAndroid Build Coastguard Worker    Strip the ASM of unwanted directives and lines
93*dbb99499SAndroid Build Coastguard Worker    """
94*dbb99499SAndroid Build Coastguard Worker    new_contents = ""
95*dbb99499SAndroid Build Coastguard Worker    asm = transform_labels(asm)
96*dbb99499SAndroid Build Coastguard Worker
97*dbb99499SAndroid Build Coastguard Worker    # TODO: Add more things we want to remove
98*dbb99499SAndroid Build Coastguard Worker    discard_regexes = [
99*dbb99499SAndroid Build Coastguard Worker        re.compile(r"\s+\..*$"),  # directive
100*dbb99499SAndroid Build Coastguard Worker        re.compile(r"\s*#(NO_APP|APP)$"),  # inline ASM
101*dbb99499SAndroid Build Coastguard Worker        re.compile(r"\s*#.*$"),  # comment line
102*dbb99499SAndroid Build Coastguard Worker        re.compile(
103*dbb99499SAndroid Build Coastguard Worker            r"\s*\.globa?l\s*([.a-zA-Z_][a-zA-Z0-9$_.]*)"
104*dbb99499SAndroid Build Coastguard Worker        ),  # global directive
105*dbb99499SAndroid Build Coastguard Worker        re.compile(
106*dbb99499SAndroid Build Coastguard Worker            r"\s*\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)"
107*dbb99499SAndroid Build Coastguard Worker        ),
108*dbb99499SAndroid Build Coastguard Worker    ]
109*dbb99499SAndroid Build Coastguard Worker    keep_regexes: list[re.Pattern] = []
110*dbb99499SAndroid Build Coastguard Worker    fn_label_def = re.compile("^[a-zA-Z_][a-zA-Z0-9_.]*:")
111*dbb99499SAndroid Build Coastguard Worker    for line in asm.splitlines():
112*dbb99499SAndroid Build Coastguard Worker        # Remove Mach-O attribute
113*dbb99499SAndroid Build Coastguard Worker        line = line.replace("@GOTPCREL", "")
114*dbb99499SAndroid Build Coastguard Worker        add_line = True
115*dbb99499SAndroid Build Coastguard Worker        for reg in discard_regexes:
116*dbb99499SAndroid Build Coastguard Worker            if reg.match(line) is not None:
117*dbb99499SAndroid Build Coastguard Worker                add_line = False
118*dbb99499SAndroid Build Coastguard Worker                break
119*dbb99499SAndroid Build Coastguard Worker        for reg in keep_regexes:
120*dbb99499SAndroid Build Coastguard Worker            if reg.match(line) is not None:
121*dbb99499SAndroid Build Coastguard Worker                add_line = True
122*dbb99499SAndroid Build Coastguard Worker                break
123*dbb99499SAndroid Build Coastguard Worker        if add_line:
124*dbb99499SAndroid Build Coastguard Worker            if fn_label_def.match(line) and len(new_contents) != 0:
125*dbb99499SAndroid Build Coastguard Worker                new_contents += "\n"
126*dbb99499SAndroid Build Coastguard Worker            line = process_identifiers(line)
127*dbb99499SAndroid Build Coastguard Worker            new_contents += line
128*dbb99499SAndroid Build Coastguard Worker            new_contents += "\n"
129*dbb99499SAndroid Build Coastguard Worker    return new_contents
130*dbb99499SAndroid Build Coastguard Worker
131*dbb99499SAndroid Build Coastguard Worker
132*dbb99499SAndroid Build Coastguard Workerdef main():
133*dbb99499SAndroid Build Coastguard Worker    parser = ArgumentParser(description="generate a stripped assembly file")
134*dbb99499SAndroid Build Coastguard Worker    parser.add_argument(
135*dbb99499SAndroid Build Coastguard Worker        "input",
136*dbb99499SAndroid Build Coastguard Worker        metavar="input",
137*dbb99499SAndroid Build Coastguard Worker        type=str,
138*dbb99499SAndroid Build Coastguard Worker        nargs=1,
139*dbb99499SAndroid Build Coastguard Worker        help="An input assembly file",
140*dbb99499SAndroid Build Coastguard Worker    )
141*dbb99499SAndroid Build Coastguard Worker    parser.add_argument(
142*dbb99499SAndroid Build Coastguard Worker        "out", metavar="output", type=str, nargs=1, help="The output file"
143*dbb99499SAndroid Build Coastguard Worker    )
144*dbb99499SAndroid Build Coastguard Worker    args, unknown_args = parser.parse_known_args()
145*dbb99499SAndroid Build Coastguard Worker    input = args.input[0]
146*dbb99499SAndroid Build Coastguard Worker    output = args.out[0]
147*dbb99499SAndroid Build Coastguard Worker    if not os.path.isfile(input):
148*dbb99499SAndroid Build Coastguard Worker        print("ERROR: input file '%s' does not exist" % input)
149*dbb99499SAndroid Build Coastguard Worker        sys.exit(1)
150*dbb99499SAndroid Build Coastguard Worker
151*dbb99499SAndroid Build Coastguard Worker    with open(input, "r") as f:
152*dbb99499SAndroid Build Coastguard Worker        contents = f.read()
153*dbb99499SAndroid Build Coastguard Worker    new_contents = process_asm(contents)
154*dbb99499SAndroid Build Coastguard Worker    with open(output, "w") as f:
155*dbb99499SAndroid Build Coastguard Worker        f.write(new_contents)
156*dbb99499SAndroid Build Coastguard Worker
157*dbb99499SAndroid Build Coastguard Worker
158*dbb99499SAndroid Build Coastguard Workerif __name__ == "__main__":
159*dbb99499SAndroid Build Coastguard Worker    main()
160*dbb99499SAndroid Build Coastguard Worker
161*dbb99499SAndroid Build Coastguard Worker# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
162*dbb99499SAndroid Build Coastguard Worker# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
163*dbb99499SAndroid Build Coastguard Worker# kate: indent-mode python; remove-trailing-spaces modified;
164