1 #define NOINLINE __attribute__((noinline)) 2 #define NODISCARD [[nodiscard]] 3 4 5 #include <cstdarg> 6 #include <cstdint> 7 #include <cstdlib> 8 #include <new> 9 10 enum class FillRule : uint8_t { 11 A, 12 B, 13 }; 14 15 /// This will have a destructor manually implemented via variant_body, and 16 /// similarly a Drop impl in Rust. 17 template<typename T> 18 struct OwnedSlice { 19 uintptr_t len; 20 T *ptr; ~OwnedSliceOwnedSlice21 ~OwnedSlice() {} 22 }; 23 24 template<typename LengthPercentage> 25 struct Polygon { 26 FillRule fill; 27 OwnedSlice<LengthPercentage> coordinates; 28 }; 29 30 template<typename T> 31 struct Foo { 32 enum class Tag : uint8_t { 33 Bar, 34 Polygon1, 35 Slice1, 36 Slice2, 37 Slice3, 38 Slice4, 39 }; 40 41 struct Polygon1_Body { 42 Polygon<T> _0; 43 }; 44 45 struct Slice1_Body { 46 OwnedSlice<T> _0; 47 }; 48 49 struct Slice2_Body { 50 OwnedSlice<int32_t> _0; 51 }; 52 53 struct Slice3_Body { 54 FillRule fill; 55 OwnedSlice<T> coords; 56 }; 57 58 struct Slice4_Body { 59 FillRule fill; 60 OwnedSlice<int32_t> coords; 61 }; 62 63 Tag tag; 64 union { 65 Polygon1_Body polygon1; 66 Slice1_Body slice1; 67 Slice2_Body slice2; 68 Slice3_Body slice3; 69 Slice4_Body slice4; 70 }; 71 BarFoo72 static Foo Bar() { 73 Foo result; 74 result.tag = Tag::Bar; 75 return result; 76 } 77 IsBarFoo78 bool IsBar() const { 79 return tag == Tag::Bar; 80 } 81 Polygon1Foo82 static Foo Polygon1(const Polygon<T> &a0) { 83 Foo result; 84 ::new (&result.polygon1._0) (Polygon<T>)(a0); 85 result.tag = Tag::Polygon1; 86 return result; 87 } 88 IsPolygon1Foo89 bool IsPolygon1() const { 90 return tag == Tag::Polygon1; 91 } 92 Slice1Foo93 static Foo Slice1(const OwnedSlice<T> &a0) { 94 Foo result; 95 ::new (&result.slice1._0) (OwnedSlice<T>)(a0); 96 result.tag = Tag::Slice1; 97 return result; 98 } 99 IsSlice1Foo100 bool IsSlice1() const { 101 return tag == Tag::Slice1; 102 } 103 Slice2Foo104 static Foo Slice2(const OwnedSlice<int32_t> &a0) { 105 Foo result; 106 ::new (&result.slice2._0) (OwnedSlice<int32_t>)(a0); 107 result.tag = Tag::Slice2; 108 return result; 109 } 110 IsSlice2Foo111 bool IsSlice2() const { 112 return tag == Tag::Slice2; 113 } 114 Slice3Foo115 static Foo Slice3(const FillRule &aFill, 116 const OwnedSlice<T> &aCoords) { 117 Foo result; 118 ::new (&result.slice3.fill) (FillRule)(aFill); 119 ::new (&result.slice3.coords) (OwnedSlice<T>)(aCoords); 120 result.tag = Tag::Slice3; 121 return result; 122 } 123 IsSlice3Foo124 bool IsSlice3() const { 125 return tag == Tag::Slice3; 126 } 127 Slice4Foo128 static Foo Slice4(const FillRule &aFill, 129 const OwnedSlice<int32_t> &aCoords) { 130 Foo result; 131 ::new (&result.slice4.fill) (FillRule)(aFill); 132 ::new (&result.slice4.coords) (OwnedSlice<int32_t>)(aCoords); 133 result.tag = Tag::Slice4; 134 return result; 135 } 136 IsSlice4Foo137 bool IsSlice4() const { 138 return tag == Tag::Slice4; 139 } 140 141 private: FooFoo142 Foo() { 143 144 } 145 public: 146 147 ~FooFoo148 ~Foo() { 149 switch (tag) { 150 case Tag::Polygon1: polygon1.~Polygon1_Body(); break; 151 case Tag::Slice1: slice1.~Slice1_Body(); break; 152 case Tag::Slice2: slice2.~Slice2_Body(); break; 153 case Tag::Slice3: slice3.~Slice3_Body(); break; 154 case Tag::Slice4: slice4.~Slice4_Body(); break; 155 default: break; 156 } 157 } 158 FooFoo159 Foo(const Foo& other) 160 : tag(other.tag) { 161 switch (tag) { 162 case Tag::Polygon1: ::new (&polygon1) (Polygon1_Body)(other.polygon1); break; 163 case Tag::Slice1: ::new (&slice1) (Slice1_Body)(other.slice1); break; 164 case Tag::Slice2: ::new (&slice2) (Slice2_Body)(other.slice2); break; 165 case Tag::Slice3: ::new (&slice3) (Slice3_Body)(other.slice3); break; 166 case Tag::Slice4: ::new (&slice4) (Slice4_Body)(other.slice4); break; 167 default: break; 168 } 169 } operator =Foo170 Foo& operator=(const Foo& other) { 171 if (this != &other) { 172 this->~Foo(); 173 new (this) Foo(other); 174 } 175 return *this; 176 } 177 }; 178 179 template<typename T> 180 union Baz { 181 enum class Tag : uint8_t { 182 Bar2, 183 Polygon21, 184 Slice21, 185 Slice22, 186 Slice23, 187 Slice24, 188 }; 189 190 struct Polygon21_Body { 191 Tag tag; 192 Polygon<T> _0; 193 }; 194 195 struct Slice21_Body { 196 Tag tag; 197 OwnedSlice<T> _0; 198 }; 199 200 struct Slice22_Body { 201 Tag tag; 202 OwnedSlice<int32_t> _0; 203 }; 204 205 struct Slice23_Body { 206 Tag tag; 207 FillRule fill; 208 OwnedSlice<T> coords; 209 }; 210 211 struct Slice24_Body { 212 Tag tag; 213 FillRule fill; 214 OwnedSlice<int32_t> coords; 215 }; 216 217 struct { 218 Tag tag; 219 }; 220 Polygon21_Body polygon21; 221 Slice21_Body slice21; 222 Slice22_Body slice22; 223 Slice23_Body slice23; 224 Slice24_Body slice24; 225 Bar2()226 static Baz Bar2() { 227 Baz result; 228 result.tag = Tag::Bar2; 229 return result; 230 } 231 IsBar2() const232 bool IsBar2() const { 233 return tag == Tag::Bar2; 234 } 235 Polygon21(const Polygon<T> & a0)236 static Baz Polygon21(const Polygon<T> &a0) { 237 Baz result; 238 ::new (&result.polygon21._0) (Polygon<T>)(a0); 239 result.tag = Tag::Polygon21; 240 return result; 241 } 242 IsPolygon21() const243 bool IsPolygon21() const { 244 return tag == Tag::Polygon21; 245 } 246 Slice21(const OwnedSlice<T> & a0)247 static Baz Slice21(const OwnedSlice<T> &a0) { 248 Baz result; 249 ::new (&result.slice21._0) (OwnedSlice<T>)(a0); 250 result.tag = Tag::Slice21; 251 return result; 252 } 253 IsSlice21() const254 bool IsSlice21() const { 255 return tag == Tag::Slice21; 256 } 257 Slice22(const OwnedSlice<int32_t> & a0)258 static Baz Slice22(const OwnedSlice<int32_t> &a0) { 259 Baz result; 260 ::new (&result.slice22._0) (OwnedSlice<int32_t>)(a0); 261 result.tag = Tag::Slice22; 262 return result; 263 } 264 IsSlice22() const265 bool IsSlice22() const { 266 return tag == Tag::Slice22; 267 } 268 Slice23(const FillRule & aFill,const OwnedSlice<T> & aCoords)269 static Baz Slice23(const FillRule &aFill, 270 const OwnedSlice<T> &aCoords) { 271 Baz result; 272 ::new (&result.slice23.fill) (FillRule)(aFill); 273 ::new (&result.slice23.coords) (OwnedSlice<T>)(aCoords); 274 result.tag = Tag::Slice23; 275 return result; 276 } 277 IsSlice23() const278 bool IsSlice23() const { 279 return tag == Tag::Slice23; 280 } 281 Slice24(const FillRule & aFill,const OwnedSlice<int32_t> & aCoords)282 static Baz Slice24(const FillRule &aFill, 283 const OwnedSlice<int32_t> &aCoords) { 284 Baz result; 285 ::new (&result.slice24.fill) (FillRule)(aFill); 286 ::new (&result.slice24.coords) (OwnedSlice<int32_t>)(aCoords); 287 result.tag = Tag::Slice24; 288 return result; 289 } 290 IsSlice24() const291 bool IsSlice24() const { 292 return tag == Tag::Slice24; 293 } 294 295 private: Baz()296 Baz() { 297 298 } 299 public: 300 301 ~Baz()302 ~Baz() { 303 switch (tag) { 304 case Tag::Polygon21: polygon21.~Polygon21_Body(); break; 305 case Tag::Slice21: slice21.~Slice21_Body(); break; 306 case Tag::Slice22: slice22.~Slice22_Body(); break; 307 case Tag::Slice23: slice23.~Slice23_Body(); break; 308 case Tag::Slice24: slice24.~Slice24_Body(); break; 309 default: break; 310 } 311 } 312 Baz(const Baz & other)313 Baz(const Baz& other) 314 : tag(other.tag) { 315 switch (tag) { 316 case Tag::Polygon21: ::new (&polygon21) (Polygon21_Body)(other.polygon21); break; 317 case Tag::Slice21: ::new (&slice21) (Slice21_Body)(other.slice21); break; 318 case Tag::Slice22: ::new (&slice22) (Slice22_Body)(other.slice22); break; 319 case Tag::Slice23: ::new (&slice23) (Slice23_Body)(other.slice23); break; 320 case Tag::Slice24: ::new (&slice24) (Slice24_Body)(other.slice24); break; 321 default: break; 322 } 323 } operator =(const Baz & other)324 Baz& operator=(const Baz& other) { 325 if (this != &other) { 326 this->~Baz(); 327 new (this) Baz(other); 328 } 329 return *this; 330 } 331 }; 332 333 union Taz { 334 enum class Tag : uint8_t { 335 Bar3, 336 Taz1, 337 Taz3, 338 }; 339 340 struct Taz1_Body { 341 Tag tag; 342 int32_t _0; 343 }; 344 345 struct Taz3_Body { 346 Tag tag; 347 OwnedSlice<int32_t> _0; 348 }; 349 350 struct { 351 Tag tag; 352 }; 353 Taz1_Body taz1; 354 Taz3_Body taz3; 355 Bar3()356 static Taz Bar3() { 357 Taz result; 358 result.tag = Tag::Bar3; 359 return result; 360 } 361 IsBar3() const362 bool IsBar3() const { 363 return tag == Tag::Bar3; 364 } 365 Taz1(const int32_t & a0)366 static Taz Taz1(const int32_t &a0) { 367 Taz result; 368 ::new (&result.taz1._0) (int32_t)(a0); 369 result.tag = Tag::Taz1; 370 return result; 371 } 372 IsTaz1() const373 bool IsTaz1() const { 374 return tag == Tag::Taz1; 375 } 376 Taz3(const OwnedSlice<int32_t> & a0)377 static Taz Taz3(const OwnedSlice<int32_t> &a0) { 378 Taz result; 379 ::new (&result.taz3._0) (OwnedSlice<int32_t>)(a0); 380 result.tag = Tag::Taz3; 381 return result; 382 } 383 IsTaz3() const384 bool IsTaz3() const { 385 return tag == Tag::Taz3; 386 } 387 388 private: Taz()389 Taz() { 390 391 } 392 public: 393 394 ~Taz()395 ~Taz() { 396 switch (tag) { 397 case Tag::Taz1: taz1.~Taz1_Body(); break; 398 case Tag::Taz3: taz3.~Taz3_Body(); break; 399 default: break; 400 } 401 } 402 Taz(const Taz & other)403 Taz(const Taz& other) 404 : tag(other.tag) { 405 switch (tag) { 406 case Tag::Taz1: ::new (&taz1) (Taz1_Body)(other.taz1); break; 407 case Tag::Taz3: ::new (&taz3) (Taz3_Body)(other.taz3); break; 408 default: break; 409 } 410 } operator =(const Taz & other)411 Taz& operator=(const Taz& other) { 412 if (this != &other) { 413 this->~Taz(); 414 new (this) Taz(other); 415 } 416 return *this; 417 } 418 }; 419 420 union Tazz { 421 enum class Tag : uint8_t { 422 Bar4, 423 Taz2, 424 }; 425 426 struct Taz2_Body { 427 Tag tag; 428 int32_t _0; 429 }; 430 431 struct { 432 Tag tag; 433 }; 434 Taz2_Body taz2; 435 Bar4()436 static Tazz Bar4() { 437 Tazz result; 438 result.tag = Tag::Bar4; 439 return result; 440 } 441 IsBar4() const442 bool IsBar4() const { 443 return tag == Tag::Bar4; 444 } 445 Taz2(const int32_t & a0)446 static Tazz Taz2(const int32_t &a0) { 447 Tazz result; 448 ::new (&result.taz2._0) (int32_t)(a0); 449 result.tag = Tag::Taz2; 450 return result; 451 } 452 IsTaz2() const453 bool IsTaz2() const { 454 return tag == Tag::Taz2; 455 } 456 457 private: Tazz()458 Tazz() { 459 460 } 461 public: 462 463 }; 464 465 union Tazzz { 466 enum class Tag : uint8_t { 467 Bar5, 468 Taz5, 469 }; 470 471 struct Taz5_Body { 472 Tag tag; 473 int32_t _0; 474 }; 475 476 struct { 477 Tag tag; 478 }; 479 Taz5_Body taz5; 480 Bar5()481 static Tazzz Bar5() { 482 Tazzz result; 483 result.tag = Tag::Bar5; 484 return result; 485 } 486 IsBar5() const487 bool IsBar5() const { 488 return tag == Tag::Bar5; 489 } 490 Taz5(const int32_t & a0)491 static Tazzz Taz5(const int32_t &a0) { 492 Tazzz result; 493 ::new (&result.taz5._0) (int32_t)(a0); 494 result.tag = Tag::Taz5; 495 return result; 496 } 497 IsTaz5() const498 bool IsTaz5() const { 499 return tag == Tag::Taz5; 500 } 501 502 private: Tazzz()503 Tazzz() { 504 505 } 506 public: 507 508 ~Tazzz()509 ~Tazzz() { 510 switch (tag) { 511 case Tag::Taz5: taz5.~Taz5_Body(); break; 512 default: break; 513 } 514 } 515 Tazzz(const Tazzz & other)516 Tazzz(const Tazzz& other) 517 : tag(other.tag) { 518 switch (tag) { 519 case Tag::Taz5: ::new (&taz5) (Taz5_Body)(other.taz5); break; 520 default: break; 521 } 522 } 523 }; 524 525 union Tazzzz { 526 enum class Tag : uint8_t { 527 Taz6, 528 Taz7, 529 }; 530 531 struct Taz6_Body { 532 Tag tag; 533 int32_t _0; 534 }; 535 536 struct Taz7_Body { 537 Tag tag; 538 uint32_t _0; 539 }; 540 541 struct { 542 Tag tag; 543 }; 544 Taz6_Body taz6; 545 Taz7_Body taz7; 546 Taz6(const int32_t & a0)547 static Tazzzz Taz6(const int32_t &a0) { 548 Tazzzz result; 549 ::new (&result.taz6._0) (int32_t)(a0); 550 result.tag = Tag::Taz6; 551 return result; 552 } 553 IsTaz6() const554 bool IsTaz6() const { 555 return tag == Tag::Taz6; 556 } 557 Taz7(const uint32_t & a0)558 static Tazzzz Taz7(const uint32_t &a0) { 559 Tazzzz result; 560 ::new (&result.taz7._0) (uint32_t)(a0); 561 result.tag = Tag::Taz7; 562 return result; 563 } 564 IsTaz7() const565 bool IsTaz7() const { 566 return tag == Tag::Taz7; 567 } 568 569 private: Tazzzz()570 Tazzzz() { 571 572 } 573 public: 574 575 ~Tazzzz()576 ~Tazzzz() { 577 switch (tag) { 578 case Tag::Taz6: taz6.~Taz6_Body(); break; 579 case Tag::Taz7: taz7.~Taz7_Body(); break; 580 581 } 582 } 583 Tazzzz(const Tazzzz & other)584 Tazzzz(const Tazzzz& other) 585 : tag(other.tag) { 586 switch (tag) { 587 case Tag::Taz6: ::new (&taz6) (Taz6_Body)(other.taz6); break; 588 case Tag::Taz7: ::new (&taz7) (Taz7_Body)(other.taz7); break; 589 590 } 591 } operator =(const Tazzzz & other)592 Tazzzz& operator=(const Tazzzz& other) { 593 if (this != &other) { 594 this->~Tazzzz(); 595 new (this) Tazzzz(other); 596 } 597 return *this; 598 } 599 }; 600 601 union Qux { 602 enum class Tag : uint8_t { 603 Qux1, 604 Qux2, 605 }; 606 607 struct Qux1_Body { 608 Tag tag; 609 int32_t _0; 610 operator ==Qux::Qux1_Body611 bool operator==(const Qux1_Body& other) const { 612 return _0 == other._0; 613 } 614 }; 615 616 struct Qux2_Body { 617 Tag tag; 618 uint32_t _0; 619 operator ==Qux::Qux2_Body620 bool operator==(const Qux2_Body& other) const { 621 return _0 == other._0; 622 } 623 }; 624 625 struct { 626 Tag tag; 627 }; 628 Qux1_Body qux1; 629 Qux2_Body qux2; 630 Qux1(const int32_t & a0)631 static Qux Qux1(const int32_t &a0) { 632 Qux result; 633 ::new (&result.qux1._0) (int32_t)(a0); 634 result.tag = Tag::Qux1; 635 return result; 636 } 637 IsQux1() const638 bool IsQux1() const { 639 return tag == Tag::Qux1; 640 } 641 Qux2(const uint32_t & a0)642 static Qux Qux2(const uint32_t &a0) { 643 Qux result; 644 ::new (&result.qux2._0) (uint32_t)(a0); 645 result.tag = Tag::Qux2; 646 return result; 647 } 648 IsQux2() const649 bool IsQux2() const { 650 return tag == Tag::Qux2; 651 } 652 operator ==(const Qux & other) const653 NODISCARD bool operator==(const Qux& other) const { 654 if (tag != other.tag) { 655 return false; 656 } 657 switch (tag) { 658 case Tag::Qux1: return qux1 == other.qux1; 659 case Tag::Qux2: return qux2 == other.qux2; 660 661 } 662 return true; 663 } 664 operator !=(const Qux & other) const665 NODISCARD bool operator!=(const Qux& other) const { 666 return !(*this == other); 667 } 668 669 private: Qux()670 Qux() { 671 672 } 673 public: 674 675 ~Qux()676 NOINLINE ~Qux() { 677 switch (tag) { 678 case Tag::Qux1: qux1.~Qux1_Body(); break; 679 case Tag::Qux2: qux2.~Qux2_Body(); break; 680 681 } 682 } 683 Qux(const Qux & other)684 NOINLINE Qux(const Qux& other) 685 : tag(other.tag) { 686 switch (tag) { 687 case Tag::Qux1: ::new (&qux1) (Qux1_Body)(other.qux1); break; 688 case Tag::Qux2: ::new (&qux2) (Qux2_Body)(other.qux2); break; 689 690 } 691 } operator =(const Qux & other)692 NOINLINE Qux& operator=(const Qux& other) { 693 if (this != &other) { 694 this->~Qux(); 695 new (this) Qux(other); 696 } 697 return *this; 698 } 699 }; 700 701 extern "C" { 702 703 void root(const Foo<uint32_t> *a, 704 const Baz<int32_t> *b, 705 const Taz *c, 706 Tazz d, 707 const Tazzz *e, 708 const Tazzzz *f, 709 const Qux *g); 710 711 } // extern "C" 712