github.com/gotranspile/cxgo@v0.3.7/parse_test.go (about) 1 package cxgo 2 3 import ( 4 "bytes" 5 "runtime/debug" 6 "strings" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 "modernc.org/cc/v3" 12 13 "github.com/gotranspile/cxgo/libs" 14 "github.com/gotranspile/cxgo/types" 15 ) 16 17 const testPkg = "lib" 18 19 type configFunc func(c *Config) 20 type envFunc func(c *types.Config) 21 22 type parseCase struct { 23 name string 24 inc string 25 src string 26 exp string 27 skipExp string 28 skip bool 29 builtins bool 30 configFuncs []configFunc 31 envFuncs []envFunc 32 } 33 34 func (c parseCase) shouldSkip() bool { 35 return c.skip || c.skipExp != "" 36 } 37 38 func withIdent(ic IdentConfig) configFunc { 39 return func(c *Config) { 40 c.Idents = append(c.Idents, ic) 41 } 42 } 43 44 func withIdentField(name string, f IdentConfig) configFunc { 45 return withIdent(IdentConfig{Name: name, Fields: []IdentConfig{f}}) 46 } 47 48 func withAlias(name string) configFunc { 49 return func(c *Config) { 50 c.Idents = append(c.Idents, IdentConfig{Name: name, Alias: true}) 51 } 52 } 53 54 func withRename(from, to string) configFunc { 55 return func(c *Config) { 56 c.Idents = append(c.Idents, IdentConfig{Name: from, Rename: to}) 57 } 58 } 59 60 var casesTranslate = []parseCase{ 61 { 62 name: "empty", 63 src: " ", 64 }, 65 { 66 name: "push defines", 67 src: ` 68 #define BLAH 10 69 70 int v1 = BLAH; 71 72 #pragma push_macro("BLAH") 73 #undef BLAH 74 #define BLAH 5 75 76 int v2 = BLAH; 77 78 #pragma pop_macro("BLAH") 79 80 int v3 = BLAH; 81 82 #pragma push_macro("NON_EXISTENT") 83 #pragma pop_macro("NON_EXISTENT") 84 `, 85 exp: ` 86 const BLAH = 10 87 const BLAH = 5 88 89 var v1 int32 = BLAH 90 var v2 int32 = BLAH 91 var v3 int32 = BLAH 92 `, 93 skipExp: ` 94 const BLAH = 10 95 96 var v1 int32 = BLAH 97 var v2 int32 = BLAH 98 var v3 int32 = BLAH 99 `, 100 }, 101 { 102 name: "switch", 103 src: ` 104 void foo(int a) { 105 switch (a) { 106 case 1: 107 foo(1); 108 break; 109 case 2: 110 foo(2); 111 default: 112 foo(0); 113 case 3: 114 foo(3); 115 break; 116 case 4: 117 case 5: 118 foo(5); 119 return; 120 case 6: 121 foo(6); 122 } 123 } 124 `, 125 exp: ` 126 func foo(a int32) { 127 switch a { 128 case 1: 129 foo(1) 130 case 2: 131 foo(2) 132 fallthrough 133 default: 134 foo(0) 135 fallthrough 136 case 3: 137 foo(3) 138 case 4: 139 fallthrough 140 case 5: 141 foo(5) 142 return 143 case 6: 144 foo(6) 145 } 146 } 147 `, 148 }, 149 { 150 skip: true, 151 name: "switch cases everywhere", 152 src: ` 153 void foo(int p, char s) { 154 switch (p) { 155 case 0: 156 if (s == 'a') { 157 case 1: 158 s = 'c'; 159 } 160 break; 161 } 162 } 163 `, 164 exp: ` 165 func foo(p int32, s int8) { 166 switch p { 167 case 1: 168 goto case_1 169 case 0: 170 if s == 'a' { 171 case_1: 172 s = 'c' 173 } 174 } 175 } 176 `, 177 }, 178 { 179 skip: true, 180 name: "switch cases everywhere 2", 181 src: ` 182 void foo(int p, char s) { 183 switch (p) { 184 if (s) { 185 case 0: 186 if (s == 'a') { 187 case 1: 188 s = 'c'; 189 } 190 break; 191 } 192 case 2: 193 s = 'd'; 194 break; 195 } 196 } 197 `, 198 exp: ` 199 func foo(p int32, s int8) { 200 switch { 201 case s != 0 && p == 1: 202 goto case_1 203 case s != 0 && p == 0: 204 if s == 'a' { 205 case_1: 206 s = 'c' 207 } 208 case p == 2 209 s = 'd' 210 } 211 } 212 `, 213 }, 214 { 215 name: "revert last if", 216 skip: !optimizeStatements, 217 src: ` 218 int foo(int* a, int* b) { 219 if (a) { 220 foo(a); 221 foo(a); 222 foo(a); 223 } 224 foo(b); 225 return 1; 226 } 227 `, 228 exp: ` 229 func foo(a *int32, b *int32) int32 { 230 if a == nil { 231 foo(b) 232 return 1 233 } 234 foo(a) 235 foo(a) 236 foo(a) 237 foo(b) 238 return 1 239 } 240 `, 241 }, 242 { 243 name: "revert last if goto", 244 skip: !optimizeStatements, 245 src: ` 246 int foo(int* a, int* b) { 247 if (a) { 248 foo(a); 249 foo(a); 250 foo(a); 251 } 252 LABEL_X: 253 foo(b); 254 return 1; 255 } 256 `, 257 exp: ` 258 func foo(a *int32, b *int32) int32 { 259 if a == nil { 260 foo(b) 261 return 1 262 } 263 foo(a) 264 foo(a) 265 foo(a) 266 foo(b) 267 return 1 268 } 269 `, 270 }, 271 { 272 name: "revert last if void", 273 skip: !optimizeStatements, 274 src: ` 275 void foo(int* a) { 276 if (a) { 277 foo(a); 278 foo(a); 279 foo(a); 280 } 281 } 282 `, 283 exp: ` 284 func foo(a *int32) { 285 if a == nil { 286 return 287 } 288 foo(a) 289 foo(a) 290 foo(a) 291 } 292 `, 293 }, 294 { 295 name: "move return to if", 296 skip: !optimizeStatements, 297 src: ` 298 int foo(int* a) { 299 if (a) { 300 foo(a); 301 } else { 302 foo(a); 303 } 304 return 1; 305 } 306 `, 307 exp: ` 308 func foo(a *int32) int32 { 309 if a != nil { 310 foo(a) 311 return 1 312 } 313 foo(a) 314 return 1 315 } 316 `, 317 }, 318 { 319 name: "move return to if nested", 320 skip: !optimizeStatements, 321 src: ` 322 int foo(int a) { 323 if (a == 1) { 324 foo(2); 325 if (a == 3) { 326 foo(4); 327 } else if (a == 5) { 328 foo(6); 329 } 330 } 331 return 1; 332 } 333 `, 334 exp: ` 335 func foo(a int32) int32 { 336 if a != 1 { 337 return 1 338 } 339 foo(2) 340 if a == 3 { 341 foo(4) 342 return 1 343 } else if a == 5 { 344 foo(6) 345 return 1 346 } 347 return 1 348 } 349 `, 350 }, 351 { 352 name: "revert last if cost", 353 skip: !optimizeStatements, 354 src: ` 355 int foo(int* a) { 356 if (a) { 357 foo(a); 358 foo(a); 359 if (a) { 360 foo(a); 361 } 362 foo(a); 363 return 1; 364 } 365 foo(a); 366 foo(a); 367 foo(a); 368 return 0; 369 } 370 `, 371 exp: ` 372 func foo(a *int32) int32 { 373 if a == nil { 374 foo(a) 375 foo(a) 376 foo(a) 377 return 0 378 } 379 foo(a) 380 foo(a) 381 if a != nil { 382 foo(a) 383 } 384 foo(a) 385 return 1 386 } 387 `, 388 }, 389 { 390 name: "sub_40BC10", 391 inc: `typedef unsigned int _DWORD;`, 392 src: ` 393 unsigned char blob[10]; 394 char* foo(int a) { 395 return (char*)(*(_DWORD*)& blob[3] + 160 * a); 396 } 397 `, 398 exp: ` 399 var blob [10]uint8 400 401 func foo(a int32) *byte { 402 return (*byte)(unsafe.Pointer(uintptr(*(*_DWORD)(unsafe.Pointer(&blob[3])) + _DWORD(a*160)))) 403 } 404 `, 405 }, 406 { 407 name: "inline gotos", 408 skip: !optimizeStatements, 409 src: ` 410 int foo(int* a) { 411 if (a) { 412 foo(a); 413 LABEL_2: 414 foo(a); 415 if (a) { 416 foo(a); 417 goto LABEL_1; 418 } 419 LABEL_1: 420 foo(a); 421 return 1; 422 } 423 foo(a); 424 foo(a); 425 goto LABEL_2; 426 } 427 `, 428 exp: ` 429 func foo(a *int32) int32 { 430 if a == nil { 431 foo(a) 432 foo(a) 433 goto LABEL_2 434 } 435 foo(a) 436 LABEL_2: 437 foo(a) 438 if a == nil { 439 foo(a) 440 return 1 441 } 442 foo(a) 443 foo(a) 444 return 1 445 } 446 `, 447 }, 448 { 449 name: "inline gotos chain", 450 skip: !optimizeStatements, 451 src: ` 452 int foo(int* a) { 453 if (a) { 454 foo(a); 455 foo(a); 456 if (a) { 457 LABEL_2: 458 foo(a); 459 goto LABEL_1; 460 } 461 LABEL_1: 462 foo(a); 463 return 1; 464 } 465 foo(a); 466 foo(a); 467 goto LABEL_2; 468 } 469 `, 470 exp: ` 471 func foo(a *int32) int32 { 472 if a == nil { 473 foo(a) 474 foo(a) 475 foo(a) 476 foo(a) 477 return 1 478 } 479 foo(a) 480 foo(a) 481 if a == nil { 482 foo(a) 483 return 1 484 } 485 foo(a) 486 foo(a) 487 return 1 488 } 489 `, 490 }, 491 { 492 name: "blocks with vars", 493 src: ` 494 #define set(s) \ 495 { int t = s;\ 496 } 497 498 void main() { 499 int s; 500 if (0) { 501 set(s) 502 set(s) 503 set(s) 504 } 505 } 506 `, 507 exp: ` 508 func main() { 509 var s int32 510 if false { 511 { 512 var t int32 = s 513 _ = t 514 } 515 { 516 var t int32 = s 517 _ = t 518 } 519 { 520 var t int32 = s 521 _ = t 522 } 523 } 524 } 525 `, 526 }, 527 { 528 name: "blocks no vars", 529 src: ` 530 #define set(s) \ 531 { t = s;\ 532 } 533 534 void main() { 535 int s, t; 536 if (0) { 537 set(s) 538 set(s) 539 set(s) 540 } 541 } 542 `, 543 exp: ` 544 func main() { 545 var ( 546 s int32 547 t int32 548 ) 549 _ = t 550 if false { 551 t = s 552 t = s 553 t = s 554 } 555 } 556 `, 557 }, 558 { 559 name: "sizeof only", 560 builtins: true, 561 src: ` 562 int a = sizeof(int); 563 `, 564 exp: ` 565 var a int32 = int32(unsafe.Sizeof(int32(0))) 566 `, 567 }, 568 { 569 name: "sizeof", 570 builtins: true, 571 src: ` 572 void foo() { 573 size_t a; 574 int b[10]; 575 unsigned char b2[10]; 576 void* c; 577 int* d; 578 int (*e)(void); 579 a = sizeof(b); 580 a = sizeof(b2); 581 a = sizeof(c); 582 a = sizeof(d); 583 a = sizeof(e); 584 } 585 `, 586 exp: ` 587 func foo() { 588 var a size_t 589 _ = a 590 var b [10]int32 591 _ = b 592 var b2 [10]uint8 593 _ = b2 594 var c unsafe.Pointer 595 _ = c 596 var d *int32 597 _ = d 598 var e func() int32 599 _ = e 600 a = size_t(unsafe.Sizeof([10]int32{})) 601 a = size_t(10) 602 a = size_t(unsafe.Sizeof(unsafe.Pointer(nil))) 603 a = size_t(unsafe.Sizeof((*int32)(nil))) 604 a = size_t(unsafe.Sizeof(uintptr(0))) 605 } 606 `, 607 }, 608 { 609 name: "assign expr", 610 src: ` 611 void foo() { 612 int a; 613 int b; 614 b = a = 1; 615 } 616 `, 617 exp: ` 618 func foo() { 619 var ( 620 a int32 621 b int32 622 ) 623 _ = b 624 b = func() int32 { 625 a = 1 626 return a 627 }() 628 } 629 `, 630 }, 631 { 632 name: "stdint override", 633 src: ` 634 #include <stdint.h> 635 636 void foo() { 637 int16_t a1; 638 uint32_t a2; 639 } 640 `, 641 exp: ` 642 func foo() { 643 var a1 int16 644 _ = a1 645 var a2 uint32 646 _ = a2 647 } 648 `, 649 }, 650 { 651 name: "void cast", 652 src: ` 653 void foo(int a, int* b) { 654 int c; 655 (void)a; 656 (void)b; 657 (void)c; 658 } 659 `, 660 exp: ` 661 func foo(a int32, b *int32) { 662 var c int32 663 _ = a 664 _ = b 665 _ = c 666 } 667 `, 668 }, 669 { 670 name: "assign ternary", 671 src: ` 672 void foo(int a) { 673 a = a ? 1 : 0; 674 a = -(a ? 1 : 0); 675 int b = a ? 1 : 0; 676 } 677 `, 678 exp: ` 679 func foo(a int32) { 680 if a != 0 { 681 a = 1 682 } else { 683 a = 0 684 } 685 if a != 0 { 686 a = -1 687 } else { 688 a = 0 689 } 690 var b int32 691 _ = b 692 if a != 0 { 693 b = 1 694 } else { 695 b = 0 696 } 697 } 698 `, 699 }, 700 { 701 name: "return ternary", 702 src: ` 703 int foo(int a) { 704 return a ? 1 : 0; 705 } 706 `, 707 exp: ` 708 func foo(a int32) int32 { 709 if a != 0 { 710 return 1 711 } 712 return 0 713 } 714 `, 715 }, 716 { 717 skip: true, 718 name: "multiple assignments", 719 src: ` 720 void foo(int a) { 721 int b, c; 722 c = b = a; 723 c = b = a++; 724 c = b = ++a; 725 } 726 `, 727 exp: ` 728 func foo(a int32) { 729 var b, c int32 730 b, c = a, a 731 b, c = a, a 732 a++ 733 a++ 734 b, c = a, a 735 } 736 `, 737 }, 738 { 739 skip: true, 740 name: "if init 1", 741 src: ` 742 void foo(int a) { 743 if (a = 1, a) { 744 a = 0; 745 } 746 } 747 `, 748 exp: ` 749 func foo(a int32) { 750 if a = 1; a != 0 { 751 a = 0 752 } 753 } 754 `, 755 }, 756 { 757 skip: true, 758 name: "if init 2", 759 src: ` 760 void foo(int a) { 761 if (a = 1) { 762 a = 0; 763 } 764 } 765 `, 766 exp: ` 767 func foo(a int32) { 768 if a = 1; a != 0 { 769 a = 0 770 } 771 } 772 `, 773 }, 774 { 775 skip: true, 776 name: "if init 3", 777 src: ` 778 void foo(int a) { 779 if ((a = 1) != 0) { 780 a = 0; 781 } 782 } 783 `, 784 exp: ` 785 func foo(a int32) { 786 if a = 1; a != 0 { 787 a = 0 788 } 789 } 790 `, 791 }, 792 { 793 name: "multiple stmt splits", 794 src: ` 795 typedef struct list_t list_t; 796 typedef struct list_t { 797 list_t* next; 798 } list_t; 799 800 void foo() { 801 list_t *elt, *list; 802 for (elt=list; elt ? (list=elt->next, elt->next=0), 1 : 0; elt=list) {} 803 } 804 `, 805 exp: ` 806 type list_t struct { 807 Next *list_t 808 } 809 810 func foo() { 811 var ( 812 elt *list_t 813 list *list_t 814 ) 815 for elt = list; func() int { 816 if elt != nil { 817 return func() int { 818 list = elt.Next 819 elt.Next = nil 820 return 1 821 }() 822 } 823 return 0 824 }() != 0; elt = list { 825 } 826 } 827 `, 828 envFuncs: []envFunc{func(c *types.Config) { 829 c.UseGoInt = true 830 }}, 831 }, 832 } 833 834 func TestTranslate(t *testing.T) { 835 runTestTranslate(t, casesTranslate) 836 } 837 838 func runTestTranslateCase(t *testing.T, c parseCase) { 839 if c.shouldSkip() { 840 defer func() { 841 if r := recover(); r != nil { 842 defer debug.PrintStack() 843 t.Skip(r) 844 } 845 }() 846 } 847 fname := strings.ReplaceAll(c.name, " ", "_") + ".c" 848 var srcs []cc.Source 849 if c.inc != "" { 850 srcs = append(srcs, cc.Source{ 851 Name: strings.TrimSuffix(fname, ".c") + "_predef.h", 852 Value: c.inc, 853 }) 854 } 855 srcs = append(srcs, cc.Source{ 856 Name: fname, 857 Value: c.src, 858 }) 859 econf := types.Config32() 860 for _, f := range c.envFuncs { 861 f(&econf) 862 } 863 env := libs.NewEnv(econf) 864 ast, err := ParseSource(env, ParseConfig{ 865 WorkDir: "", 866 Predefines: c.builtins, 867 Sources: srcs, 868 }) 869 if c.skip { 870 t.SkipNow() 871 } else { 872 require.NoError(t, err) 873 } 874 875 tconf := Config{ForwardDecl: true} 876 for _, f := range c.configFuncs { 877 f(&tconf) 878 } 879 decls, err := TranslateAST(fname, ast, env, tconf) 880 require.NoError(t, err) 881 882 buf := bytes.NewBuffer(nil) 883 err = PrintGo(buf, testPkg, decls) 884 assert.NoError(t, err) 885 886 exp := c.exp 887 a, b := strings.TrimSpace(exp), strings.TrimSpace(strings.TrimPrefix(buf.String(), "package lib")) 888 if a != b { 889 if c.skipExp != "" { 890 a = strings.TrimSpace(c.skipExp) 891 require.Equal(t, a, b) 892 t.SkipNow() 893 } else if c.skip { 894 t.SkipNow() 895 } else { 896 require.Equal(t, a, b) 897 } 898 } 899 if c.skip && !t.Failed() { 900 require.Fail(t, "skipped test passes") 901 } 902 } 903 904 func runTestTranslate(t *testing.T, cases []parseCase) { 905 for _, c := range cases { 906 t.Run(c.name, func(t *testing.T) { 907 runTestTranslateCase(t, c) 908 }) 909 } 910 } 911 912 func TestTypeResolution(t *testing.T) { 913 const ( 914 fname = "resolve.c" 915 ) 916 env := libs.NewEnv(types.Config32()) 917 ast, err := ParseSource(env, ParseConfig{ 918 WorkDir: "", 919 Sources: []cc.Source{ 920 // { 921 // Name: "resolve.h", 922 // Value:` 923 //void unused(char*,int); 924 //`, 925 // }, 926 { 927 Name: fname, 928 Value: ` 929 typedef int int_t; 930 int_t a, b; 931 struct bar { 932 int_t x; 933 int_t y; 934 }; 935 struct bar *f1(int_t c, struct bar e) { 936 int_t b; 937 int_t d = a + b + c + e.x + e.y; 938 } 939 `, 940 }, 941 }, 942 }) 943 require.NoError(t, err) 944 945 decls, err := TranslateCAST(fname, ast, env, Config{}) 946 require.NoError(t, err) 947 require.Len(t, decls, 5) 948 949 // find the first int typedef 950 d1, ok := decls[0].(*CTypeDef) 951 require.True(t, ok) 952 // check the named type that we get 953 intT := d1.Named 954 assert.Equal(t, "int_t", intT.Name().Name) 955 assert.Equal(t, types.IntT(4), intT.Underlying()) 956 957 // both variable declarations should have exactly the same type (by pointer) 958 a1d, ok := decls[1].(*CVarDecl) 959 require.True(t, ok) 960 assert.Equal(t, "a", a1d.Names[0].Name) 961 assert.True(t, intT == a1d.Type, "invalid type in global") 962 963 b1d, ok := decls[2].(*CVarDecl) 964 require.True(t, ok) 965 assert.Equal(t, "b", b1d.Names[0].Name) 966 assert.True(t, intT == b1d.Type, "invalid type in global 2") 967 968 // test struct definition 969 bard, ok := decls[3].(*CTypeDef) 970 require.True(t, ok) 971 assert.Equal(t, "bar", bard.Name().Name) 972 bar, ok := bard.Underlying().(*types.StructType) 973 require.True(t, ok) 974 require.Len(t, bar.Fields(), 2) 975 xf := bar.Fields()[0] 976 yf := bar.Fields()[1] 977 assert.True(t, intT == xf.Type(), "invalid type in struct field 1") 978 assert.True(t, intT == yf.Type(), "invalid type in struct field 2") 979 980 // check that the same type works in function args 981 f1d, ok := decls[4].(*CFuncDecl) 982 require.True(t, ok) 983 assert.Equal(t, "f1", f1d.Name.Name) 984 f1t := f1d.Type 985 require.Len(t, f1t.Args(), 2) 986 assert.True(t, intT == f1t.Args()[0].Type(), "invalid type in func arg") 987 assert.True(t, bard.Named == f1t.Args()[1].Type(), "invalid type in func arg") 988 p1, ok := f1t.Return().(types.PtrType) 989 require.True(t, ok) 990 assert.True(t, bard.Named == p1.Elem(), "invalid type in func return") 991 992 require.Len(t, f1d.Body.Stmts, 3) 993 // first decl is always __func__ 994 s1, ok := f1d.Body.Stmts[0].(*CDeclStmt) 995 require.True(t, ok) 996 fnc_, ok := s1.Decl.(*CVarDecl) 997 require.True(t, ok) 998 require.Equal(t, "__func__", fnc_.Names[0].Name) 999 1000 // check if the type works in function body 1001 s1, ok = f1d.Body.Stmts[1].(*CDeclStmt) 1002 require.True(t, ok) 1003 b2d, ok := s1.Decl.(*CVarDecl) 1004 require.True(t, ok) 1005 assert.Equal(t, "b", b2d.Names[0].Name) 1006 assert.True(t, intT == b2d.Type, "invalid type in local") 1007 // and that we can distinguish globals from locals 1008 assert.True(t, b1d != b2d) 1009 assert.True(t, b1d.Names[0] != b2d.Names[0]) 1010 1011 // check same conditions for a second local decl 1012 s1, ok = f1d.Body.Stmts[2].(*CDeclStmt) 1013 require.True(t, ok) 1014 d1d, ok := s1.Decl.(*CVarDecl) 1015 require.True(t, ok) 1016 assert.Equal(t, "d", d1d.Names[0].Name) 1017 assert.True(t, intT == d1d.Type, "invalid type in local 2") 1018 // check variables - one is global, second is local, third is an arg 1019 e1, ok := d1d.Inits[0].(*CBinaryExpr) 1020 require.True(t, ok, "%T", d1d.Inits[0]) 1021 e2, ok := e1.Right.(*CSelectExpr) 1022 assert.True(t, ok, "%T", e1.Right) 1023 assert.True(t, e2.Sel == yf.Name, "invalid field ref 5") // arg 1024 assert.True(t, e2.Expr == IdentExpr{f1t.Args()[1].Name}, "invalid ref 5") // arg 1025 1026 e1, ok = e1.Left.(*CBinaryExpr) 1027 require.True(t, ok, "%T", e1.Left) 1028 e2, ok = e1.Right.(*CSelectExpr) 1029 assert.True(t, ok, "%T", e1.Right) 1030 assert.True(t, e2.Sel == xf.Name, "invalid field ref 4") // arg 1031 assert.True(t, e2.Expr == IdentExpr{f1t.Args()[1].Name}, "invalid ref 4") // arg 1032 1033 e1, ok = e1.Left.(*CBinaryExpr) 1034 require.True(t, ok, "%T", e1.Left) 1035 assert.True(t, IdentExpr{f1t.Args()[0].Name} == e1.Right, "invalid ref 3") // arg 1036 1037 e1, ok = e1.Left.(*CBinaryExpr) 1038 require.True(t, ok) 1039 assert.True(t, IdentExpr{a1d.Names[0]} == e1.Left, "invalid ref 1") // global 1040 assert.True(t, IdentExpr{b2d.Names[0]} == e1.Right, "invalid ref 2") // local 1041 }