blob: ee426e49b2f7457b311e79fbdb6b7b75159f0b22 [file] [log] [blame]
Mike Stump46ae64f2010-01-07 18:58:28 +00001#include <stdio.h>
2#include <stdlib.h>
3
4#define N_FIELDS 7
5#define N_FUNCS 128
6#define FUNCSPACING 10
7#define N_STRUCTS 300 /* 1280 */
8// FIXME: Need final overrider logic for 3 or more if we turn on virtual base
9// class dups
10#define N_BASES 30 /* 30 */
11
12const char *simple_types[] = { "bool", "char", "short", "int", "float",
13 "double", "long double", "wchar_t", "void *",
14 "char *"
15};
16
17void gl(const char *c) {
18 printf("%s\n", c);
19}
20
21void g(const char *c) {
22 printf("%s", c);
23}
24
25void g(int i) {
26 printf("%d", i);
27}
28
29int vfn = 0;
30char base_present[N_STRUCTS][N_STRUCTS];
31
32bool is_ambiguous(int s, int base) {
33 for (int i = 0; i < N_STRUCTS; ++i) {
34 if ((base_present[base][i] & base_present[s][i])
35 // FIXME: todo this, we need final overrider additions
36 /*== 1 */)
37 return true;
38 }
39 return false;
40}
41
42void add_bases(int s, int base) {
43 for (int i = 0; i < N_STRUCTS; ++i)
44 base_present[s][i] |= base_present[base][i];
45}
46
47void gs(int s) {
48 bool polymorphic = false;
49
50 static int bases[N_BASES];
51 int i_bases = random() % (N_BASES*2);
52 if (i_bases >= N_BASES)
53 // PARAM: 1/2 of all clases should have no bases
54 i_bases = 0;
55 int n_bases = 0;
56 bool first_base = true;
57
58 // PARAM: 3/4 of all should be class, the rest are structs
59 if (random() % 4 == 0)
60 g("struct s");
61 else
62 g("class s");
63 g(s);
64 int old_base = -1;
65 if (s == 0)
66 i_bases = 0;
67 while (i_bases) {
68 --i_bases;
69 int base = random() % s;
70 if (!base_present[s][base]) {
71 if (is_ambiguous(s, base))
72 continue;
73 if (first_base) {
74 first_base = false;
75 g(": ");
76 } else
77 g(", ");
78 int base_type = 1;
79 if (random()%8 == 0) {
80 // PARAM: 1/8th the bases are virtual
81 g("virtual ");
82 polymorphic = true;
83 base_type = 3;
84 }
85 switch (random()%8) {
86 case 0:
87 case 1:
88 case 2:
89 case 3:
90 break;
91 case 4:
92 case 5:
93 g("public "); break;
94 case 6:
95 g("private "); break;
96 case 7:
97 g("protected "); break;
98 }
99 g("s");
100 add_bases(s, base);
101 bases[n_bases] = base;
102 base_present[s][base] = base_type;
103 ++n_bases;
104 g(base);
105 old_base = base;
106 }
107 }
108 gl(" {");
109
110 /* Fields */
111 int n_fields = random() % (N_FIELDS*4);
112 // PARAM: 3/4 of all structs should have no members
113 if (n_fields >= N_FIELDS)
114 n_fields = 0;
115 for (int i = 0; i < n_fields; ++i) {
116 int t = random() % (sizeof(simple_types) / sizeof(simple_types[0]));
117 g(" "); g(simple_types[t]); g(" field"); g(i); gl(";");
118 }
119
120 /* Virtual functions */
121 static int funcs[N_FUNCS];
122 int n_funcs = random() % N_FUNCS;
123 int old_func = -1;
124 for (int i = 0; i < n_funcs; ++i) {
125 int fn = old_func + random() % FUNCSPACING + 1;
126 funcs[i] = fn;
Mike Stump365d6382010-01-07 19:39:43 +0000127 g(" virtual void fun"); g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++vfn); gl("); }");
Mike Stump46ae64f2010-01-07 18:58:28 +0000128 old_func = fn;
129 }
130
131 gl("public:");
132 gl(" void calc(char *t) {");
133
134 // mix in the type number
Mike Stump365d6382010-01-07 19:39:43 +0000135 g(" mix(\"type num\", "); g(s); gl(");");
Mike Stump46ae64f2010-01-07 18:58:28 +0000136 // mix in the size
Mike Stump365d6382010-01-07 19:39:43 +0000137 g(" mix(\"type size\", sizeof (s"); g(s); gl("));");
Mike Stump46ae64f2010-01-07 18:58:28 +0000138 // mix in the this offset
Mike Stump365d6382010-01-07 19:39:43 +0000139 gl(" mix(\"subobject offset\", (char *)this - t);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000140 if (n_funcs)
141 polymorphic = true;
142 if (polymorphic) {
143 // mix in offset to the complete object under construction
Mike Stump365d6382010-01-07 19:39:43 +0000144 gl(" mix(\"real top v current top\", t - (char *)dynamic_cast<void*>(this));");
Mike Stump46ae64f2010-01-07 18:58:28 +0000145 }
146
147 /* check base layout and overrides */
148 for (int i = 0; i < n_bases; ++i) {
149 g(" calc_s"); g(bases[i]); gl("(t);");
150 }
151
152 if (polymorphic) {
153 /* check dynamic_cast to each direct base */
154 for (int i = 0; i < n_bases; ++i) {
155 g(" if ((char *)dynamic_cast<s"); g(bases[i]); gl("*>(this))");
Mike Stump365d6382010-01-07 19:39:43 +0000156 g(" mix(\"base dyn cast\", t - (char *)dynamic_cast<s"); g(bases[i]); gl("*>(this));");
157 gl(" else mix(\"no dyncast\", 666);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000158 }
159 }
160
161 /* check field layout */
162 for (int i = 0; i < n_fields; ++i) {
Mike Stump365d6382010-01-07 19:39:43 +0000163 g(" mix(\"field offset\", (char *)&field"); g(i); gl(" - (char *)this);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000164 }
165 if (n_fields == 0)
Mike Stump365d6382010-01-07 19:39:43 +0000166 gl(" mix(\"no fields\", 42);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000167
168 /* check functions */
169 for (int i = 0; i < n_funcs; ++i) {
170 g(" fun"); g(funcs[i]); gl("(t);");
171 }
172 if (n_funcs == 0)
Mike Stump365d6382010-01-07 19:39:43 +0000173 gl(" mix(\"no funcs\", 13);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000174
175 gl(" }");
176
177 // default ctor
178 g(" s"); g(s); g("() ");
179 first_base = true;
180 for (int i = 0; i < n_bases; ++i) {
181 if (first_base) {
182 g(": ");
183 first_base = false;
184 } else
185 g(", ");
186 g("s"); g(bases[i]); g("((char *)this)");
187 }
188 gl(" { calc((char *)this); }");
189 g(" ~s"); g(s); gl("() { calc((char *)this); }");
190
191 // ctor with this to the complete object
192 g(" s"); g(s); gl("(char *t) { calc(t); }");
193 g(" void calc_s"); g(s); gl("(char *t) { calc(t); }");
194 g("} a"); g(s); gl(";");
195}
196
197main(int argc, char **argv) {
198 unsigned seed = 0;
199 char state[16];
200 if (argc > 1)
201 seed = atol(argv[1]);
202
203 initstate(seed, state, sizeof(state));
204 gl("extern \"C\" int printf(const char *...);");
205 gl("");
206 gl("long long sum;");
Mike Stump365d6382010-01-07 19:39:43 +0000207 gl("void mix(const char *desc, long long i) {");
Mike Stump46ae64f2010-01-07 18:58:28 +0000208 // If this ever becomes too slow, we can remove this after we improve the
209 // mixing function
Mike Stump365d6382010-01-07 19:39:43 +0000210 gl(" printf(\"%s: %lld\\n\", desc, i);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000211 gl(" sum += ((sum ^ i) << 3) + (sum<<1) - i;");
212 gl("}");
Mike Stump46ae64f2010-01-07 18:58:28 +0000213 gl("");
214 // PARAM: Randomly size testcases or large testcases?
215 int n_structs = /* random() % */ N_STRUCTS;
216 for (int i = 0; i < n_structs; ++i)
217 gs(i);
218 gl("int main() {");
219 gl(" printf(\"%llx\\n\", sum);");
220 gl("}");
221 return 0;
222}