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