gen.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define N_FIELDS 7
  4. #define N_FUNCS 128
  5. #define FUNCSPACING 20
  6. #define N_STRUCTS 180 /* 1280 */
  7. #define N_BASES 6
  8. #define COVARIANT 0
  9. const char *simple_types[] = { "bool", "char", "short", "int", "float",
  10. "double", "long double", "wchar_t", "void *",
  11. "char *"
  12. };
  13. void gl(const char *c) {
  14. printf("%s\n", c);
  15. }
  16. void g(const char *c) {
  17. printf("%s", c);
  18. }
  19. void g(int i) {
  20. printf("%d", i);
  21. }
  22. int uuid = 0;
  23. char base_present[N_STRUCTS][N_STRUCTS];
  24. // The return type for each function when doing covariant testcase generation.
  25. short ret_types[N_STRUCTS][N_FUNCS*FUNCSPACING];
  26. bool is_ambiguous(int s, int base) {
  27. for (int i = 0; i < N_STRUCTS; ++i) {
  28. if ((base_present[base][i] & base_present[s][i]) == 1)
  29. return true;
  30. }
  31. return false;
  32. }
  33. void add_bases(int s, int base) {
  34. for (int i = 0; i < N_STRUCTS; ++i)
  35. base_present[s][i] |= base_present[base][i];
  36. if (!COVARIANT)
  37. return;
  38. for (int i = 0; i < N_FUNCS*FUNCSPACING; ++i) {
  39. if (!ret_types[base][i])
  40. continue;
  41. if (!ret_types[s][i]) {
  42. ret_types[s][i] = ret_types[base][i];
  43. continue;
  44. }
  45. if (base_present[ret_types[base][i]][ret_types[s][i]])
  46. // If the return type of the function from this base dominates
  47. ret_types[s][i] = ret_types[base][i];
  48. if (base_present[ret_types[s][i]][ret_types[base][i]])
  49. // If a previous base dominates
  50. continue;
  51. // If neither dominates, we'll use this class.
  52. ret_types[s][i] = s;
  53. }
  54. }
  55. // This contains the class that has the final override for
  56. // each class, for each function.
  57. short final_override[N_STRUCTS][N_FUNCS*FUNCSPACING];
  58. void gs(int s) {
  59. bool polymorphic = false;
  60. static int bases[N_BASES];
  61. int i_bases = random() % (N_BASES*2);
  62. if (i_bases >= N_BASES)
  63. // PARAM: 1/2 of all clases should have no bases
  64. i_bases = 0;
  65. int n_bases = 0;
  66. bool first_base = true;
  67. // PARAM: 3/4 of all should be class, the rest are structs
  68. if (random() % 4 == 0)
  69. g("struct s");
  70. else
  71. g("class s");
  72. g(s);
  73. int old_base = -1;
  74. if (s == 0 || s == 1)
  75. i_bases = 0;
  76. while (i_bases) {
  77. --i_bases;
  78. int base = random() % (s-1) + 1;
  79. if (!base_present[s][base]) {
  80. if (is_ambiguous(s, base))
  81. continue;
  82. if (first_base) {
  83. first_base = false;
  84. g(": ");
  85. } else
  86. g(", ");
  87. int base_type = 1;
  88. if (random()%8 == 0) {
  89. // PARAM: 1/8th the bases are virtual
  90. g("virtual ");
  91. // We have a vtable and rtti, but technically we're not polymorphic
  92. // polymorphic = true;
  93. base_type = 3;
  94. }
  95. // PARAM: 1/4 are public, 1/8 are privare, 1/8 are protected, the reset, default
  96. int base_protection = 0;
  97. if (!COVARIANT)
  98. base_protection = random()%8;
  99. switch (base_protection) {
  100. case 0:
  101. case 1:
  102. g("public "); break;
  103. case 2:
  104. case 3:
  105. case 4:
  106. case 5:
  107. break;
  108. case 6:
  109. g("private "); break;
  110. case 7:
  111. g("protected "); break;
  112. }
  113. g("s");
  114. add_bases(s, base);
  115. bases[n_bases] = base;
  116. base_present[s][base] = base_type;
  117. ++n_bases;
  118. g(base);
  119. old_base = base;
  120. }
  121. }
  122. gl(" {");
  123. /* Fields */
  124. int n_fields = N_FIELDS == 0 ? 0 : random() % (N_FIELDS*4);
  125. // PARAM: 3/4 of all structs should have no members
  126. if (n_fields >= N_FIELDS)
  127. n_fields = 0;
  128. for (int i = 0; i < n_fields; ++i) {
  129. int t = random() % (sizeof(simple_types) / sizeof(simple_types[0]));
  130. g(" "); g(simple_types[t]); g(" field"); g(i); gl(";");
  131. }
  132. /* Virtual functions */
  133. static int funcs[N_FUNCS*FUNCSPACING];
  134. // PARAM: 1/2 of all structs should have no virtual functions
  135. int n_funcs = random() % (N_FUNCS*2);
  136. if (n_funcs > N_FUNCS)
  137. n_funcs = 0;
  138. int old_func = -1;
  139. for (int i = 0; i < n_funcs; ++i) {
  140. int fn = old_func + random() % FUNCSPACING + 1;
  141. funcs[i] = fn;
  142. int ret_type = 0;
  143. if (COVARIANT) {
  144. ret_type = random() % s + 1;
  145. if (!base_present[s][ret_type]
  146. || !base_present[ret_type][ret_types[s][fn]])
  147. if (ret_types[s][fn]) {
  148. printf(" // Found one for s%d for s%d* fun%d.\n", s,
  149. ret_types[s][fn], fn);
  150. ret_type = ret_types[s][fn];
  151. } else
  152. ret_type = s;
  153. else
  154. printf(" // Wow found one for s%d for fun%d.\n", s, fn);
  155. ret_types[s][fn] = ret_type;
  156. }
  157. if (ret_type) {
  158. g(" virtual s"); g(ret_type); g("* fun");
  159. } else
  160. g(" virtual void fun");
  161. g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++uuid);
  162. if (ret_type)
  163. gl("); return 0; }");
  164. else
  165. gl("); }");
  166. final_override[s][fn] = s;
  167. old_func = fn;
  168. }
  169. // Add required overriders for correctness
  170. for (int i = 0; i < n_bases; ++i) {
  171. // For each base
  172. int base = bases[i];
  173. for (int fn = 0; fn < N_FUNCS*FUNCSPACING; ++fn) {
  174. // For each possible function
  175. int new_base = final_override[base][fn];
  176. if (new_base == 0)
  177. // If the base didn't have a final overrider, skip
  178. continue;
  179. int prev_base = final_override[s][fn];
  180. if (prev_base == s)
  181. // Skip functions defined in this class
  182. continue;
  183. // If we don't want to change the info, skip
  184. if (prev_base == new_base)
  185. continue;
  186. if (prev_base == 0) {
  187. // record the final override
  188. final_override[s][fn] = new_base;
  189. continue;
  190. }
  191. if (base_present[prev_base][new_base]) {
  192. // The previous base dominates the new base, no update necessary
  193. printf(" // No override for fun%d in s%d as s%d dominates s%d.\n",
  194. fn, s, prev_base, new_base);
  195. continue;
  196. }
  197. if (base_present[new_base][prev_base]) {
  198. // The new base dominates the old base, no override necessary
  199. printf(" // No override for fun%d in s%d as s%d dominates s%d.\n",
  200. fn, s, new_base, prev_base);
  201. // record the final override
  202. final_override[s][fn] = new_base;
  203. continue;
  204. }
  205. printf(" // Found we needed override for fun%d in s%d.\n", fn, s);
  206. // record the final override
  207. funcs[n_funcs++] = fn;
  208. if (n_funcs == (N_FUNCS*FUNCSPACING-1))
  209. abort();
  210. int ret_type = 0;
  211. if (COVARIANT) {
  212. if (!ret_types[s][fn]) {
  213. ret_types[s][fn] = ret_type = s;
  214. } else {
  215. ret_type = ret_types[s][fn];
  216. if (ret_type != s)
  217. printf(" // Calculated return type in s%d as s%d* fun%d.\n",
  218. s, ret_type, fn);
  219. }
  220. }
  221. if (ret_type) {
  222. g(" virtual s"); g(ret_type); g("* fun");
  223. } else
  224. g(" virtual void fun");
  225. g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++uuid);
  226. if (ret_type)
  227. gl("); return 0; }");
  228. else
  229. gl("); }");
  230. final_override[s][fn] = s;
  231. }
  232. }
  233. gl("public:");
  234. gl(" void calc(char *t) {");
  235. // mix in the type number
  236. g(" mix(\"type num\", "); g(s); gl(");");
  237. // mix in the size
  238. g(" mix(\"type size\", sizeof (s"); g(s); gl("));");
  239. // mix in the this offset
  240. gl(" mix(\"subobject offset\", (char *)this - t);");
  241. if (n_funcs)
  242. polymorphic = true;
  243. if (polymorphic) {
  244. // mix in offset to the complete object under construction
  245. gl(" mix(\"real top v current top\", t - (char *)dynamic_cast<void*>(this));");
  246. }
  247. /* check base layout and overrides */
  248. for (int i = 0; i < n_bases; ++i) {
  249. g(" calc_s"); g(bases[i]); gl("(t);");
  250. }
  251. if (polymorphic) {
  252. /* check dynamic_cast to each direct base */
  253. for (int i = 0; i < n_bases; ++i) {
  254. g(" if ((char *)dynamic_cast<s"); g(bases[i]); gl("*>(this))");
  255. g(" mix(\"base dyn cast\", t - (char *)dynamic_cast<s"); g(bases[i]); gl("*>(this));");
  256. g(" else mix(\"no dyncast\", "); g(++uuid); gl(");");
  257. }
  258. }
  259. /* check field layout */
  260. for (int i = 0; i < n_fields; ++i) {
  261. g(" mix(\"field offset\", (char *)&field"); g(i); gl(" - (char *)this);");
  262. }
  263. if (n_fields == 0) {
  264. g(" mix(\"no fields\", "); g(++uuid); gl(");");
  265. }
  266. /* check functions */
  267. for (int i = 0; i < n_funcs; ++i) {
  268. g(" fun"); g(funcs[i]); gl("(t);");
  269. }
  270. if (n_funcs == 0) {
  271. g(" mix(\"no funcs\", "); g(++uuid); gl(");");
  272. }
  273. gl(" }");
  274. // default ctor
  275. g(" s"); g(s); g("() ");
  276. first_base = true;
  277. for (int i = 0; i < n_bases; ++i) {
  278. if (first_base) {
  279. g(": ");
  280. first_base = false;
  281. } else
  282. g(", ");
  283. g("s"); g(bases[i]); g("((char *)this)");
  284. }
  285. gl(" { calc((char *)this); }");
  286. g(" ~s"); g(s); gl("() { calc((char *)this); }");
  287. // ctor with this to the complete object
  288. g(" s"); g(s); gl("(char *t) { calc(t); }");
  289. g(" void calc_s"); g(s); gl("(char *t) { calc(t); }");
  290. g("} a"); g(s); gl(";");
  291. }
  292. main(int argc, char **argv) {
  293. unsigned seed = 0;
  294. char state[16];
  295. if (argc > 1)
  296. seed = atol(argv[1]);
  297. initstate(seed, state, sizeof(state));
  298. gl("extern \"C\" int printf(const char *...);");
  299. gl("");
  300. gl("long long sum;");
  301. gl("void mix(const char *desc, long long i) {");
  302. // If this ever becomes too slow, we can remove this after we improve the
  303. // mixing function
  304. gl(" printf(\"%s: %lld\\n\", desc, i);");
  305. gl(" sum += ((sum ^ i) << 3) + (sum<<1) - i;");
  306. gl("}");
  307. gl("");
  308. // PARAM: Randomly size testcases or large testcases?
  309. int n_structs = /* random() % */ N_STRUCTS;
  310. for (int i = 1; i < n_structs; ++i)
  311. gs(i);
  312. gl("int main() {");
  313. gl(" printf(\"%llx\\n\", sum);");
  314. gl("}");
  315. return 0;
  316. }