Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lld / test / MachO / tools / generate-cfi-funcs.py
blob4617bd578e591e5bc4e01fce9753ca7ed65324ad
1 #!/usr/bin/env python
3 """Generate skeletal functions with a variety .cfi_ directives.
4 The purpose is to produce object-file test inputs to lld with a
5 variety of compact unwind encodings.
6 """
7 from __future__ import print_function
8 import random
9 import argparse
10 import string
11 from math import factorial
12 from itertools import permutations
14 lsda_n = 0
15 lsda_odds = 0.0
16 func_size_low = 0x10
17 func_size_high = 0x100
18 saved_regs = ["%r15", "%r14", "%r13", "%r12", "%rbx"]
19 saved_regs_combined = list(list(permutations(saved_regs, i)) for i in range(0, 6))
22 def print_function(name):
23 global lsda_odds
24 have_lsda = random.random() < lsda_odds
25 frame_size = random.randint(4, 64) * 16
26 frame_offset = -random.randint(0, int(frame_size / 16 - 4)) * 16
27 global func_size_low, func_size_high
28 func_size = random.randint(func_size_low, func_size_high) * 0x10
29 func_size_high += 1
30 if func_size_high % 0x10 == 0:
31 func_size_low += 1
33 print(
34 """\
35 ### %s frame=%d lsda=%s size=%d
36 .section __TEXT,__text,regular,pure_instructions
37 .p2align 4, 0x90
38 .globl %s
39 %s:
40 .cfi_startproc"""
41 % (name, frame_size, have_lsda, func_size, name, name)
43 if have_lsda:
44 global lsda_n
45 lsda_n += 1
46 print(
47 """\
48 .cfi_personality 155, ___gxx_personality_v0
49 .cfi_lsda 16, Lexception%d"""
50 % lsda_n
52 print(
53 """\
54 pushq %%rbp
55 .cfi_def_cfa_offset %d
56 .cfi_offset %%rbp, %d
57 movq %%rsp, %%rbp
58 .cfi_def_cfa_register %%rbp"""
59 % (frame_size, frame_offset + 6 * 8)
61 print(
62 """\
63 .fill %d
64 popq %%rbp
65 retq
66 .cfi_endproc
67 """
68 % (func_size - 6)
71 if have_lsda:
72 print(
73 """\
74 .section __TEXT,__gcc_except_tab
75 .p2align 2
76 Lexception%d:
77 .space 0x10
78 """
79 % lsda_n
81 return func_size
84 def random_seed():
85 """Generate a seed that can easily be passed back in via --seed=STRING"""
86 return "".join(random.choice(string.ascii_lowercase) for i in range(10))
89 def main():
90 parser = argparse.ArgumentParser(
91 description=__doc__,
92 epilog="""\
93 Function sizes begin small then monotonically increase. The goal is
94 to produce early pages that are full and later pages that are less
95 than full, in order to test handling for both cases. Full pages
96 contain the maximum of 1021 compact unwind entries for a total page
97 size = 4 KiB.
99 Use --pages=N or --functions=N to control the size of the output.
100 Default is --pages=2, meaning produce at least two full pages of
101 compact unwind entries, plus some more. The calculation is sloppy.
102 """,
104 parser.add_argument(
105 "--seed",
106 type=str,
107 default=random_seed(),
108 help="Seed the random number generator",
110 parser.add_argument(
111 "--pages", type=int, default=2, help="Number of compact-unwind pages"
113 parser.add_argument(
114 "--functions", type=int, default=None, help="Number of functions to generate"
116 parser.add_argument(
117 "--encodings",
118 type=int,
119 default=127,
120 help="Maximum number of unique unwind encodings (default = 127)",
122 parser.add_argument(
123 "--lsda",
124 type=int,
125 default=0,
126 help="Percentage of functions with personality & LSDA (default = 10",
128 args = parser.parse_args()
129 random.seed(args.seed)
130 p2align = 14
131 global lsda_odds
132 lsda_odds = args.lsda / 100.0
134 print(
135 """\
136 ### seed=%s lsda=%f p2align=%d
137 .section __TEXT,__text,regular,pure_instructions
138 .p2align %d, 0x90
140 % (args.seed, lsda_odds, p2align, p2align)
143 size = 0
144 base = 1 << p2align
145 if args.functions:
146 for n in range(args.functions):
147 size += print_function("x%08x" % (size + base))
148 else:
149 while size < (args.pages << 24):
150 size += print_function("x%08x" % (size + base))
152 print(
153 """\
154 .section __TEXT,__text,regular,pure_instructions
155 .globl _main
156 .p2align 4, 0x90
157 _main:
158 retq
160 .p2align 4, 0x90
161 ___gxx_personality_v0:
162 retq
167 if __name__ == "__main__":
168 main()