modernc.org/qbe@v0.0.9/cc/all_test.go (about) 1 // Copyright 2021 The QBE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //TODO Csmith 6 7 package cc // import "modernc.org/qbe/cc" 8 9 import ( 10 "bufio" 11 "bytes" 12 "context" 13 "encoding/hex" 14 "flag" 15 "fmt" 16 "go/build" 17 "io" 18 "io/ioutil" 19 "math" 20 "os" 21 "os/exec" 22 "path" 23 "path/filepath" 24 "regexp" 25 "runtime" 26 "runtime/debug" 27 "sort" 28 "strconv" 29 "strings" 30 "sync" 31 "testing" 32 "time" 33 34 "github.com/pmezard/go-difflib/difflib" 35 "modernc.org/cc/v3" 36 "modernc.org/ccgo/v3/lib" 37 "modernc.org/ccorpus" 38 "modernc.org/qbe" 39 ) 40 41 var ( 42 fs = ccorpus.FileSystem() 43 includePaths []string 44 initIncludePathsOnce sync.Once 45 oBenchO = flag.Int("BO", 3, "") 46 oBestOf = flag.Int("bestof", 5, "TestBenchmarksGame: best of N") 47 oCSmith = flag.Duration("csmith", time.Minute, "") 48 oFF = flag.Bool("ff", false, "fail fast") 49 oFullPaths = flag.Bool("full-paths", false, "") 50 oInstall = flag.Bool("install", false, "install qbec and ecc binaries") 51 oKeepTmp = flag.Bool("keep-tmp", false, "") 52 oMarch = flag.String("march", "native", "") 53 oMtune = flag.String("mtune", "native", "") 54 oO = flag.Int("O", 1, "") 55 oOpenmp = flag.Bool("fopenmp", false, "") 56 oRE = flag.String("re", "", "") 57 oTrc = flag.Bool("trc", false, "") 58 oTrc2 = flag.Bool("trc2", false, "") 59 oTrco = flag.Bool("trco", false, "") 60 overlayDir string 61 predefined string 62 re *regexp.Regexp 63 sysIncludePaths []string 64 systemCC string 65 systemCCVersion string 66 tempDir string 67 ) 68 69 func init() { 70 use(use) 71 } 72 73 func use(...interface{}) {} 74 75 func initIncludePaths(cpp string) error { 76 var err error 77 predefined, includePaths, sysIncludePaths, err = cc.HostConfig(cpp) 78 if err != nil { 79 return err 80 } 81 82 includePaths = append(includePaths, "@") 83 includePaths = append(includePaths, sysIncludePaths...) 84 return nil 85 } 86 87 func TestMain(m *testing.M) { 88 fmt.Fprintf(os.Stderr, "qbe/cc: %v\n", os.Args) 89 oGCC := flag.String("gcc", "", "") 90 flag.BoolVar(&qbe.TraceC, "trcc", false, "") 91 flag.BoolVar(&oTrcw, "trcw", false, "") 92 flag.Parse() 93 if s := *oRE; s != "" { 94 re = regexp.MustCompile(s) 95 } 96 if *oGCC == "" { 97 var err error 98 initIncludePathsOnce.Do(func() { err = initIncludePaths("") }) 99 if err != nil { 100 fmt.Println(err) 101 os.Exit(1) 102 } 103 104 if systemCC, err = exec.LookPath(env("QBEC_CC", env("CC", "gcc"))); err != nil { 105 fmt.Println(err) 106 os.Exit(1) 107 } 108 109 fmt.Fprintf(os.Stderr, "QBEC_CC=%s\n", systemCC) 110 out, err := exec.Command(systemCC, "--version").CombinedOutput() 111 if err == nil { 112 if a := strings.Split(string(out), "\n"); len(a) > 0 { 113 systemCCVersion = a[0] 114 fmt.Fprintf(os.Stderr, "%s\n", systemCCVersion) 115 } 116 } 117 118 os.Exit(testMain(m)) 119 } 120 121 var args []string 122 for i, v := range os.Args { 123 if v == "-gcc" { 124 args = append(os.Args[:i], os.Args[i+2:]...) 125 } 126 } 127 a := strings.Split(*oGCC, ",") 128 rc := 0 129 for _, suffix := range a { 130 systemCC = fmt.Sprintf("gcc-%s", suffix) 131 systemCPP := fmt.Sprintf("cpp-%s", suffix) 132 var err error 133 if systemCC, err = exec.LookPath(systemCC); err != nil { 134 fmt.Fprintf(os.Stderr, "%s: %s\n", systemCC, err) 135 continue 136 } 137 138 if systemCPP, err = exec.LookPath(systemCPP); err != nil { 139 fmt.Fprintf(os.Stderr, "%s: %s\n", systemCPP, err) 140 continue 141 } 142 143 os.Setenv("QBEC_CC", systemCC) 144 os.Setenv("ECC_CPP", systemCPP) 145 cmd := exec.Command(args[0], args[1:]...) 146 cmd.Stdout = os.Stdout 147 cmd.Stderr = os.Stderr 148 if err := cmd.Run(); err != nil { 149 rc = 1 150 } 151 } 152 os.Exit(rc) 153 154 } 155 156 func testMain(m *testing.M) int { 157 var err error 158 tempDir, err = ioutil.TempDir("", "qbe-cc-test-") 159 if err != nil { 160 panic(err) //TODOOK 161 } 162 163 switch { 164 case *oKeepTmp: 165 fmt.Fprintf(os.Stderr, "keeping temporary directory %s\n", tempDir) 166 default: 167 defer os.RemoveAll(tempDir) 168 } 169 170 s := filepath.FromSlash("testdata/overlay") 171 if overlayDir, err = filepath.Abs(s); err != nil { 172 panic(err) //TODOOK 173 } 174 175 return m.Run() 176 } 177 178 func mustEmptyDir(t *testing.T, s string) { 179 if err := emptyDir(s); err != nil { 180 t.Fatal(err) 181 } 182 } 183 184 func emptyDir(s string) error { 185 m, err := filepath.Glob(filepath.FromSlash(s + "/*")) 186 if err != nil { 187 return err 188 } 189 190 for _, v := range m { 191 fi, err := os.Stat(v) 192 if err != nil { 193 return err 194 } 195 196 switch { 197 case fi.IsDir(): 198 if err = os.RemoveAll(v); err != nil { 199 return err 200 } 201 default: 202 if err = os.Remove(v); err != nil { 203 return err 204 } 205 } 206 } 207 return nil 208 } 209 210 type runResult struct { 211 ccTime time.Duration 212 csmithSrc []byte 213 eccTime time.Duration 214 err error 215 name string 216 out []byte 217 } 218 219 type skipErr string 220 221 func (e skipErr) Error() string { return "skipped: " + string(e) } 222 223 type runTask struct { 224 args []string 225 c chan *runResult 226 cmd string 227 csmithSrc []byte 228 opts []string 229 src string 230 231 ccCanFail bool 232 doNotExec bool 233 hasBinaryOutput bool 234 } 235 236 func (t *runTask) run() { 237 r := &runResult{name: t.src} 238 r.out, r.err, r.ccTime, r.eccTime = t.run0() 239 t.c <- r 240 } 241 242 func (t *runTask) runCSmith() { 243 r := &runResult{name: t.src, csmithSrc: t.csmithSrc} 244 r.out, r.err, r.ccTime, r.eccTime = t.run0CSmith() 245 t.c <- r 246 } 247 248 func (t *runTask) run0() (_ []byte, err error, ccTime, eccTime time.Duration) { 249 const outLimit = 1 << 16 250 defer func() { 251 if e := recover(); e != nil { 252 switch { 253 case err == nil: 254 err = fmt.Errorf("PANIC: %v\n%s", e, debug.Stack()) 255 default: 256 err = fmt.Errorf("%v\nPANIC: %v\n%s", err, e, debug.Stack()) 257 } 258 } 259 }() 260 261 overlay := filepath.Join(overlayDir, t.src) 262 b, err := ioutil.ReadFile(overlay) 263 if err != nil { 264 if !os.IsNotExist(err) { 265 return nil, err, ccTime, eccTime 266 } 267 268 f, err := fs.Open(t.src) 269 if err != nil { 270 return nil, err, ccTime, eccTime 271 } 272 273 if b, err = ioutil.ReadAll(f); err != nil { 274 return nil, err, ccTime, eccTime 275 } 276 277 if err = f.Close(); err != nil { 278 return nil, err, ccTime, eccTime 279 } 280 } 281 282 overlay = filepath.Join(overlayDir, t.src+".expectrc") 283 b2, err := ioutil.ReadFile(overlay) 284 if err != nil { 285 f, err := fs.Open(t.src + ".expectrc") 286 if err == nil { 287 if b2, err = ioutil.ReadAll(f); err != nil { 288 return nil, err, ccTime, eccTime 289 } 290 291 if err = f.Close(); err != nil { 292 return nil, err, ccTime, eccTime 293 } 294 } 295 } 296 var expectRC int 297 if len(b2) != 0 { 298 s := strings.TrimSpace(string(b2)) 299 n, err := strconv.ParseUint(s, 10, 32) 300 if err != nil { 301 return nil, err, ccTime, eccTime 302 } 303 304 expectRC = int(n) 305 } 306 307 baseName := filepath.Base(t.src) 308 if err := ioutil.WriteFile(baseName, b, 0600); err != nil { 309 return nil, err, ccTime, eccTime 310 } 311 312 args, err := getArgs(t.src) 313 if err != nil { 314 return nil, err, ccTime, eccTime 315 } 316 317 ccArgs := append([]string{"-lm"}, t.opts...) 318 ok := true 319 for _, v := range t.opts { 320 if strings.HasPrefix(v, "-O") { 321 ok = false 322 break 323 } 324 } 325 if ok { 326 if o := *oO; o >= 0 { 327 ccArgs = append(ccArgs, fmt.Sprintf("-O%d", o)) 328 } 329 } 330 if t.doNotExec { 331 ccArgs = append(ccArgs, "-c") 332 } 333 binary, err := makeCCBinary(baseName, t.doNotExec, ccArgs...) 334 if err != nil { 335 return nil, skipErr(err.Error()), ccTime, eccTime 336 } 337 338 const ( 339 ccOut = "cc.out" 340 eccOut = "ecc.out" 341 ) 342 var binaryBytes, binaryBytes2 int 343 var expected []byte 344 if !t.doNotExec { 345 ctx, cancel := context.WithTimeout(context.Background(), 4*time.Minute) 346 defer cancel() 347 if t.cmd != "" { 348 binary = t.cmd 349 } 350 if len(t.args) != 0 { 351 args = t.args 352 } 353 t0 := time.Now() 354 if *oTrc2 { 355 fmt.Fprintf(os.Stderr, "%v: started CC binary for %s: %v %v\n", t0, baseName, binary, args) 356 } 357 switch { 358 case t.hasBinaryOutput: 359 binaryBytes, err = execute(ctx, binary, ccOut, args) 360 defer os.Remove(ccOut) 361 default: 362 expected, err = exec.CommandContext(ctx, binary, args...).CombinedOutput() 363 if len(expected) > outLimit { 364 panic(todo("", t.src, len(expected))) 365 } 366 } 367 ccTime = time.Since(t0) 368 if *oTrc2 { 369 switch { 370 case t.hasBinaryOutput: 371 fmt.Fprintf(os.Stderr, "%v: CC binary for %s returned: %v bytes, err %v\n", time.Now(), baseName, binaryBytes, err) 372 default: 373 fmt.Fprintf(os.Stderr, "%v: CC binary for %s returned: err %v\n%s\n", time.Now(), baseName, err, expected) 374 } 375 } 376 if err != nil { 377 switch { 378 case t.ccCanFail: 379 expected = nil 380 expectRC = 0 381 default: 382 rc := err.(*exec.ExitError).ProcessState.ExitCode() 383 if rc != expectRC { 384 return nil, skipErr(fmt.Sprintf("executing CC binary %v %v: %v (rc %v, expected %v)\n%s", binary, args, err, rc, expectRC, expected)), ccTime, eccTime 385 } 386 387 err = nil 388 } 389 } 390 391 if *oTrco { 392 switch { 393 case t.hasBinaryOutput: 394 fmt.Fprintf(os.Stderr, "%v %q: %d bytes\n", ccTime, args, binaryBytes) 395 default: 396 fmt.Fprintf(os.Stderr, "%v %q: %s\n", ccTime, args, expected) 397 } 398 } 399 } 400 401 if t.cmd == "" { 402 if err := os.Remove(binary); err != nil { 403 return nil, fmt.Errorf("removing %v: %v", binary, err), ccTime, eccTime 404 } 405 } 406 407 eccArgs := append([]string{"-lm"}, t.opts...) 408 ok = true 409 for _, v := range t.opts { 410 if strings.HasPrefix(v, "-O") { 411 ok = false 412 break 413 } 414 } 415 if ok { 416 if o := *oO; o >= 0 { 417 eccArgs = append(eccArgs, fmt.Sprintf("-O%d", o)) 418 } 419 } 420 if *oFullPaths { 421 eccArgs = append(eccArgs, "-full-paths") 422 } 423 if *oKeepTmp { 424 eccArgs = append(eccArgs, "-keep-tmp") 425 } 426 if t.doNotExec { 427 eccArgs = append(ccArgs, "-c") 428 } 429 if binary, err = makeBinary(t.src, t.doNotExec, eccArgs...); err != nil { 430 return nil, err, ccTime, eccTime 431 } 432 433 var got []byte 434 if !t.doNotExec { 435 ctx, cancel := context.WithTimeout(context.Background(), 4*time.Minute) 436 defer cancel() 437 if t.cmd != "" { 438 binary = t.cmd 439 } 440 if len(t.args) != 0 { 441 args = t.args 442 } 443 t0 := time.Now() 444 if *oTrc2 { 445 fmt.Fprintf(os.Stderr, "%v: started ecc binary for %s: %v %v\n", t0, baseName, binary, args) 446 } 447 switch { 448 case t.hasBinaryOutput: 449 binaryBytes2, err = execute(ctx, binary, eccOut, args) 450 defer os.Remove(eccOut) 451 default: 452 got, err = exec.CommandContext(ctx, binary, args...).CombinedOutput() 453 if len(got) > outLimit { 454 panic(todo("", t.src, len(expected))) 455 } 456 } 457 eccTime = time.Since(t0) 458 if *oTrc2 { 459 switch { 460 case t.hasBinaryOutput: 461 fmt.Fprintf(os.Stderr, "%v: ecc binary for %s returned: %v bytes, err %v\n", time.Now(), baseName, binaryBytes2, err) 462 default: 463 fmt.Fprintf(os.Stderr, "%v: ecc binary for %s returned: err %v\n%s\n", time.Now(), baseName, err, got) 464 } 465 } 466 if err != nil { 467 rc := err.(*exec.ExitError).ProcessState.ExitCode() 468 if rc != expectRC { 469 return nil, fmt.Errorf("executing ecc binary %v %v: %v (rc %v, expected %v)\n%s", binary, args, err, rc, expectRC, got), ccTime, eccTime 470 } 471 472 err = nil 473 } 474 475 if *oTrco { 476 switch { 477 case t.hasBinaryOutput: 478 fmt.Fprintf(os.Stderr, "%v %q: %d bytes\n", eccTime, args, binaryBytes2) 479 default: 480 fmt.Fprintf(os.Stderr, "%v %q: %s\n", eccTime, args, got) 481 } 482 } 483 switch { 484 case t.hasBinaryOutput: 485 if err := fileEqual(eccOut, ccOut); err != nil { 486 return nil, fmt.Errorf("binary output: %s", err), ccTime, eccTime 487 } 488 default: 489 got := string(got) 490 expected := string(expected) 491 got = strings.ReplaceAll(got, "\r", "") 492 got = lineTrim(strings.TrimSpace(got)) 493 expected = strings.ReplaceAll(expected, "\r", "") 494 expected = lineTrim(strings.TrimSpace(expected)) 495 if got != expected { 496 diff := difflib.UnifiedDiff{ 497 A: difflib.SplitLines(expected), 498 B: difflib.SplitLines(got), 499 FromFile: "expected", 500 ToFile: "got", 501 Context: 3, 502 } 503 text, _ := difflib.GetUnifiedDiffString(diff) 504 return nil, fmt.Errorf( 505 "%v: text output differs:\n%s\n---- x.c\ngot\n%s\nexp\n%s\ngot\n%s\nexp\n%s", 506 t.src, text, 507 hex.Dump([]byte(got)), hex.Dump([]byte(expected)), 508 got, expected, 509 ), ccTime, eccTime 510 } 511 } 512 } 513 return got, err, ccTime, eccTime 514 } 515 516 func (t *runTask) run0CSmith() (_ []byte, err error, ccTime, eccTime time.Duration) { 517 timeLimit := 10 * time.Second 518 const outLimit = 1 << 16 519 defer func() { 520 if e := recover(); e != nil { 521 switch { 522 case err == nil: 523 err = fmt.Errorf("PANIC: %v\n%s", e, debug.Stack()) 524 default: 525 err = fmt.Errorf("%v\nPANIC: %v\n%s", err, e, debug.Stack()) 526 } 527 } 528 }() 529 530 baseName := filepath.Base(t.src) 531 ccArgs := append([]string(nil), t.opts...) 532 ok := true 533 for _, v := range t.opts { 534 if strings.HasPrefix(v, "-O") { 535 ok = false 536 break 537 } 538 } 539 if ok { 540 if o := *oO; o >= 0 { 541 ccArgs = append(ccArgs, fmt.Sprintf("-O%d", o)) 542 } 543 } 544 binary, err := makeCCBinary(baseName, t.doNotExec, ccArgs...) 545 if err != nil { 546 return nil, skipErr(err.Error()), ccTime, eccTime 547 } 548 549 const ( 550 ccOut = "cc.out" 551 eccOut = "ecc.out" 552 ) 553 var binaryBytes, binaryBytes2 int 554 var expected []byte 555 ctx, cancel := context.WithTimeout(context.Background(), timeLimit) 556 defer cancel() 557 t0 := time.Now() 558 if *oTrc2 { 559 fmt.Fprintf(os.Stderr, "%v: started CC binary for %s: %v\n", t0, baseName, binary) 560 } 561 switch { 562 case t.hasBinaryOutput: 563 binaryBytes, err = execute(ctx, binary, ccOut, nil) 564 defer os.Remove(ccOut) 565 default: 566 expected, err = exec.CommandContext(ctx, binary).CombinedOutput() 567 if len(expected) > outLimit { 568 panic(todo("", t.src, len(expected))) 569 } 570 } 571 ccTime = time.Since(t0) 572 if *oTrc2 { 573 switch { 574 case t.hasBinaryOutput: 575 fmt.Fprintf(os.Stderr, "%v: CC binary for %s returned: %v bytes, err %v\n", time.Now(), baseName, binaryBytes, err) 576 default: 577 fmt.Fprintf(os.Stderr, "%v: CC binary for %s returned: err %v\n%s\n", time.Now(), baseName, err, expected) 578 } 579 } 580 if err != nil { 581 return nil, skipErr(fmt.Sprintf("executing CC binary %v: %v\n%s", binary, err, expected)), ccTime, eccTime 582 } 583 584 if *oTrco { 585 fmt.Fprintf(os.Stderr, "%v: %s\n", ccTime, expected) 586 } 587 588 if err := os.Remove(binary); err != nil { 589 return nil, fmt.Errorf("removing %v: %v", binary, err), ccTime, eccTime 590 } 591 592 eccArgs := append([]string(nil), t.opts...) 593 ok = true 594 for _, v := range t.opts { 595 if strings.HasPrefix(v, "-O") { 596 ok = false 597 break 598 } 599 } 600 if ok { 601 if o := *oO; o >= 0 { 602 eccArgs = append(eccArgs, fmt.Sprintf("-O%d", o)) 603 } 604 } 605 if *oFullPaths { 606 eccArgs = append(eccArgs, "-full-paths") 607 } 608 if *oKeepTmp { 609 eccArgs = append(eccArgs, "-keep-tmp") 610 } 611 if binary, err = makeBinary(t.src, t.doNotExec, eccArgs...); err != nil { 612 return nil, err, ccTime, eccTime 613 } 614 615 var got []byte 616 ctx, cancel = context.WithTimeout(context.Background(), timeLimit) 617 defer cancel() 618 t0 = time.Now() 619 if *oTrc2 { 620 fmt.Fprintf(os.Stderr, "%v: started ecc binary for %s: %v\n", t0, baseName, binary) 621 } 622 got, err = exec.CommandContext(ctx, binary).CombinedOutput() 623 if len(got) > outLimit { 624 panic(todo("", t.src, len(expected))) 625 } 626 eccTime = time.Since(t0) 627 if *oTrc2 { 628 switch { 629 case t.hasBinaryOutput: 630 fmt.Fprintf(os.Stderr, "%v: ecc binary for %s returned: %v bytes, err %v\n", time.Now(), baseName, binaryBytes2, err) 631 default: 632 fmt.Fprintf(os.Stderr, "%v: ecc binary for %s returned: err %v\n%s\n", time.Now(), baseName, err, got) 633 } 634 } 635 if err != nil { 636 return nil, fmt.Errorf("executing ecc binary %v: %v\n%s", binary, err, got), ccTime, eccTime 637 } 638 639 if *oTrco { 640 fmt.Fprintf(os.Stderr, "%v: %s\n", eccTime, got) 641 } 642 { 643 got := string(got) 644 expected := string(expected) 645 got = strings.ReplaceAll(got, "\r", "") 646 got = lineTrim(strings.TrimSpace(got)) 647 expected = strings.ReplaceAll(expected, "\r", "") 648 expected = lineTrim(strings.TrimSpace(expected)) 649 if got != expected { 650 diff := difflib.UnifiedDiff{ 651 A: difflib.SplitLines(expected), 652 B: difflib.SplitLines(got), 653 FromFile: "expected", 654 ToFile: "got", 655 Context: 3, 656 } 657 text, _ := difflib.GetUnifiedDiffString(diff) 658 return nil, fmt.Errorf( 659 "%v: text output differs:\n%s\n---- x.c\ngot\n%s\nexp\n%s\ngot\n%s\nexp\n%s", 660 t.src, text, 661 hex.Dump([]byte(got)), hex.Dump([]byte(expected)), 662 got, expected, 663 ), ccTime, eccTime 664 } 665 } 666 return got, err, ccTime, eccTime 667 } 668 669 func fileEqual(g, e string) error { 670 fig, err := os.Stat(g) 671 if err != nil { 672 return err 673 } 674 675 fie, err := os.Stat(e) 676 if err != nil { 677 return err 678 } 679 680 if g, e := fig.Size(), fie.Size(); g != e { 681 return fmt.Errorf("files sizes differ, got %v, expected %v", g, e) 682 } 683 684 rem := fig.Size() 685 if rem == 0 { 686 return nil 687 } 688 689 var bg, be [4096]byte 690 fg, err := os.Open(g) 691 if err != nil { 692 return err 693 } 694 695 defer fg.Close() 696 697 fe, err := os.Open(e) 698 if err != nil { 699 return err 700 } 701 702 defer fe.Close() 703 704 for rem != 0 { 705 n, err := io.ReadFull(fg, bg[:]) 706 if n == 0 { 707 if err == io.EOF { 708 err = nil 709 } 710 return err 711 } 712 713 n2, err := io.ReadFull(fe, be[:]) 714 if n == 0 { 715 if err == io.EOF { 716 err = nil 717 } 718 return err 719 } 720 721 if n != n2 { 722 panic(todo("", n, n2)) 723 } 724 725 if !bytes.Equal(bg[:n], be[:n]) { 726 return fmt.Errorf("files are different") 727 } 728 729 rem -= int64(n) 730 } 731 return nil 732 } 733 734 type countingWriter struct { 735 written int 736 w *bufio.Writer 737 } 738 739 func (c *countingWriter) Write(b []byte) (int, error) { 740 n, err := c.w.Write(b) 741 c.written += n 742 return n, err 743 } 744 745 var _ io.Writer = (*countingWriter)(nil) 746 747 // err = execute(ctx, executable, args, ccOut) 748 func execute(ctx context.Context, executable, out string, args []string) (n int, err error) { 749 cmd := exec.CommandContext(ctx, executable, args...) 750 f, err := os.Create(out) 751 if err != nil { 752 return 0, err 753 } 754 755 defer func() { 756 if e := f.Close(); e != nil && err == nil { 757 err = e 758 } 759 }() 760 761 w := &countingWriter{w: bufio.NewWriter(f)} 762 763 defer func() { 764 if e := w.w.Flush(); e != nil && err == nil { 765 err = e 766 } 767 }() 768 769 cmd.Stdout = w 770 err = cmd.Run() 771 return w.written, err 772 } 773 774 func run(src string, binaryOut, ccCanFail, doNotExec bool, c chan *runResult, opts ...string) { 775 (&runTask{ 776 c: c, 777 ccCanFail: ccCanFail, 778 doNotExec: doNotExec, 779 hasBinaryOutput: binaryOut, 780 opts: opts, 781 src: src, 782 }).run() 783 } 784 785 func makeCCBinary(src string, obj bool, args ...string) (executable string, err error) { 786 ext := "" 787 if obj { 788 ext = ".o" 789 } 790 src = filepath.Base(src) 791 executable = "./" + src[:len(src)-len(filepath.Ext(src))] 792 if runtime.GOOS == "windows" && !obj { 793 ext = ".exe" 794 } 795 executable += ext 796 os.Remove(executable) 797 b, err := exec.Command(systemCC, append([]string{"-o", executable, src}, args...)...).CombinedOutput() 798 if err != nil { 799 return "", fmt.Errorf("%v %v -o %v %v: system C compiler: %v\n%s", systemCC, args, executable, src, err, b) 800 } 801 802 return executable, nil 803 } 804 805 func makeBinary(src string, obj bool, args ...string) (executable string, err error) { 806 ext := "" 807 if obj { 808 ext = ".o" 809 } 810 src = filepath.Base(src) 811 executable = "./" + src[:len(src)-len(filepath.Ext(src))] 812 if runtime.GOOS == "windows" { 813 ext = ".exe" 814 } 815 executable += ext 816 os.Remove(executable) 817 var out bytes.Buffer 818 task := NewTask("ecc", append([]string{"-o", executable, src}, args...), &out, &out) 819 if err := task.Main(); err != nil { 820 return "", fmt.Errorf("%v: ecc compiler: %v\n%s", src, err, out.Bytes()) 821 } 822 823 if b := out.Bytes(); len(b) != 0 { //TODO- 824 s := string(b) 825 s = strings.ReplaceAll(s, "‘", "'") 826 s = strings.ReplaceAll(s, "’", "'") 827 switch { 828 case 829 strings.Contains(s, "warning: 'return' with no value, in function returning non-void"), 830 strings.Contains(s, "warning: conflicting types for built-in function '__fprintf_chk'"), 831 strings.Contains(s, "warning: conflicting types for built-in function '__printf_chk'"), 832 strings.Contains(s, "warning: conflicting types for built-in function '__vfprintf_chk'"), 833 strings.Contains(s, "warning: conflicting types for built-in function '__vprintf_chk'"), 834 strings.Contains(s, "warning: conflicting types for built-in function 'cbrtl'"), 835 strings.Contains(s, "warning: conflicting types for built-in function 'memcmp'"), 836 strings.Contains(s, "warning: conflicting types for built-in function 'rintf'"), 837 strings.Contains(s, "warning: floating constant exceeds range of 'long double'"), 838 strings.Contains(s, "warning:") && strings.Contains(s, "may not be initialized"): 839 // ok 840 default: 841 fmt.Printf("WARNING %s\n", s) 842 } 843 } 844 return executable, nil 845 } 846 847 func getArgs(src string) (args []string, err error) { 848 src = src[:len(src)-len(filepath.Ext(src))] + ".arg" 849 overlay := filepath.Join(overlayDir, src) 850 b, err := ioutil.ReadFile(overlay) 851 if err != nil { 852 if !os.IsNotExist(err) { 853 return nil, err 854 } 855 856 f, err := fs.Open(src) 857 if err != nil { 858 return nil, nil 859 } 860 861 if b, err = ioutil.ReadAll(f); err != nil { 862 return nil, err 863 } 864 865 if err = f.Close(); err != nil { 866 return nil, err 867 } 868 } 869 870 a := strings.Split(strings.TrimSpace(string(b)), "\n") 871 for _, v := range a { 872 switch { 873 case strings.HasPrefix(v, "\"") || strings.HasPrefix(v, "`"): 874 w, err := strconv.Unquote(v) 875 if err != nil { 876 return nil, fmt.Errorf("%s: %v: %v", src, v, err) 877 } 878 879 args = append(args, w) 880 default: 881 args = append(args, v) 882 } 883 } 884 return args, nil 885 } 886 887 func lineTrim(s string) string { 888 a := strings.Split(s, "\n") 889 for i, v := range a { 890 a[i] = strings.TrimSpace(v) 891 } 892 return strings.Join(a, "\n") 893 } 894 895 func walk(dir string, f func(pth string, fi os.FileInfo) error) error { 896 if !strings.HasSuffix(dir, "/") { 897 dir += "/" 898 } 899 root, err := fs.Open(dir) 900 if err != nil { 901 return err 902 } 903 904 fi, err := root.Stat() 905 if err != nil { 906 return err 907 } 908 909 if !fi.IsDir() { 910 return fmt.Errorf("%s: not a directory", fi.Name()) 911 } 912 913 fis, err := root.Readdir(-1) 914 if err != nil { 915 return err 916 } 917 918 for _, v := range fis { 919 switch { 920 case v.IsDir(): 921 if err = walk(v.Name(), f); err != nil { 922 return err 923 } 924 default: 925 if err = f(v.Name(), v); err != nil { 926 return err 927 } 928 } 929 } 930 return nil 931 } 932 933 func TestTCC(t *testing.T) { 934 const root = "/tcc-0.9.27/tests/tests2" 935 mustEmptyDir(t, tempDir) 936 wd, err := os.Getwd() 937 if err != nil { 938 t.Fatal(err) 939 } 940 941 if err := os.Chdir(tempDir); err != nil { 942 t.Fatal(err) 943 } 944 945 defer func() { 946 if err := os.Chdir(wd); err != nil { 947 t.Fatal(err) 948 } 949 }() 950 951 needFiles(t, root, []string{ 952 "18_include.h", 953 "95_bitfields.c", 954 }) 955 blacklist := map[string]struct{}{ 956 "60_errors_and_warnings.c": {}, // no main 957 "73_arm64.c": {}, // does not work properly on any gcc tested (7-11) 958 "77_push_pop_macro.c": {}, // unsupported push/pop macro 959 "78_vla_label.c": {}, //MAYBE 960 "79_vla_continue.c": {}, //MAYBE 961 "80_flexarray.c": {}, //MAYBE 962 "83_utf8_in_identifiers.c": {}, // No support before gcc 10. 963 "85_asm-outside-function.c": {}, // asm 964 "90_struct-init.c": {}, // 90_struct-init.c:168:25: `...`: expected ] 965 "94_generic.c": {}, // 94_generic.c:36:18: `int`: expected primary-expression 966 "96_nodata_wanted.c": {}, // no main 967 "98_al_ax_extend.c": {}, // asm 968 "99_fastcall.c": {}, // asm 969 970 "95_bitfields_ms.c": {}, //TODO 971 } 972 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 973 blacklist["95_bitfields.c"] = struct{}{} //TODO 974 } 975 var rq, res, ok int 976 limit := runtime.GOMAXPROCS(0) 977 limiter := make(chan struct{}, limit) 978 results := make(chan *runResult, limit) 979 failed := map[string]struct{}{} 980 err = walk(root, func(pth string, fi os.FileInfo) error { 981 if !strings.HasSuffix(pth, ".c") { 982 return nil 983 } 984 985 switch { 986 case re != nil: 987 if !re.MatchString(pth) { 988 return nil 989 } 990 default: 991 if _, ok := blacklist[filepath.Base(pth)]; ok { 992 return nil 993 } 994 } 995 996 more: 997 select { 998 case r := <-results: 999 res++ 1000 <-limiter 1001 switch r.err.(type) { 1002 case nil: 1003 ok++ 1004 delete(failed, r.name) 1005 case skipErr: 1006 delete(failed, r.name) 1007 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1008 default: 1009 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1010 } 1011 goto more 1012 case limiter <- struct{}{}: 1013 rq++ 1014 if *oTrc { 1015 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1016 } 1017 failed[pth] = struct{}{} 1018 go run(pth, false, false, false, results) 1019 } 1020 return nil 1021 }) 1022 if err != nil { 1023 t.Fatal(err) 1024 } 1025 for res != rq { 1026 r := <-results 1027 res++ 1028 <-limiter 1029 switch r.err.(type) { 1030 case nil: 1031 ok++ 1032 delete(failed, r.name) 1033 case skipErr: 1034 delete(failed, r.name) 1035 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1036 default: 1037 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1038 } 1039 } 1040 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1041 if len(failed) == 0 { 1042 return 1043 } 1044 1045 var a []string 1046 for k := range failed { 1047 a = append(a, k) 1048 } 1049 sort.Strings(a) 1050 for _, v := range a { 1051 t.Logf("FAIL %s", v) 1052 } 1053 } 1054 1055 func needFiles(t *testing.T, root string, a []string) { 1056 for _, v := range a { 1057 overlay := filepath.Join(overlayDir, filepath.FromSlash(root), v) 1058 b, err := ioutil.ReadFile(overlay) 1059 if err != nil { 1060 if !os.IsNotExist(err) { 1061 t.Fatal(err) 1062 } 1063 1064 f, err := fs.Open(path.Join(root, v)) 1065 if err != nil { 1066 t.Fatal(err) 1067 } 1068 1069 if b, err = ioutil.ReadAll(f); err != nil { 1070 t.Fatal(err) 1071 } 1072 1073 if err = f.Close(); err != nil { 1074 t.Fatal(err) 1075 } 1076 } 1077 if dir, _ := filepath.Split(v); dir != "" { 1078 if err := os.MkdirAll(dir, 0700); err != nil { 1079 t.Fatal(err) 1080 } 1081 } 1082 1083 if err := ioutil.WriteFile(v, b, 0600); err != nil { 1084 t.Fatal(err) 1085 } 1086 } 1087 } 1088 1089 func TestCCGo(t *testing.T) { 1090 const root = "/ccgo/bug" 1091 mustEmptyDir(t, tempDir) 1092 wd, err := os.Getwd() 1093 if err != nil { 1094 t.Fatal(err) 1095 } 1096 1097 if err := os.Chdir(tempDir); err != nil { 1098 t.Fatal(err) 1099 } 1100 1101 defer func() { 1102 if err := os.Chdir(wd); err != nil { 1103 t.Fatal(err) 1104 } 1105 }() 1106 1107 blacklist := map[string]struct{}{} 1108 var rq, res, ok int 1109 limit := runtime.GOMAXPROCS(0) 1110 limiter := make(chan struct{}, limit) 1111 results := make(chan *runResult, limit) 1112 failed := map[string]struct{}{} 1113 err = walk(root, func(pth string, fi os.FileInfo) error { 1114 if !strings.HasSuffix(pth, ".c") { 1115 return nil 1116 } 1117 1118 switch { 1119 case re != nil: 1120 if !re.MatchString(pth) { 1121 return nil 1122 } 1123 default: 1124 if _, ok := blacklist[filepath.Base(pth)]; ok { 1125 return nil 1126 } 1127 } 1128 1129 more: 1130 select { 1131 case r := <-results: 1132 res++ 1133 <-limiter 1134 switch r.err.(type) { 1135 case nil: 1136 ok++ 1137 delete(failed, r.name) 1138 case skipErr: 1139 delete(failed, r.name) 1140 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1141 default: 1142 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1143 } 1144 goto more 1145 case limiter <- struct{}{}: 1146 rq++ 1147 if *oTrc { 1148 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1149 } 1150 failed[pth] = struct{}{} 1151 go run(pth, false, false, false, results) 1152 } 1153 return nil 1154 }) 1155 if err != nil { 1156 t.Fatal(err) 1157 } 1158 for res != rq { 1159 r := <-results 1160 res++ 1161 <-limiter 1162 switch r.err.(type) { 1163 case nil: 1164 ok++ 1165 delete(failed, r.name) 1166 case skipErr: 1167 delete(failed, r.name) 1168 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1169 default: 1170 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1171 } 1172 } 1173 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1174 if len(failed) == 0 { 1175 return 1176 } 1177 1178 var a []string 1179 for k := range failed { 1180 a = append(a, k) 1181 } 1182 sort.Strings(a) 1183 for _, v := range a { 1184 t.Logf("FAIL %s", v) 1185 } 1186 } 1187 1188 func TestMirBenchmarks(t *testing.T) { 1189 const root = "/github.com/vnmakarov/mir/c-benchmarks" 1190 mustEmptyDir(t, tempDir) 1191 wd, err := os.Getwd() 1192 if err != nil { 1193 t.Fatal(err) 1194 } 1195 1196 if err := os.Chdir(tempDir); err != nil { 1197 t.Fatal(err) 1198 } 1199 1200 defer func() { 1201 if err := os.Chdir(wd); err != nil { 1202 t.Fatal(err) 1203 } 1204 }() 1205 1206 needFiles(t, root, []string{ 1207 "simple_hash.h", 1208 }) 1209 blacklist := map[string]struct{}{} 1210 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 1211 blacklist["except.c"] = struct{}{} //TODO 1212 } 1213 binary := map[string]bool{ 1214 "mandelbrot.c": true, 1215 } 1216 var rq, res, ok int 1217 limit := runtime.GOMAXPROCS(0) 1218 limiter := make(chan struct{}, limit) 1219 results := make(chan *runResult, limit) 1220 failed := map[string]struct{}{} 1221 err = walk(root, func(pth string, fi os.FileInfo) error { 1222 if !strings.HasSuffix(pth, ".c") { 1223 return nil 1224 } 1225 1226 switch { 1227 case re != nil: 1228 if !re.MatchString(pth) { 1229 return nil 1230 } 1231 default: 1232 if _, ok := blacklist[filepath.Base(pth)]; ok { 1233 return nil 1234 } 1235 } 1236 1237 more: 1238 select { 1239 case r := <-results: 1240 res++ 1241 <-limiter 1242 switch r.err.(type) { 1243 case nil: 1244 ok++ 1245 delete(failed, r.name) 1246 case skipErr: 1247 delete(failed, r.name) 1248 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1249 default: 1250 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1251 } 1252 goto more 1253 case limiter <- struct{}{}: 1254 rq++ 1255 if *oTrc { 1256 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1257 } 1258 failed[pth] = struct{}{} 1259 go run(pth, binary[filepath.Base(pth)], false, false, results) 1260 } 1261 return nil 1262 }) 1263 if err != nil { 1264 t.Fatal(err) 1265 } 1266 for res != rq { 1267 r := <-results 1268 res++ 1269 <-limiter 1270 switch r.err.(type) { 1271 case nil: 1272 ok++ 1273 delete(failed, r.name) 1274 case skipErr: 1275 delete(failed, r.name) 1276 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1277 default: 1278 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1279 } 1280 } 1281 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1282 if len(failed) == 0 { 1283 return 1284 } 1285 1286 var a []string 1287 for k := range failed { 1288 a = append(a, k) 1289 } 1290 sort.Strings(a) 1291 for _, v := range a { 1292 t.Logf("FAIL %s", v) 1293 } 1294 } 1295 1296 func TestMirAndrewChambers(t *testing.T) { 1297 const root = "/github.com/vnmakarov/mir/c-tests/andrewchambers_c" 1298 mustEmptyDir(t, tempDir) 1299 wd, err := os.Getwd() 1300 if err != nil { 1301 t.Fatal(err) 1302 } 1303 1304 if err := os.Chdir(tempDir); err != nil { 1305 t.Fatal(err) 1306 } 1307 1308 defer func() { 1309 if err := os.Chdir(wd); err != nil { 1310 t.Fatal(err) 1311 } 1312 }() 1313 1314 blacklist := map[string]struct{}{} 1315 binary := map[string]bool{} 1316 var rq, res, ok int 1317 limit := runtime.GOMAXPROCS(0) 1318 limiter := make(chan struct{}, limit) 1319 results := make(chan *runResult, limit) 1320 failed := map[string]struct{}{} 1321 err = walk(root, func(pth string, fi os.FileInfo) error { 1322 if !strings.HasSuffix(pth, ".c") { 1323 return nil 1324 } 1325 1326 switch { 1327 case re != nil: 1328 if !re.MatchString(pth) { 1329 return nil 1330 } 1331 default: 1332 if _, ok := blacklist[filepath.Base(pth)]; ok { 1333 return nil 1334 } 1335 } 1336 1337 more: 1338 select { 1339 case r := <-results: 1340 res++ 1341 <-limiter 1342 switch r.err.(type) { 1343 case nil: 1344 ok++ 1345 delete(failed, r.name) 1346 case skipErr: 1347 delete(failed, r.name) 1348 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1349 default: 1350 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1351 } 1352 goto more 1353 case limiter <- struct{}{}: 1354 rq++ 1355 if *oTrc { 1356 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1357 } 1358 failed[pth] = struct{}{} 1359 go run(pth, binary[filepath.Base(pth)], false, false, results) 1360 } 1361 return nil 1362 }) 1363 if err != nil { 1364 t.Fatal(err) 1365 } 1366 for res != rq { 1367 r := <-results 1368 res++ 1369 <-limiter 1370 switch r.err.(type) { 1371 case nil: 1372 ok++ 1373 delete(failed, r.name) 1374 case skipErr: 1375 delete(failed, r.name) 1376 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1377 default: 1378 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1379 } 1380 } 1381 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1382 if len(failed) == 0 { 1383 return 1384 } 1385 1386 var a []string 1387 for k := range failed { 1388 a = append(a, k) 1389 } 1390 sort.Strings(a) 1391 for _, v := range a { 1392 t.Logf("FAIL %s", v) 1393 } 1394 } 1395 1396 func TestMirLacc(t *testing.T) { 1397 const root = "/github.com/vnmakarov/mir/c-tests/lacc" 1398 mustEmptyDir(t, tempDir) 1399 wd, err := os.Getwd() 1400 if err != nil { 1401 t.Fatal(err) 1402 } 1403 1404 if err := os.Chdir(tempDir); err != nil { 1405 t.Fatal(err) 1406 } 1407 1408 defer func() { 1409 if err := os.Chdir(wd); err != nil { 1410 t.Fatal(err) 1411 } 1412 }() 1413 1414 needFiles(t, root, []string{ 1415 "hello.c", 1416 "header.h", 1417 }) 1418 blacklist := map[string]struct{}{ 1419 "function-incomplete.c": {}, // Calls int foo(char*) without argument, no intent to support. 1420 1421 "macro-repeat-expand.c": {}, //TODO 1422 "pointer-immediate.c": {}, //TODO 1423 "string-addr.c": {}, //TODO 1424 "string-conversion.c": {}, //TODO 1425 "strings.c": {}, //TODO 1426 } 1427 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 1428 blacklist["assignment-type.c"] = struct{}{} //TODO 1429 blacklist["bitfield-basic.c"] = struct{}{} //TODO 1430 blacklist["bitfield-load.c"] = struct{}{} //TODO 1431 blacklist["bitfield-pack-next.c"] = struct{}{} //TODO 1432 blacklist["bitfield-packing.c"] = struct{}{} //TODO 1433 blacklist["bitfield-types-init.c"] = struct{}{} //TODO 1434 blacklist["bitfield-types.c"] = struct{}{} //TODO 1435 blacklist["cast-immediate-truncate.c"] = struct{}{} //TODO 1436 blacklist["comment.c"] = struct{}{} //TODO 1437 blacklist["convert-unsigned-float.c"] = struct{}{} //TODO 1438 blacklist["function-char-args.c"] = struct{}{} //TODO 1439 blacklist["return-bitfield.c"] = struct{}{} //TODO 1440 blacklist["stringify.c"] = struct{}{} //TODO 1441 blacklist["struct-comma-call.c"] = struct{}{} //TODO 1442 blacklist["token.c"] = struct{}{} //TODO 1443 blacklist["union-bitfield.c"] = struct{}{} //TODO 1444 } 1445 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 1446 blacklist["bitfield-basic.c"] = struct{}{} //TODO 1447 blacklist["bitfield-pack-next.c"] = struct{}{} //TODO 1448 blacklist["bitfield-trailing-zero.c"] = struct{}{} //TODO 1449 blacklist["bitfield-types-init.c"] = struct{}{} //TODO 1450 blacklist["constant-expression.c"] = struct{}{} //TODO 1451 blacklist["ptrdiff.c"] = struct{}{} //TODO 1452 blacklist["signed-division.c"] = struct{}{} //TODO 1453 } 1454 if runtime.GOOS == "linux" && runtime.GOARCH == "386" { 1455 blacklist["bitfield-pack-next.c"] = struct{}{} //TODO 1456 blacklist["bitfield-types-init.c"] = struct{}{} //TODO 1457 } 1458 if runtime.GOOS == "linux" && runtime.GOARCH == "arm" { 1459 blacklist["assignment-type.c"] = struct{}{} //TODO 1460 blacklist["bitfield-basic.c"] = struct{}{} //TODO 1461 blacklist["bitfield-trailing-zero.c"] = struct{}{} //TODO 1462 blacklist["bitfield-types-init.c"] = struct{}{} //TODO 1463 blacklist["cast-immediate-truncate.c"] = struct{}{} //TODO 1464 blacklist["function-char-args.c"] = struct{}{} //TODO 1465 blacklist["stringify.c"] = struct{}{} //TODO 1466 } 1467 if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" { 1468 blacklist["assignment-type.c"] = struct{}{} //TODO 1469 blacklist["bitfield-basic.c"] = struct{}{} //TODO 1470 blacklist["bitfield-trailing-zero.c"] = struct{}{} //TODO 1471 blacklist["bitfield-types-init.c"] = struct{}{} //TODO 1472 blacklist["cast-immediate-truncate.c"] = struct{}{} //TODO 1473 blacklist["function-char-args.c"] = struct{}{} //TODO 1474 blacklist["stringify.c"] = struct{}{} //TODO 1475 } 1476 binary := map[string]bool{} 1477 var rq, res, ok int 1478 limit := runtime.GOMAXPROCS(0) 1479 limiter := make(chan struct{}, limit) 1480 results := make(chan *runResult, limit) 1481 failed := map[string]struct{}{} 1482 err = walk(root, func(pth string, fi os.FileInfo) error { 1483 if !strings.HasSuffix(pth, ".c") { 1484 return nil 1485 } 1486 1487 switch { 1488 case re != nil: 1489 if !re.MatchString(pth) { 1490 return nil 1491 } 1492 default: 1493 if _, ok := blacklist[filepath.Base(pth)]; ok { 1494 return nil 1495 } 1496 } 1497 1498 more: 1499 select { 1500 case r := <-results: 1501 res++ 1502 <-limiter 1503 switch r.err.(type) { 1504 case nil: 1505 ok++ 1506 delete(failed, r.name) 1507 case skipErr: 1508 delete(failed, r.name) 1509 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1510 default: 1511 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1512 } 1513 goto more 1514 case limiter <- struct{}{}: 1515 rq++ 1516 if *oTrc { 1517 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1518 } 1519 failed[pth] = struct{}{} 1520 go run(pth, binary[filepath.Base(pth)], false, false, results, "-trigraphs") // comment.c needs trigraphs 1521 } 1522 return nil 1523 }) 1524 if err != nil { 1525 t.Fatal(err) 1526 } 1527 for res != rq { 1528 r := <-results 1529 res++ 1530 <-limiter 1531 switch r.err.(type) { 1532 case nil: 1533 ok++ 1534 delete(failed, r.name) 1535 case skipErr: 1536 delete(failed, r.name) 1537 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1538 default: 1539 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1540 } 1541 } 1542 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1543 if len(failed) == 0 { 1544 return 1545 } 1546 1547 var a []string 1548 for k := range failed { 1549 a = append(a, k) 1550 } 1551 sort.Strings(a) 1552 for _, v := range a { 1553 t.Logf("FAIL %s", v) 1554 } 1555 } 1556 1557 func TestMirNew(t *testing.T) { 1558 const root = "/github.com/vnmakarov/mir/c-tests/new" 1559 mustEmptyDir(t, tempDir) 1560 wd, err := os.Getwd() 1561 if err != nil { 1562 t.Fatal(err) 1563 } 1564 1565 if err := os.Chdir(tempDir); err != nil { 1566 t.Fatal(err) 1567 } 1568 1569 defer func() { 1570 if err := os.Chdir(wd); err != nil { 1571 t.Fatal(err) 1572 } 1573 }() 1574 1575 blacklist := map[string]struct{}{ 1576 // 1: /github.com/vnmakarov/mir/c-tests/new/endif.c 1577 // all_test.go:1045: /github.com/vnmakarov/mir/c-tests/new/endif.c: /usr/bin/gcc: system C compiler: exit status 1 1578 // endif.c:1:2: error: #endif without #if 1579 // #endif 1580 // ^~~~~ 1581 "endif.c": {}, // No intent to support. 1582 1583 // 1: /github.com/vnmakarov/mir/c-tests/new/fermian-2.c 1584 // all_test.go:1051: /github.com/vnmakarov/mir/c-tests/new/fermian-2.c: /usr/bin/gcc: system C compiler: exit status 1 1585 // fermian-2.c:1:3: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token 1586 // a { 1587 // ^ 1588 "fermian-2.c": {}, // No intent to support. 1589 "fermian.c": {}, // No main. 1590 1591 "array-elem-addr-in-initializer.c": {}, //TODO 1592 "issue117.c": {}, //TODO 1593 "issue23.c": {}, //TODO 1594 } 1595 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 1596 blacklist["setjmp2.c"] = struct{}{} //TODO 1597 } 1598 binary := map[string]bool{} 1599 var rq, res, ok int 1600 limit := runtime.GOMAXPROCS(0) 1601 limiter := make(chan struct{}, limit) 1602 results := make(chan *runResult, limit) 1603 failed := map[string]struct{}{} 1604 err = walk(root, func(pth string, fi os.FileInfo) error { 1605 if !strings.HasSuffix(pth, ".c") { 1606 return nil 1607 } 1608 1609 switch { 1610 case re != nil: 1611 if !re.MatchString(pth) { 1612 return nil 1613 } 1614 default: 1615 if _, ok := blacklist[filepath.Base(pth)]; ok { 1616 return nil 1617 } 1618 } 1619 1620 more: 1621 select { 1622 case r := <-results: 1623 res++ 1624 <-limiter 1625 switch r.err.(type) { 1626 case nil: 1627 ok++ 1628 delete(failed, r.name) 1629 case skipErr: 1630 delete(failed, r.name) 1631 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1632 default: 1633 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1634 } 1635 goto more 1636 case limiter <- struct{}{}: 1637 rq++ 1638 if *oTrc { 1639 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1640 } 1641 failed[pth] = struct{}{} 1642 go run(pth, binary[filepath.Base(pth)], false, false, results) 1643 } 1644 return nil 1645 }) 1646 if err != nil { 1647 t.Fatal(err) 1648 } 1649 for res != rq { 1650 r := <-results 1651 res++ 1652 <-limiter 1653 switch r.err.(type) { 1654 case nil: 1655 ok++ 1656 delete(failed, r.name) 1657 case skipErr: 1658 delete(failed, r.name) 1659 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1660 default: 1661 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1662 } 1663 } 1664 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1665 if len(failed) == 0 { 1666 return 1667 } 1668 1669 var a []string 1670 for k := range failed { 1671 a = append(a, k) 1672 } 1673 sort.Strings(a) 1674 for _, v := range a { 1675 t.Logf("FAIL %s", v) 1676 } 1677 } 1678 1679 func TestCompCert(t *testing.T) { 1680 const root = "/github.com/AbsInt/CompCert/test/c/" 1681 mustEmptyDir(t, tempDir) 1682 wd, err := os.Getwd() 1683 if err != nil { 1684 t.Fatal(err) 1685 } 1686 1687 if err := os.Chdir(tempDir); err != nil { 1688 t.Fatal(err) 1689 } 1690 1691 defer func() { 1692 if err := os.Chdir(wd); err != nil { 1693 t.Fatal(err) 1694 } 1695 }() 1696 1697 needFiles(t, root, []string{ 1698 "Results/knucleotide-input.txt", 1699 "endian.h", 1700 }) 1701 blacklist := map[string]struct{}{} 1702 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 1703 blacklist["aes.c"] = struct{}{} //TODO 1704 } 1705 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 1706 blacklist["qsort.c"] = struct{}{} //TODO 1707 } 1708 binary := map[string]bool{ 1709 "mandelbrot.c": true, 1710 } 1711 var rq, res, ok int 1712 limit := runtime.GOMAXPROCS(0) 1713 limiter := make(chan struct{}, limit) 1714 results := make(chan *runResult, limit) 1715 failed := map[string]struct{}{} 1716 err = walk(root, func(pth string, fi os.FileInfo) error { 1717 if !strings.HasSuffix(pth, ".c") { 1718 return nil 1719 } 1720 1721 switch { 1722 case re != nil: 1723 if !re.MatchString(pth) { 1724 return nil 1725 } 1726 default: 1727 if _, ok := blacklist[filepath.Base(pth)]; ok { 1728 return nil 1729 } 1730 } 1731 1732 more: 1733 select { 1734 case r := <-results: 1735 res++ 1736 <-limiter 1737 switch r.err.(type) { 1738 case nil: 1739 ok++ 1740 delete(failed, r.name) 1741 case skipErr: 1742 delete(failed, r.name) 1743 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1744 default: 1745 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1746 } 1747 goto more 1748 case limiter <- struct{}{}: 1749 rq++ 1750 if *oTrc { 1751 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 1752 } 1753 failed[pth] = struct{}{} 1754 go run(pth, binary[filepath.Base(pth)], false, false, results) 1755 } 1756 return nil 1757 }) 1758 if err != nil { 1759 t.Fatal(err) 1760 } 1761 for res != rq { 1762 r := <-results 1763 res++ 1764 <-limiter 1765 switch r.err.(type) { 1766 case nil: 1767 ok++ 1768 delete(failed, r.name) 1769 case skipErr: 1770 delete(failed, r.name) 1771 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 1772 default: 1773 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 1774 } 1775 } 1776 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 1777 if len(failed) == 0 { 1778 return 1779 } 1780 1781 var a []string 1782 for k := range failed { 1783 a = append(a, k) 1784 } 1785 sort.Strings(a) 1786 for _, v := range a { 1787 t.Logf("FAIL %s", v) 1788 } 1789 } 1790 1791 func TestGCCExecute(t *testing.T) { 1792 const root = "/github.com/gcc-mirror/gcc/gcc/testsuite/gcc.c-torture/execute" 1793 mustEmptyDir(t, tempDir) 1794 wd, err := os.Getwd() 1795 if err != nil { 1796 t.Fatal(err) 1797 } 1798 1799 if err := os.Chdir(tempDir); err != nil { 1800 t.Fatal(err) 1801 } 1802 1803 defer func() { 1804 if err := os.Chdir(wd); err != nil { 1805 t.Fatal(err) 1806 } 1807 }() 1808 1809 // Prepare testdata 1810 needFiles(t, root, []string{ 1811 "20040709-2.c", 1812 }) 1813 blacklist := map[string]struct{}{ 1814 "eeprof-1.c": {}, // Requires -finstrument-functions 1815 "pr64242.c": {}, // Depends on specific stack corruption. 1816 1817 // assembler 1818 "20001009-2.c": {}, //TODO 1819 "20020107-1.c": {}, //TODO 1820 "20050203-1.c": {}, //TODO 1821 "20061031-1.c": {}, //TODO 1822 "20071211-1.c": {}, //TODO 1823 "20071220-1.c": {}, //TODO 1824 "20071220-2.c": {}, //TODO 1825 "20080122-1.c": {}, //TODO 1826 "960312-1.c": {}, //TODO 1827 "990130-1.c": {}, //TODO 1828 "990413-2.c": {}, //TODO 1829 "bitfld-5.c": {}, //TODO 1830 "pr38533.c": {}, //TODO 1831 "pr40022.c": {}, //TODO 1832 "pr40657.c": {}, //TODO 1833 "pr41239.c": {}, //TODO 1834 "pr43385.c": {}, //TODO 1835 "pr43560.c": {}, //TODO 1836 "pr44852.c": {}, //TODO 1837 "pr45695.c": {}, //TODO 1838 "pr46309.c": {}, //TODO 1839 "pr47925.c": {}, //TODO 1840 "pr49218.c": {}, //TODO 1841 "pr49279.c": {}, //TODO 1842 "pr49390.c": {}, //TODO 1843 "pr51581-1.c": {}, //TODO 1844 "pr51581-2.c": {}, //TODO 1845 "pr51877.c": {}, //TODO 1846 "pr51933.c": {}, //TODO 1847 "pr52286.c": {}, //TODO 1848 "pr56205.c": {}, //TODO 1849 "pr56866.c": {}, //TODO 1850 "pr56982.c": {}, //TODO 1851 "pr57344-1.c": {}, //TODO 1852 "pr57344-2.c": {}, //TODO 1853 "pr57344-3.c": {}, //TODO 1854 "pr57344-4.c": {}, //TODO 1855 "pr58277-1.c": {}, //TODO 1856 "pr58419.c": {}, //TODO 1857 "pr63641.c": {}, //TODO 1858 "pr65053-1.c": {}, //TODO 1859 "pr65053-2.c": {}, //TODO 1860 "pr65648.c": {}, //TODO 1861 "pr65956.c": {}, //TODO 1862 "pr68328.c": {}, //TODO 1863 "pr69320-2.c": {}, //TODO 1864 "pr69691.c": {}, //TODO 1865 "pr78438.c": {}, //TODO 1866 "pr78726.c": {}, //TODO 1867 "pr79354.c": {}, //TODO 1868 "pr79737-2.c": {}, //TODO 1869 "pr80421.c": {}, //TODO 1870 "pr81588.c": {}, //TODO 1871 "pr82954.c": {}, //TODO 1872 "pr84478.c": {}, //TODO 1873 "pr84524.c": {}, //TODO 1874 "pr85156.c": {}, //TODO 1875 "pr85756.c": {}, //TODO 1876 "pr88904.c": {}, //TODO 1877 "pr93945.c": {}, //TODO 1878 "pr94130.c": {}, //TODO 1879 "stkalign.c": {}, //TODO 1880 1881 // variable type size 1882 "20010209-1.c": {}, //TODO 1883 "20020412-1.c": {}, //TODO 1884 "20040308-1.c": {}, //TODO 1885 "20040411-1.c": {}, //TODO 1886 "20040423-1.c": {}, //TODO 1887 "20040811-1.c": {}, //TODO 1888 "20041218-2.c": {}, //TODO 1889 "20070919-1.c": {}, //TODO 1890 "920721-2.c": {}, //TODO 1891 "920929-1.c": {}, //TODO 1892 "970217-1.c": {}, //TODO 1893 "align-nest.c": {}, //TODO 1894 "pr22061-1.c": {}, //TODO 1895 "pr41935.c": {}, //TODO 1896 "pr43220.c": {}, //TODO 1897 "pr77767.c": {}, //TODO 1898 "pr82210.c": {}, //TODO 1899 "vla-dealloc-1.c": {}, //TODO 1900 1901 // vector 1902 "20050316-1.c": {}, //TODO 1903 "20050316-2.c": {}, //TODO 1904 "20050316-3.c": {}, //TODO 1905 "20050604-1.c": {}, //TODO 1906 "20050607-1.c": {}, //TODO 1907 "20060420-1.c": {}, //TODO 1908 "pr23135.c": {}, //TODO 1909 "pr53645-2.c": {}, //TODO 1910 "pr53645.c": {}, //TODO 1911 "pr60960.c": {}, //TODO 1912 "pr65427.c": {}, //TODO 1913 "pr70903.c": {}, //TODO 1914 "pr71626-1.c": {}, //TODO 1915 "pr71626-2.c": {}, //TODO 1916 "pr85169.c": {}, //TODO 1917 "pr85331.c": {}, //TODO 1918 "pr92618.c": {}, //TODO 1919 "pr94412.c": {}, //TODO 1920 "pr94524-1.c": {}, //TODO 1921 "pr94524-2.c": {}, //TODO 1922 "pr94591.c": {}, //TODO 1923 "scal-to-vec1.c": {}, //TODO 1924 "scal-to-vec2.c": {}, //TODO 1925 "scal-to-vec3.c": {}, //TODO 1926 "simd-1.c": {}, //TODO 1927 "simd-2.c": {}, //TODO 1928 "simd-4.c": {}, //TODO 1929 "simd-5.c": {}, //TODO 1930 "simd-6.c": {}, //TODO 1931 1932 // #pragma push_macro("_") 1933 "pushpop_macro.c": {}, //TODO 1934 1935 // __attribute__ ((alias("a"))) 1936 "alias-2.c": {}, //TODO 1937 "alias-3.c": {}, //TODO 1938 "alias-4.c": {}, //TODO 1939 1940 // assignment to expression with array type 1941 "pr64979.c": {}, //TODO 1942 1943 // argument 3 in call to function ‘__builtin_mul_overflow’ does not have pointer to integral type 1944 "pr64006.c": {}, //TODO 1945 "pr68381.c": {}, //TODO 1946 "pr71554.c": {}, //TODO 1947 "pr85095.c": {}, //TODO 1948 "pr89434.c": {}, //TODO 1949 "pr90311.c": {}, //TODO 1950 "pr91450-1.c": {}, //TODO 1951 "pr91450-2.c": {}, //TODO 1952 "pr91635.c": {}, //TODO 1953 "pr93494.c": {}, //TODO 1954 1955 // __builtin_va_arg_pack 1956 "va-arg-pack-1.c": {}, //TODO 1957 1958 // __complex__ types 1959 "20010605-2.c": {}, //TODO 1960 "20020227-1.c": {}, //TODO 1961 "20020411-1.c": {}, //TODO 1962 "20030910-1.c": {}, //TODO 1963 "20041124-1.c": {}, //TODO 1964 "20041201-1.c": {}, //TODO 1965 "20050121-1.c": {}, //TODO 1966 "20070614-1.c": {}, //TODO 1967 "960512-1.c": {}, //TODO 1968 "complex-1.c": {}, //TODO 1969 "complex-2.c": {}, //TODO 1970 "complex-4.c": {}, //TODO 1971 "complex-5.c": {}, //TODO 1972 "complex-6.c": {}, //TODO 1973 "complex-7.c": {}, //TODO 1974 "pr38151.c": {}, //TODO 1975 "pr38969.c": {}, //TODO 1976 "pr42248.c": {}, //TODO 1977 "pr49644.c": {}, //TODO 1978 "pr56837.c": {}, //TODO 1979 1980 // &&label or __label__ 1981 "20040302-1.c": {}, 1982 "20041214-1.c": {}, 1983 "20071210-1.c": {}, 1984 "920302-1.c": {}, 1985 "920415-1.c": {}, 1986 "920428-2.c": {}, 1987 "920501-4.c": {}, 1988 "920501-5.c": {}, 1989 "920501-7.c": {}, 1990 "920721-4.c": {}, 1991 "930406-1.c": {}, 1992 "980526-1.c": {}, 1993 "990208-1.c": {}, 1994 "comp-goto-1.c": {}, 1995 "comp-goto-2.c": {}, 1996 "pr24135.c": {}, 1997 "pr51447.c": {}, 1998 "pr70460.c": {}, 1999 "pr71494.c": {}, 2000 2001 // local func def 2002 "20000822-1.c": {}, 2003 "20010605-1.c": {}, 2004 "20030501-1.c": {}, 2005 "20040520-1.c": {}, 2006 "20061220-1.c": {}, 2007 "20090219-1.c": {}, 2008 "920612-2.c": {}, 2009 "921017-1.c": {}, 2010 "921215-1.c": {}, 2011 "931002-1.c": {}, 2012 "nest-align-1.c": {}, 2013 "nest-stdar-1.c": {}, 2014 "nestfunc-1.c": {}, 2015 "nestfunc-2.c": {}, 2016 "nestfunc-3.c": {}, 2017 "nestfunc-5.c": {}, 2018 "nestfunc-6.c": {}, 2019 "nestfunc-7.c": {}, 2020 "pr22061-3.c": {}, 2021 "pr22061-4.c": {}, 2022 2023 // goto * expr; 2024 "920501-3.c": {}, 2025 2026 // Flexible array member 2027 "20010924-1.c": {}, 2028 "20030109-1.c": {}, 2029 "20050613-1.c": {}, 2030 "pr28865.c": {}, 2031 "pr33382.c": {}, 2032 2033 // __builtin_classify_type 2034 "20040709-1.c": {}, 2035 "20040709-2.c": {}, 2036 "20040709-3.c": {}, 2037 2038 // LabeledStatementRange 2039 "pr34154.c": {}, 2040 2041 // __builtin_apply 2042 "pr47237.c": {}, 2043 2044 // 128 bit int/uint 2045 "pr54471.c": {}, 2046 "pr61375.c": {}, 2047 "pr63302.c": {}, 2048 "pr65170.c": {}, 2049 "pr84169.c": {}, 2050 "pr84748.c": {}, 2051 "pr85582-2.c": {}, 2052 "pr85582-3.c": {}, 2053 "pr92904.c": {}, 2054 "pr93213.c": {}, 2055 "pr98474.c": {}, 2056 2057 // _Decimal64 2058 "pr80692.c": {}, 2059 2060 "builtin-types-compatible-p.c": {}, //TODO 2061 "call-trap-1.c": {}, //TODO 2062 "pr70602.c": {}, //TODO 2063 "pr71700.c": {}, //TODO 2064 2065 "vfprintf-chk-1.c": {}, //TODO va_list (nuc_64 only) 2066 } 2067 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 2068 blacklist["20020201-1.c"] = struct{}{} //TODO 2069 blacklist["20020226-1.c"] = struct{}{} //TODO 2070 blacklist["20020508-1.c"] = struct{}{} //TODO 2071 blacklist["20020508-2.c"] = struct{}{} //TODO 2072 blacklist["20020508-3.c"] = struct{}{} //TODO 2073 blacklist["20020911-1.c"] = struct{}{} //TODO 2074 blacklist["20030128-1.c"] = struct{}{} //TODO 2075 blacklist["20050215-1.c"] = struct{}{} //TODO 2076 blacklist["20070724-1.c"] = struct{}{} //TODO 2077 blacklist["20180921-1.c"] = struct{}{} //TODO 2078 blacklist["bf-pack-1.c"] = struct{}{} //TODO 2079 blacklist["bitfld-6.c"] = struct{}{} //TODO 2080 blacklist["bitfld-7.c"] = struct{}{} //TODO 2081 blacklist["memchr-1.c"] = struct{}{} //TODO 2082 blacklist["memset-1.c"] = struct{}{} //TODO 2083 blacklist["memset-2.c"] = struct{}{} //TODO 2084 blacklist["memset-3.c"] = struct{}{} //TODO 2085 blacklist["packed-1.c"] = struct{}{} //TODO 2086 blacklist["pr19606.c"] = struct{}{} //TODO 2087 blacklist["pr23467.c"] = struct{}{} //TODO 2088 blacklist["pr29695-2.c"] = struct{}{} //TODO 2089 blacklist["pr40386.c"] = struct{}{} //TODO 2090 blacklist["pr42269-2.c"] = struct{}{} //TODO 2091 blacklist["pr43438.c"] = struct{}{} //TODO 2092 blacklist["pr44164.c"] = struct{}{} //TODO 2093 blacklist["pr58574.c"] = struct{}{} //TODO 2094 blacklist["pr77766.c"] = struct{}{} //TODO 2095 blacklist["pr81503.c"] = struct{}{} //TODO 2096 blacklist["pr81555.c"] = struct{}{} //TODO 2097 blacklist["pr83383.c"] = struct{}{} //TODO 2098 blacklist["pr94567.c"] = struct{}{} //TODO 2099 blacklist["pr98366.c"] = struct{}{} //TODO 2100 } 2101 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" { 2102 blacklist["pr44164.c"] = struct{}{} //TODO 2103 blacklist["pr98366.c"] = struct{}{} //TODO 2104 } 2105 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 2106 blacklist["20000519-1.c"] = struct{}{} //TODO va_list 2107 blacklist["20001108-1.c"] = struct{}{} //TODO 2108 blacklist["20071213-1.c"] = struct{}{} //TODO va_list 2109 blacklist["20101011-1.c"] = struct{}{} //TODO 2110 blacklist["930513-1.c"] = struct{}{} //TODO 2111 blacklist["950607-2.c"] = struct{}{} //TODO 2112 blacklist["960416-1.c"] = struct{}{} //TODO 2113 blacklist["fprintf-2.c"] = struct{}{} //TODO 2114 blacklist["fprintf-chk-1.c"] = struct{}{} //TODO va_list 2115 blacklist["loop-2f.c"] = struct{}{} //TODO 2116 blacklist["loop-2g.c"] = struct{}{} //TODO 2117 blacklist["multdi-1.c"] = struct{}{} //TODO 2118 blacklist["pr34456.c"] = struct{}{} //TODO 2119 blacklist["pr78622.c"] = struct{}{} //TODO 2120 blacklist["pr98366.c"] = struct{}{} //TODO 2121 blacklist["printf-2.c"] = struct{}{} //TODO 2122 blacklist["printf-chk-1.c"] = struct{}{} //TODO va_list 2123 blacklist["stdarg-1.c"] = struct{}{} //TODO va_list 2124 blacklist["stdarg-2.c"] = struct{}{} //TODO va_list 2125 blacklist["stdarg-4.c"] = struct{}{} //TODO va_list 2126 blacklist["user-printf.c"] = struct{}{} //TODO 2127 blacklist["va-arg-10.c"] = struct{}{} //TODO va_list 2128 blacklist["va-arg-13.c"] = struct{}{} //TODO 2129 blacklist["va-arg-14.c"] = struct{}{} //TODO va_list 2130 blacklist["va-arg-20.c"] = struct{}{} //TODO va_list 2131 blacklist["va-arg-21.c"] = struct{}{} //TODO 2132 blacklist["va-arg-9.c"] = struct{}{} //TODO va_list 2133 blacklist["vfprintf-1.c"] = struct{}{} //TODO va_list 2134 blacklist["vfprintf-chk-1.c"] = struct{}{} //TODO va_list 2135 blacklist["vprintf-1.c"] = struct{}{} //TODO va_list 2136 blacklist["vprintf-chk-1.c"] = struct{}{} //TODO va_list 2137 } 2138 if runtime.GOOS == "linux" && runtime.GOARCH == "386" { 2139 blacklist["20000519-1.c"] = struct{}{} //TODO va_list 2140 blacklist["20071213-1.c"] = struct{}{} //TODO va_list 2141 blacklist["960416-1.c"] = struct{}{} //TODO 2142 blacklist["960830-1.c"] = struct{}{} //TODO 2143 blacklist["floatunsisf-1.c"] = struct{}{} //TODO 2144 blacklist["fprintf-chk-1.c"] = struct{}{} //TODO va_list 2145 blacklist["pr23467.c"] = struct{}{} //TODO 2146 blacklist["pr97073.c"] = struct{}{} //TODO 2147 blacklist["pr98366.c"] = struct{}{} //TODO 2148 blacklist["printf-chk-1.c"] = struct{}{} //TODO va_list 2149 blacklist["stdarg-1.c"] = struct{}{} //TODO va_list 2150 blacklist["stdarg-2.c"] = struct{}{} //TODO va_list 2151 blacklist["stdarg-4.c"] = struct{}{} //TODO va_list 2152 blacklist["user-printf.c"] = struct{}{} //TODO va_list 2153 blacklist["va-arg-10.c"] = struct{}{} //TODO va_list 2154 blacklist["va-arg-13.c"] = struct{}{} //TODO 2155 blacklist["va-arg-14.c"] = struct{}{} //TODO va_list 2156 blacklist["va-arg-20.c"] = struct{}{} //TODO va_list 2157 blacklist["va-arg-21.c"] = struct{}{} //TODO 2158 blacklist["va-arg-9.c"] = struct{}{} //TODO va_list 2159 blacklist["vfprintf-1.c"] = struct{}{} //TODO va_list 2160 blacklist["vfprintf-chk-1.c"] = struct{}{} //TODO va_list 2161 blacklist["vprintf-1.c"] = struct{}{} //TODO va_list 2162 blacklist["vprintf-chk-1.c"] = struct{}{} //TODO va_list 2163 } 2164 if runtime.GOOS == "linux" && runtime.GOARCH == "arm" { 2165 blacklist["20000519-1.c"] = struct{}{} //TODO va_list 2166 blacklist["20071213-1.c"] = struct{}{} //TODO va_list 2167 blacklist["960416-1.c"] = struct{}{} //TODO 2168 blacklist["fprintf-chk-1.c"] = struct{}{} //TODO va_list 2169 blacklist["pr23467.c"] = struct{}{} //TODO 2170 blacklist["pr44164.c"] = struct{}{} //TODO 2171 blacklist["pr98366.c"] = struct{}{} //TODO 2172 blacklist["printf-chk-1.c"] = struct{}{} //TODO va_list 2173 blacklist["stdarg-1.c"] = struct{}{} //TODO va_list 2174 blacklist["stdarg-2.c"] = struct{}{} //TODO va_list 2175 blacklist["stdarg-4.c"] = struct{}{} //TODO va_list 2176 blacklist["strct-pack-1.c"] = struct{}{} //TODO 2177 blacklist["user-printf.c"] = struct{}{} //TODO va_list 2178 blacklist["va-arg-10.c"] = struct{}{} //TODO va_list 2179 blacklist["va-arg-13.c"] = struct{}{} //TODO 2180 blacklist["va-arg-14.c"] = struct{}{} //TODO va_list 2181 blacklist["va-arg-20.c"] = struct{}{} //TODO va_list 2182 blacklist["va-arg-21.c"] = struct{}{} //TODO 2183 blacklist["va-arg-9.c"] = struct{}{} //TODO va_list 2184 blacklist["vfprintf-1.c"] = struct{}{} //TODO va_list 2185 blacklist["vfprintf-chk-1.c"] = struct{}{} //TODO va_list 2186 blacklist["vprintf-1.c"] = struct{}{} //TODO va_list 2187 blacklist["vprintf-chk-1.c"] = struct{}{} //TODO va_list 2188 } 2189 if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" { 2190 blacklist["20000519-1.c"] = struct{}{} //TODO va_list 2191 blacklist["20071213-1.c"] = struct{}{} //TODO va_list 2192 blacklist["fprintf-chk-1.c"] = struct{}{} //TODO va_list 2193 blacklist["pr44164.c"] = struct{}{} //TODO 2194 blacklist["pr98366.c"] = struct{}{} //TODO 2195 blacklist["pr98681.c"] = struct{}{} //TODO 2196 blacklist["pr98853-2.c"] = struct{}{} //TODO 2197 blacklist["printf-chk-1.c"] = struct{}{} //TODO va_list 2198 blacklist["stdarg-1.c"] = struct{}{} //TODO va_list 2199 blacklist["stdarg-2.c"] = struct{}{} //TODO va_list 2200 blacklist["stdarg-4.c"] = struct{}{} //TODO va_list 2201 blacklist["user-printf.c"] = struct{}{} //TODO va_list 2202 blacklist["va-arg-10.c"] = struct{}{} //TODO va_list 2203 blacklist["va-arg-13.c"] = struct{}{} //TODO 2204 blacklist["va-arg-14.c"] = struct{}{} //TODO va_list 2205 blacklist["va-arg-20.c"] = struct{}{} //TODO va_list 2206 blacklist["va-arg-21.c"] = struct{}{} //TODO 2207 blacklist["va-arg-9.c"] = struct{}{} //TODO va_list 2208 blacklist["vfprintf-1.c"] = struct{}{} //TODO va_list 2209 blacklist["vfprintf-chk-1.c"] = struct{}{} //TODO 2210 blacklist["vprintf-1.c"] = struct{}{} //TODO va_list 2211 blacklist["vprintf-chk-1.c"] = struct{}{} //TODO va_list 2212 } 2213 binary := map[string]bool{} 2214 var rq, res, ok int 2215 limit := runtime.GOMAXPROCS(0) 2216 limiter := make(chan struct{}, limit) 2217 results := make(chan *runResult, limit) 2218 failed := map[string]struct{}{} 2219 err = walk(root, func(pth string, fi os.FileInfo) error { 2220 if strings.Contains(pth, "/ieee/") || !strings.HasSuffix(pth, ".c") { 2221 return nil 2222 } 2223 2224 switch { 2225 case re != nil: 2226 if !re.MatchString(pth) { 2227 return nil 2228 } 2229 default: 2230 if _, ok := blacklist[filepath.Base(pth)]; ok { 2231 return nil 2232 } 2233 } 2234 2235 more: 2236 select { 2237 case r := <-results: 2238 res++ 2239 <-limiter 2240 switch r.err.(type) { 2241 case nil: 2242 ok++ 2243 delete(failed, r.name) 2244 case skipErr: 2245 delete(failed, r.name) 2246 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2247 default: 2248 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2249 } 2250 goto more 2251 case limiter <- struct{}{}: 2252 rq++ 2253 if *oTrc { 2254 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 2255 } 2256 base := filepath.Base(pth) 2257 var opts []string 2258 switch base { 2259 case 2260 "20010122-1.c", //TODO 2261 "20101011-1.c", //TODO 2262 "pr44164.c", //TODO 2263 "pr97386-1.c", //TODO 2264 "pr97386-2.c", //TODO 2265 "pr98366.c": //TODO 2266 2267 opts = []string{"-O0"} 2268 } 2269 failed[pth] = struct{}{} 2270 go run(pth, binary[base], true, false, results, opts...) 2271 } 2272 return nil 2273 }) 2274 if err != nil { 2275 t.Fatal(err) 2276 } 2277 for res != rq { 2278 r := <-results 2279 res++ 2280 <-limiter 2281 switch r.err.(type) { 2282 case nil: 2283 ok++ 2284 delete(failed, r.name) 2285 case skipErr: 2286 delete(failed, r.name) 2287 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2288 default: 2289 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2290 } 2291 } 2292 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 2293 if len(failed) == 0 { 2294 return 2295 } 2296 2297 var a []string 2298 for k := range failed { 2299 a = append(a, k) 2300 } 2301 sort.Strings(a) 2302 for _, v := range a { 2303 t.Logf("FAIL %s", v) 2304 } 2305 } 2306 2307 func TestGCCExecuteIEEE(t *testing.T) { 2308 const root = "/github.com/gcc-mirror/gcc/gcc/testsuite/gcc.c-torture/execute/ieee" 2309 mustEmptyDir(t, tempDir) 2310 wd, err := os.Getwd() 2311 if err != nil { 2312 t.Fatal(err) 2313 } 2314 2315 if err := os.Chdir(tempDir); err != nil { 2316 t.Fatal(err) 2317 } 2318 2319 defer func() { 2320 if err := os.Chdir(wd); err != nil { 2321 t.Fatal(err) 2322 } 2323 }() 2324 2325 blacklist := map[string]struct{}{ 2326 "builtin-nan-1.c": {}, //TODO 2327 "copysign1.c": {}, //TODO 2328 "copysign2.c": {}, //TODO 2329 "fp-cmp-3.c": {}, //TODO 2330 "fp-cmp-4l.c": {}, //TODO 2331 "fp-cmp-8l.c": {}, //TODO 2332 "pr50310.c": {}, //TODO 2333 "pr72824-2.c": {}, //TODO 2334 } 2335 if runtime.GOOS == "linux" && runtime.GOARCH == "386" { 2336 blacklist["20030331-1.c"] = struct{}{} //TODO 2337 blacklist["pr67218.c"] = struct{}{} //TODO 2338 } 2339 binary := map[string]bool{} 2340 var rq, res, ok int 2341 limit := runtime.GOMAXPROCS(0) 2342 limiter := make(chan struct{}, limit) 2343 results := make(chan *runResult, limit) 2344 failed := map[string]struct{}{} 2345 err = walk(root, func(pth string, fi os.FileInfo) error { 2346 if !strings.HasSuffix(pth, ".c") { 2347 return nil 2348 } 2349 2350 switch { 2351 case re != nil: 2352 if !re.MatchString(pth) { 2353 return nil 2354 } 2355 default: 2356 if _, ok := blacklist[filepath.Base(pth)]; ok { 2357 return nil 2358 } 2359 } 2360 2361 more: 2362 select { 2363 case r := <-results: 2364 res++ 2365 <-limiter 2366 switch r.err.(type) { 2367 case nil: 2368 ok++ 2369 delete(failed, r.name) 2370 case skipErr: 2371 delete(failed, r.name) 2372 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2373 default: 2374 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2375 } 2376 goto more 2377 case limiter <- struct{}{}: 2378 rq++ 2379 if *oTrc { 2380 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 2381 } 2382 failed[pth] = struct{}{} 2383 go run(pth, binary[filepath.Base(pth)], true, false, results) 2384 } 2385 return nil 2386 }) 2387 if err != nil { 2388 t.Fatal(err) 2389 } 2390 for res != rq { 2391 r := <-results 2392 res++ 2393 <-limiter 2394 switch r.err.(type) { 2395 case nil: 2396 ok++ 2397 delete(failed, r.name) 2398 case skipErr: 2399 delete(failed, r.name) 2400 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2401 default: 2402 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2403 } 2404 } 2405 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 2406 if len(failed) == 0 { 2407 return 2408 } 2409 2410 var a []string 2411 for k := range failed { 2412 a = append(a, k) 2413 } 2414 sort.Strings(a) 2415 for _, v := range a { 2416 t.Logf("FAIL %s", v) 2417 } 2418 } 2419 2420 var installOnce sync.Once 2421 2422 func installEcc(t *testing.T) bool { 2423 if !*oInstall && os.Getenv("INSTALL_ECC") != "1" { 2424 return false 2425 } 2426 2427 var out []byte 2428 var err error 2429 installOnce.Do(func() { 2430 t.Log("installing binaries") 2431 out, err = ccgo.Shell("go", "install", "-v", "../...") 2432 s := os.Getenv("GOPATH") 2433 if s == "" { 2434 s = build.Default.GOPATH 2435 } 2436 s = filepath.Join(s, "bin") 2437 p := os.Getenv("PATH") 2438 if !strings.Contains(p, s) { 2439 p = s + string(os.PathListSeparator) + p 2440 t.Logf("setting PATH=%s", p) 2441 os.Setenv("PATH", p) 2442 } 2443 if os.Getenv("QBEC_CC") == "" { 2444 if s := os.Getenv("CC"); s == "" || s == "ecc" { 2445 t.Logf("setting QBEC_CC=gcc") 2446 os.Setenv("QBEC_CC", "gcc") 2447 } 2448 } 2449 }) 2450 if err != nil { 2451 t.Fatalf("%s\n%s", err, out) 2452 } 2453 2454 t.Logf("ecc %v installed", Version()) 2455 return true 2456 } 2457 2458 func TestZlib(t *testing.T) { 2459 if !installEcc(t) { 2460 t.Skip("set INSTALL_ECC=1 or add -install to execute this test") 2461 } 2462 2463 const root = "/github.com/madler/zlib.tar.gz" 2464 archive, err := fs.Open(root) 2465 if err != nil { 2466 t.Fatal(err) 2467 } 2468 2469 mustEmptyDir(t, tempDir) 2470 if err := ccgo.Untar(tempDir, archive, nil); err != nil { 2471 t.Fatal(err) 2472 } 2473 2474 if err := ccgo.InDir(filepath.Join(tempDir, "zlib"), func() error { 2475 switch { 2476 case 2477 runtime.GOOS == "darwin" && runtime.GOARCH == "amd64", 2478 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "386", 2479 runtime.GOOS == "linux" && runtime.GOARCH == "amd64", 2480 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "arm", 2481 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "arm64", 2482 runtime.GOOS == "linux" && runtime.GOARCH == "s390x": 2483 2484 out, err := ccgo.Shell("sh", "-c", "CC=ecc ./configure && make check") 2485 if err != nil || strings.Contains(string(out), "FAILED") { 2486 return errorf("err: %v\n%s", err, out) 2487 } 2488 default: 2489 // windows/amd64 2490 //TODO 2491 t.Skip("TODO") //TODO 2492 } 2493 2494 return nil 2495 }); err != nil { 2496 t.Fatal(err) 2497 } 2498 } 2499 2500 func TestBenchmarksGame(t *testing.T) { 2501 const root = "/benchmarksgame-team.pages.debian.net/" 2502 2503 if testing.Short() { 2504 t.Skip("skipped: -short") 2505 } 2506 2507 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { 2508 t.Skip("skipped: supported currently only on linux/amd64") //TODO 2509 } 2510 2511 mustEmptyDir(t, tempDir) 2512 wd, err := os.Getwd() 2513 if err != nil { 2514 t.Fatal(err) 2515 } 2516 2517 if err := os.Chdir(tempDir); err != nil { 2518 t.Fatal(err) 2519 } 2520 2521 defer func() { 2522 if err := os.Chdir(wd); err != nil { 2523 t.Fatal(err) 2524 } 2525 }() 2526 2527 // Prepare testdata 2528 needFiles(t, root, []string{ 2529 "Include/khash.h", 2530 "fasta.c", 2531 }) 2532 bin, err := makeCCBinary("fasta.c", false) 2533 if err != nil { 2534 t.Fatal(err) 2535 } 2536 2537 defer os.Remove(bin) 2538 2539 for _, size := range []int{5e6, 1e8, 25e6} { 2540 cmd := exec.Command(bin, fmt.Sprint(size)) 2541 fn := fmt.Sprintf("%d.txt", size) 2542 f, err := os.Create(fn) 2543 if err != nil { 2544 t.Fatal(err) 2545 } 2546 2547 w := bufio.NewWriter(f) 2548 cmd.Stdout = w 2549 if err := cmd.Run(); err != nil { 2550 t.Fatal(err) 2551 } 2552 2553 if err := w.Flush(); err != nil { 2554 t.Fatal(err) 2555 } 2556 2557 if err := f.Close(); err != nil { 2558 t.Fatal(err) 2559 } 2560 } 2561 2562 blacklist := map[string]struct{}{ 2563 "binary-trees-2.c": {}, //TODO 2564 "binary-trees-3.c": {}, //TODO 2565 "fannkuchredux-4.c": {}, //TODO 2566 "fannkuchredux-5.c": {}, //TODO 2567 "fannkuchredux.c": {}, //TODO 2568 "fasta-2.c": {}, //TODO 2569 "fasta-5.c": {}, //TODO 2570 "fasta-6.c": {}, //TODO 2571 "fasta-7.c": {}, //TODO 2572 "k-nucleotide.c": {}, //TODO 2573 "mandelbrot-3.c": {}, //TODO 2574 "mandelbrot-4.c": {}, //TODO 2575 "mandelbrot-6.c": {}, //TODO 2576 "mandelbrot-7.c": {}, //TODO 2577 "mandelbrot-8.c": {}, //TODO 2578 "mandelbrot-9.c": {}, //TODO 2579 "mandelbrot.c": {}, //TODO 2580 "nbody-4.c": {}, //TODO 2581 "nbody-5.c": {}, //TODO 2582 "nbody-8.c": {}, //TODO 2583 "nbody-9.c": {}, //TODO 2584 "pidigits-6.c": {}, //TODO 2585 "regex-redux-4.c": {}, //TODO 2586 "regex-redux-5.c": {}, //TODO 2587 "spectral-norm-4.c": {}, //TODO 2588 "spectral-norm-5.c": {}, //TODO 2589 "spectral-norm-6.c": {}, //TODO 2590 "spectral-norm.c": {}, //TODO 2591 } 2592 2593 m := map[string]*runResult{} 2594 var names []string 2595 collect := func(r *runResult) { 2596 nm := filepath.Base(r.name) 2597 ex := m[nm] 2598 if ex == nil { 2599 m[nm] = r 2600 names = append(names, nm) 2601 return 2602 } 2603 2604 if ex.ccTime > r.ccTime { 2605 ex.ccTime = r.ccTime 2606 } 2607 if ex.eccTime > r.eccTime { 2608 ex.eccTime = r.eccTime 2609 } 2610 } 2611 binary := map[string]bool{ 2612 "fasta-3.c": true, 2613 "fasta-4.c": true, 2614 "fasta-8.c": true, 2615 "fasta-9.c": true, 2616 "fasta.c": true, 2617 "mandelbrot-2.c": true, 2618 "mandelbrot-3.c": true, 2619 "mandelbrot-4.c": true, 2620 "mandelbrot-6.c": true, 2621 "mandelbrot-7.c": true, 2622 "mandelbrot-8.c": true, 2623 "mandelbrot-9.c": true, 2624 "mandelbrot.c": true, 2625 "reverse-complement-2.c": true, 2626 "reverse-complement-4.c": true, 2627 "reverse-complement-5.c": true, 2628 "reverse-complement-6.c": true, 2629 } 2630 var rq, res, ok int 2631 limit := 1 2632 limiter := make(chan struct{}, limit) 2633 results := make(chan *runResult, limit) 2634 err = walk(root, func(pth string, fi os.FileInfo) error { 2635 if !strings.HasSuffix(pth, ".c") { 2636 return nil 2637 } 2638 2639 switch { 2640 case re != nil: 2641 if !re.MatchString(pth) { 2642 return nil 2643 } 2644 2645 fallthrough 2646 default: 2647 if _, ok := blacklist[filepath.Base(pth)]; ok { 2648 return nil 2649 } 2650 } 2651 2652 for i := 0; i < *oBestOf; i++ { 2653 more: 2654 select { 2655 case r := <-results: 2656 res++ 2657 <-limiter 2658 switch r.err.(type) { 2659 case nil: 2660 ok++ 2661 collect(r) 2662 case skipErr: 2663 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2664 default: 2665 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2666 } 2667 goto more 2668 case limiter <- struct{}{}: 2669 rq++ 2670 if *oTrc { 2671 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 2672 } 2673 opts := []string{ 2674 "-D_GNU_SOURCE", 2675 "-I/usr/include/apr-1.0", 2676 "-IInclude", 2677 "-lapr-1", 2678 "-lgmp", 2679 "-lm", 2680 "-lpcre", 2681 "-lpcre2-8", 2682 "-pthread", 2683 fmt.Sprintf("-O%d", *oBenchO), 2684 } 2685 if s := *oMarch; s != "" { 2686 opts = append(opts, fmt.Sprintf("-march=%s", s)) 2687 } 2688 if s := *oMtune; s != "" { 2689 opts = append(opts, fmt.Sprintf("-mtune=%s", s)) 2690 } 2691 if *oOpenmp { 2692 opts = append(opts, "-fopenmp") 2693 } 2694 base := filepath.Base(pth) 2695 task := &runTask{ 2696 c: results, 2697 hasBinaryOutput: binary[base], 2698 opts: opts, 2699 src: pth, 2700 } 2701 switch { 2702 case strings.HasPrefix(base, "regex-redux"): 2703 switch runtime.GOOS { 2704 case "windows": 2705 panic(todo("")) 2706 default: 2707 task.cmd = "sh" 2708 task.args = []string{"-c", fmt.Sprintf("./%s < 5000000.txt", base[:len(base)-2])} 2709 } 2710 case strings.HasPrefix(base, "k-nucleotide"): 2711 switch runtime.GOOS { 2712 case "windows": 2713 panic(todo("")) 2714 default: 2715 task.cmd = "sh" 2716 task.args = []string{"-c", fmt.Sprintf("./%s < 25000000.txt", base[:len(base)-2])} 2717 } 2718 case strings.HasPrefix(base, "reverse-complement"): 2719 switch runtime.GOOS { 2720 case "windows": 2721 panic(todo("")) 2722 default: 2723 task.cmd = "sh" 2724 task.args = []string{"-c", fmt.Sprintf("./%s < 100000000.txt", base[:len(base)-2])} 2725 } 2726 } 2727 go task.run() 2728 } 2729 } 2730 return nil 2731 }) 2732 if err != nil { 2733 t.Fatal(err) 2734 } 2735 for res != rq { 2736 r := <-results 2737 res++ 2738 <-limiter 2739 switch r.err.(type) { 2740 case nil: 2741 ok++ 2742 collect(r) 2743 case skipErr: 2744 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2745 default: 2746 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2747 } 2748 } 2749 benchmarkResults(t, rq, ok, names, m) 2750 } 2751 2752 func benchmarkResults(t *testing.T, rq, ok int, names []string, m map[string]*runResult) { 2753 t.Logf("files %v, ok %v", rq, ok) 2754 if ok == 0 { 2755 return 2756 } 2757 2758 sort.Strings(names) 2759 var ccDurations, eccDurations time.Duration 2760 t.Logf(" os/arch: %s/%s", runtime.GOOS, runtime.GOARCH) 2761 t.Logf(" cc: %s", systemCC) 2762 t.Logf("--version: %s", systemCCVersion) 2763 t.Logf(" -O: %d", *oBenchO) 2764 t.Logf(" -march: %s", *oMarch) 2765 t.Logf(" -mtune: %s", *oMtune) 2766 t.Logf(" -fopenmp: %v", *oOpenmp) 2767 t.Logf(" best of: %d", *oBestOf) 2768 t.Logf(" src ecc cc ecc/cc") 2769 var min, max float64 2770 geomean := 1.0 2771 for i, nm := range names { 2772 r := m[nm] 2773 coeff := float64(r.eccTime) / float64(r.ccTime) 2774 ccDurations += r.ccTime 2775 eccDurations += r.eccTime 2776 t.Logf("%25s: %7.3fs %7.3fs %.3f%s", nm, r.eccTime.Seconds(), r.ccTime.Seconds(), coeff, star(coeff)) 2777 switch { 2778 case i == 0: 2779 min, max = coeff, coeff 2780 default: 2781 if coeff < min { 2782 min = coeff 2783 } 2784 if coeff > max { 2785 max = coeff 2786 } 2787 } 2788 geomean *= coeff 2789 } 2790 geomean = math.Pow(geomean, 1/float64(len(names))) 2791 coeff := float64(eccDurations) / float64(ccDurations) 2792 t.Logf( 2793 " overall %7.3fs %7.3fs %.3f%s (min %.3f%s max %.3f%s)", 2794 eccDurations.Seconds(), 2795 ccDurations.Seconds(), 2796 float64(eccDurations)/float64(ccDurations), star(coeff), 2797 min, star(min), 2798 max, star(max), 2799 ) 2800 t.Logf(" geomean %7.3f%s", geomean, star(geomean)) 2801 } 2802 2803 func star(n float64) string { 2804 if n < 1 { 2805 return "*" 2806 } 2807 2808 return "" 2809 } 2810 2811 func TestBenchmarksMir(t *testing.T) { 2812 const root = "/github.com/vnmakarov/mir/c-benchmarks" 2813 2814 if testing.Short() { 2815 t.Skip("skipped: -short") 2816 } 2817 2818 mustEmptyDir(t, tempDir) 2819 wd, err := os.Getwd() 2820 if err != nil { 2821 t.Fatal(err) 2822 } 2823 2824 if err := os.Chdir(tempDir); err != nil { 2825 t.Fatal(err) 2826 } 2827 2828 defer func() { 2829 if err := os.Chdir(wd); err != nil { 2830 t.Fatal(err) 2831 } 2832 }() 2833 2834 needFiles(t, root, []string{ 2835 "simple_hash.h", 2836 }) 2837 blacklist := map[string]struct{}{} 2838 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 2839 blacklist["except.c"] = struct{}{} //TODO 2840 } 2841 m := map[string]*runResult{} 2842 var names []string 2843 collect := func(r *runResult) { 2844 nm := filepath.Base(r.name) 2845 ex := m[nm] 2846 if ex == nil { 2847 m[nm] = r 2848 names = append(names, nm) 2849 return 2850 } 2851 2852 if ex.ccTime > r.ccTime { 2853 ex.ccTime = r.ccTime 2854 } 2855 if ex.eccTime > r.eccTime { 2856 ex.eccTime = r.eccTime 2857 } 2858 } 2859 binary := map[string]bool{ 2860 "mandelbrot.c": true, 2861 } 2862 var rq, res, ok int 2863 limit := 1 2864 limiter := make(chan struct{}, limit) 2865 results := make(chan *runResult, limit) 2866 err = walk(root, func(pth string, fi os.FileInfo) error { 2867 if !strings.HasSuffix(pth, ".c") { 2868 return nil 2869 } 2870 2871 switch { 2872 case re != nil: 2873 if !re.MatchString(pth) { 2874 return nil 2875 } 2876 2877 fallthrough 2878 default: 2879 if _, ok := blacklist[filepath.Base(pth)]; ok { 2880 return nil 2881 } 2882 } 2883 2884 for i := 0; i < *oBestOf; i++ { 2885 more: 2886 select { 2887 case r := <-results: 2888 res++ 2889 <-limiter 2890 switch r.err.(type) { 2891 case nil: 2892 ok++ 2893 collect(r) 2894 case skipErr: 2895 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2896 default: 2897 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2898 } 2899 goto more 2900 case limiter <- struct{}{}: 2901 rq++ 2902 if *oTrc { 2903 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 2904 } 2905 opts := []string{ 2906 fmt.Sprintf("-O%d", *oBenchO), 2907 } 2908 if s := *oMarch; s != "" { 2909 opts = append(opts, fmt.Sprintf("-march=%s", s)) 2910 } 2911 if s := *oMtune; s != "" { 2912 opts = append(opts, fmt.Sprintf("-mtune=%s", s)) 2913 } 2914 go run(pth, binary[filepath.Base(pth)], true, false, results, opts...) 2915 } 2916 } 2917 return nil 2918 }) 2919 if err != nil { 2920 t.Fatal(err) 2921 } 2922 for res != rq { 2923 r := <-results 2924 res++ 2925 <-limiter 2926 switch r.err.(type) { 2927 case nil: 2928 ok++ 2929 collect(r) 2930 case skipErr: 2931 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 2932 default: 2933 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 2934 } 2935 } 2936 benchmarkResults(t, rq, ok, names, m) 2937 } 2938 2939 func TestBenchmarksCompCert(t *testing.T) { 2940 const root = "/github.com/AbsInt/CompCert/test/c/" 2941 2942 if testing.Short() { 2943 t.Skip("skipped: -short") 2944 } 2945 2946 mustEmptyDir(t, tempDir) 2947 wd, err := os.Getwd() 2948 if err != nil { 2949 t.Fatal(err) 2950 } 2951 2952 if err := os.Chdir(tempDir); err != nil { 2953 t.Fatal(err) 2954 } 2955 2956 defer func() { 2957 if err := os.Chdir(wd); err != nil { 2958 t.Fatal(err) 2959 } 2960 }() 2961 2962 needFiles(t, root, []string{ 2963 "Results/knucleotide-input.txt", 2964 "endian.h", 2965 }) 2966 blacklist := map[string]struct{}{} 2967 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 2968 blacklist["aes.c"] = struct{}{} //TODO 2969 } 2970 if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { 2971 blacklist["bisect.c"] = struct{}{} //TODO va_list 2972 blacklist["fftw.c"] = struct{}{} //TODO va_list 2973 blacklist["perlin.c"] = struct{}{} //TODO va_list 2974 blacklist["qsort.c"] = struct{}{} //TODO 2975 2976 } 2977 binary := map[string]bool{ 2978 "mandelbrot.c": true, //TODO 2979 } 2980 2981 m := map[string]*runResult{} 2982 var names []string 2983 collect := func(r *runResult) { 2984 nm := filepath.Base(r.name) 2985 ex := m[nm] 2986 if ex == nil { 2987 m[nm] = r 2988 names = append(names, nm) 2989 return 2990 } 2991 2992 if ex.ccTime > r.ccTime { 2993 ex.ccTime = r.ccTime 2994 } 2995 if ex.eccTime > r.eccTime { 2996 ex.eccTime = r.eccTime 2997 } 2998 } 2999 var rq, res, ok int 3000 limit := 1 3001 limiter := make(chan struct{}, limit) 3002 results := make(chan *runResult, limit) 3003 err = walk(root, func(pth string, fi os.FileInfo) error { 3004 if !strings.HasSuffix(pth, ".c") { 3005 return nil 3006 } 3007 3008 switch { 3009 case re != nil: 3010 if !re.MatchString(pth) { 3011 return nil 3012 } 3013 3014 fallthrough 3015 default: 3016 if _, ok := blacklist[filepath.Base(pth)]; ok { 3017 return nil 3018 } 3019 } 3020 3021 for i := 0; i < *oBestOf; i++ { 3022 more: 3023 select { 3024 case r := <-results: 3025 res++ 3026 <-limiter 3027 switch r.err.(type) { 3028 case nil: 3029 ok++ 3030 collect(r) 3031 case skipErr: 3032 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 3033 default: 3034 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 3035 } 3036 goto more 3037 case limiter <- struct{}{}: 3038 rq++ 3039 if *oTrc { 3040 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 3041 } 3042 opts := []string{ 3043 fmt.Sprintf("-O%d", *oBenchO), 3044 } 3045 if s := *oMarch; s != "" { 3046 opts = append(opts, fmt.Sprintf("-march=%s", s)) 3047 } 3048 if s := *oMtune; s != "" { 3049 opts = append(opts, fmt.Sprintf("-mtune=%s", s)) 3050 } 3051 if *oOpenmp { 3052 opts = append(opts, "-fopenmp") 3053 } 3054 go run(pth, binary[filepath.Base(pth)], true, false, results, opts...) 3055 } 3056 } 3057 return nil 3058 }) 3059 if err != nil { 3060 t.Fatal(err) 3061 } 3062 for res != rq { 3063 r := <-results 3064 res++ 3065 <-limiter 3066 switch r.err.(type) { 3067 case nil: 3068 ok++ 3069 collect(r) 3070 case skipErr: 3071 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 3072 default: 3073 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 3074 } 3075 } 3076 benchmarkResults(t, rq, ok, names, m) 3077 } 3078 3079 func TestPCRE(t *testing.T) { 3080 if !installEcc(t) { 3081 t.Skip("set INSTALL_ECC=1 or add -install to execute this test") 3082 } 3083 3084 const root = "/ftp.pcre.org/pub/pcre.tar.gz" 3085 archive, err := fs.Open(root) 3086 if err != nil { 3087 t.Fatal(err) 3088 } 3089 3090 mustEmptyDir(t, tempDir) 3091 if err := ccgo.Untar(tempDir, archive, nil); err != nil { 3092 t.Fatal(err) 3093 } 3094 3095 if err := ccgo.InDir(filepath.Join(tempDir, "pcre"), func() error { 3096 switch { 3097 case 3098 //TODO runtime.GOOS == "darwin" && runtime.GOARCH == "amd64", 3099 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "386", 3100 runtime.GOOS == "linux" && runtime.GOARCH == "amd64": 3101 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "arm", 3102 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "arm64", 3103 //TODO runtime.GOOS == "linux" && runtime.GOARCH == "s390x": 3104 3105 //TODO --enable-pcre16 fails 3106 //TODO --enable-jit need assembler support 3107 out, err := ccgo.Shell("sh", "-c", "CC=ecc ./configure --disable-cpp --enable-shared=no --enable-pcre16 --enable-pcre32 --enable-utf --enable-unicode-properties && make check") 3108 if err != nil { 3109 return errorf("err: %v\n%s", err, out) 3110 } 3111 default: 3112 // windows/amd64 3113 //TODO 3114 t.Skip("TODO") //TODO 3115 } 3116 3117 return nil 3118 }); err != nil { 3119 t.Fatal(err) 3120 } 3121 } 3122 3123 func TestCxgo(t *testing.T) { 3124 const root = "/github.com/cxgo" 3125 mustEmptyDir(t, tempDir) 3126 wd, err := os.Getwd() 3127 if err != nil { 3128 t.Fatal(err) 3129 } 3130 3131 if err := os.Chdir(tempDir); err != nil { 3132 t.Fatal(err) 3133 } 3134 3135 defer func() { 3136 if err := os.Chdir(wd); err != nil { 3137 t.Fatal(err) 3138 } 3139 }() 3140 3141 needFiles(t, root, []string{}) 3142 blacklist := map[string]struct{}{ 3143 "function forward decl 2.c": {}, //TODO 3144 "inet.c": {}, //TODO 3145 } 3146 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" { 3147 blacklist["function forward decl 2.c"] = struct{}{} //TODO 3148 } 3149 if runtime.GOOS == "linux" && runtime.GOARCH == "s390x" { 3150 blacklist["function forward decl 2.c"] = struct{}{} //TODO 3151 } 3152 if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" { 3153 blacklist["function forward decl 2.c"] = struct{}{} //TODO 3154 } 3155 if runtime.GOOS == "linux" && runtime.GOARCH == "386" { 3156 blacklist["enum fixed.c"] = struct{}{} //TODO 3157 blacklist["enum no zero 2.c"] = struct{}{} //TODO 3158 blacklist["enum no zero.c"] = struct{}{} //TODO 3159 blacklist["enum start.c"] = struct{}{} //TODO 3160 blacklist["enum zero.c"] = struct{}{} //TODO 3161 blacklist["extern var.c"] = struct{}{} //TODO 3162 blacklist["forward enum.c"] = struct{}{} //TODO 3163 blacklist["function forward decl 2.c"] = struct{}{} //TODO 3164 blacklist["go ints.c"] = struct{}{} //TODO 3165 blacklist["named enum.c"] = struct{}{} //TODO 3166 blacklist["return enum.c"] = struct{}{} //TODO 3167 blacklist["struct and func.c"] = struct{}{} //TODO 3168 blacklist["typedef enum.c"] = struct{}{} //TODO 3169 blacklist["typedef primitive.c"] = struct{}{} //TODO 3170 blacklist["unnamed enum.c"] = struct{}{} //TODO 3171 } 3172 var rq, res, ok int 3173 limit := runtime.GOMAXPROCS(0) 3174 limiter := make(chan struct{}, limit) 3175 results := make(chan *runResult, limit) 3176 failed := map[string]struct{}{} 3177 err = walk(root, func(pth string, fi os.FileInfo) error { 3178 if !strings.HasSuffix(pth, ".c") { 3179 return nil 3180 } 3181 3182 switch { 3183 case re != nil: 3184 if !re.MatchString(pth) { 3185 return nil 3186 } 3187 default: 3188 if _, ok := blacklist[filepath.Base(pth)]; ok { 3189 return nil 3190 } 3191 } 3192 3193 more: 3194 select { 3195 case r := <-results: 3196 res++ 3197 <-limiter 3198 switch r.err.(type) { 3199 case nil: 3200 ok++ 3201 delete(failed, r.name) 3202 case skipErr: 3203 delete(failed, r.name) 3204 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 3205 default: 3206 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 3207 } 3208 goto more 3209 case limiter <- struct{}{}: 3210 rq++ 3211 if *oTrc { 3212 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 3213 } 3214 failed[pth] = struct{}{} 3215 go run(pth, false, false, true, results) 3216 } 3217 return nil 3218 }) 3219 if err != nil { 3220 t.Fatal(err) 3221 } 3222 for res != rq { 3223 r := <-results 3224 res++ 3225 <-limiter 3226 switch r.err.(type) { 3227 case nil: 3228 ok++ 3229 delete(failed, r.name) 3230 case skipErr: 3231 delete(failed, r.name) 3232 t.Logf("%v: %v\n%s", r.name, r.err, r.out) 3233 default: 3234 t.Errorf("%v: %v\n%s", r.name, r.err, r.out) 3235 } 3236 } 3237 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 3238 if len(failed) == 0 { 3239 return 3240 } 3241 3242 var a []string 3243 for k := range failed { 3244 a = append(a, k) 3245 } 3246 sort.Strings(a) 3247 for _, v := range a { 3248 t.Logf("FAIL %s", v) 3249 } 3250 } 3251 3252 func TestCSmith(t *testing.T) { 3253 return //TODO- 3254 3255 if *oCSmith == 0 { 3256 return 3257 } 3258 3259 fixedBugs := []string{ 3260 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 169375684", 3261 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 1833258637", 3262 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 1885311141", 3263 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 2205128324", 3264 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 2273393378", 3265 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 241244373", 3266 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 2517344771", 3267 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 2648215054", 3268 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 2876930815", 3269 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3043990076", 3270 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3100949894", 3271 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3126091077", 3272 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3130410542", 3273 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3329111231", 3274 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3363122597", 3275 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3365074920", 3276 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3578720023", 3277 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3645367888", 3278 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3919255949", 3279 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 4058772172", 3280 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 4101947480", 3281 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 4130344133", 3282 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 4146870674", 3283 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 517639208", 3284 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 56498550", 3285 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 890611563", 3286 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 963985971", 3287 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1341005347", 3288 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1346606946", 3289 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1410729753", 3290 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1473217979", 3291 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1485689586", 3292 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1872452393", 3293 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 1947158672", 3294 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 2232359541", 3295 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 2295327168", 3296 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 231122029", 3297 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 2452101147", 3298 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 251697819", 3299 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 2545154538", 3300 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 2551936195", 3301 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 3394478498", 3302 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 3688696230", 3303 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 4151780743", 3304 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 4275869822", 3305 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 541090131", 3306 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 828263634", 3307 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 885721321", 3308 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 964049230", 3309 "--bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-volatile-pointers --no-volatiles --paranoid -s 980538434", 3310 "--bitfields --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid --max-nested-struct-level 10 -s 1906742816", 3311 "--bitfields --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid --max-nested-struct-level 10 -s 3629008936", 3312 "--bitfields --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid --max-nested-struct-level 10 -s 612971101", 3313 "--no-bitfields --max-nested-struct-level 10 --no-const-pointers --no-consts --no-packed-struct --no-volatile-pointers --no-volatiles --paranoid -s 3720922579", 3314 } 3315 3316 csmithDefaultArgs := strings.Join([]string{ 3317 "--bitfields", // --bitfields | --no-bitfields: enable | disable full-bitfields structs (disabled by default). 3318 "--max-nested-struct-level", "10", // --max-nested-struct-level <num>: limit maximum nested level of structs to <num>(default 0). Only works in the exhaustive mode. 3319 "--no-const-pointers", // --const-pointers | --no-const-pointers: enable | disable const pointers (enabled by default). 3320 "--no-consts", // --consts | --no-consts: enable | disable const qualifier (enabled by default). 3321 "--no-volatile-pointers", // --volatile-pointers | --no-volatile-pointers: enable | disable volatile pointers (enabled by default). 3322 "--no-volatiles", // --volatiles | --no-volatiles: enable | disable volatiles (enabled by default). 3323 "--paranoid", // --paranoid | --no-paranoid: enable | disable pointer-related assertions (disabled by default). 3324 }, " ") 3325 3326 csmith, err := exec.LookPath("csmith") 3327 if err != nil { 3328 t.Skip("csmith executable not found") 3329 return 3330 } 3331 3332 var csp string 3333 switch runtime.GOOS { 3334 case "linux", "darwin": 3335 csp = "/usr/include/csmith" 3336 } 3337 if s := os.Getenv("CSMITH_PATH"); s != "" { 3338 csp = s 3339 } 3340 if csp != "" { 3341 csp = fmt.Sprintf("-I%s", csp) 3342 } 3343 3344 argCh := make(chan string, 100) 3345 doneCh := make(chan struct{}) 3346 3347 go func() { 3348 for _, v := range fixedBugs { 3349 select { 3350 case <-doneCh: 3351 return 3352 default: 3353 argCh <- v 3354 } 3355 } 3356 for { 3357 select { 3358 case <-doneCh: 3359 return 3360 default: 3361 argCh <- csmithDefaultArgs 3362 } 3363 } 3364 }() 3365 3366 go func() { 3367 <-time.After(*oCSmith) 3368 close(doneCh) 3369 }() 3370 3371 mustEmptyDir(t, tempDir) 3372 wd, err := os.Getwd() 3373 if err != nil { 3374 t.Fatal(err) 3375 } 3376 3377 if err := os.Chdir(tempDir); err != nil { 3378 t.Fatal(err) 3379 } 3380 3381 defer func() { 3382 if err := os.Chdir(wd); err != nil { 3383 t.Fatal(err) 3384 } 3385 }() 3386 3387 blacklist := map[string]struct{}{} 3388 3389 var rq, res, ok int 3390 limit := runtime.GOMAXPROCS(0) 3391 limiter := make(chan struct{}, limit) 3392 results := make(chan *runResult, limit) 3393 failed := map[string]string{} 3394 iFile := 0 3395 loop: 3396 for { 3397 var args string 3398 select { 3399 case args = <-argCh: 3400 // ok 3401 case <-doneCh: 3402 break loop 3403 } 3404 3405 switch { 3406 case re != nil: 3407 if !re.MatchString(args) { 3408 continue 3409 } 3410 3411 close(doneCh) 3412 default: 3413 if _, ok := blacklist[filepath.Base(args)]; ok { 3414 continue 3415 } 3416 } 3417 3418 pth := fmt.Sprintf("%06d.c", iFile) 3419 iFile++ 3420 more: 3421 select { 3422 case r := <-results: 3423 res++ 3424 <-limiter 3425 switch r.err.(type) { 3426 case nil: 3427 os.Remove(r.name) 3428 ok++ 3429 delete(failed, r.name) 3430 case skipErr: 3431 os.Remove(r.name) 3432 delete(failed, r.name) 3433 t.Errorf("%v: ERROR %v\n%s", r.name, r.err, r.out) 3434 if *oFF { 3435 break loop 3436 } 3437 default: 3438 t.Errorf("%v: ERROR %v\n%s", r.name, r.err, r.out) 3439 if *oFF { 3440 break loop 3441 } 3442 } 3443 goto more 3444 case limiter <- struct{}{}: 3445 rq++ 3446 if *oTrc { 3447 fmt.Fprintf(os.Stderr, "%v: %s\n", rq, pth) 3448 } 3449 csOut, err := exec.Command(csmith, strings.Split(args, " ")...).Output() 3450 if err != nil { 3451 t.Fatalf("%v\n%s", err, csOut) 3452 } 3453 3454 if err := os.WriteFile(pth, csOut, 0660); err != nil { 3455 t.Fatalf("%s, %s: %v", pth, args, err) 3456 } 3457 3458 failed[pth] = string(csOut) 3459 go (&runTask{ 3460 c: results, 3461 csmithSrc: csOut, 3462 opts: []string{csp}, 3463 src: pth, 3464 }).runCSmith() 3465 } 3466 } 3467 for res != rq { 3468 r := <-results 3469 res++ 3470 <-limiter 3471 switch r.err.(type) { 3472 case nil: 3473 os.Remove(r.name) 3474 ok++ 3475 delete(failed, r.name) 3476 case skipErr: 3477 os.Remove(r.name) 3478 delete(failed, r.name) 3479 t.Errorf("%v: ERROR %v\n%s", r.name, r.err, r.out) 3480 default: 3481 t.Errorf("%v: ERROR %v\n%s", r.name, r.err, r.out) 3482 } 3483 } 3484 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 3485 if len(failed) == 0 { 3486 return 3487 } 3488 3489 var a []string 3490 for k := range failed { 3491 a = append(a, k) 3492 } 3493 sort.Strings(a) 3494 for _, v := range a { 3495 t.Logf("FAIL %s\n%s", v, failed[v]) 3496 if *oFF { 3497 break 3498 } 3499 } 3500 t.Logf("files %v, ok %v, failed %v", rq, ok, len(failed)) 3501 for _, v := range a { 3502 t.Logf("FAIL %s: %s", v, extractCSmithOptions(failed[v])) 3503 if *oFF { 3504 break 3505 } 3506 } 3507 } 3508 3509 func extractCSmithOptions(s string) string { 3510 const ( 3511 tag = "* Options:" 3512 tag2 = "* Seed:" 3513 ) 3514 x := strings.Index(s, tag) 3515 s = s[x+len(tag):] 3516 x = strings.Index(s, "\n") 3517 s2 := s[x:] 3518 s = s[:x] 3519 s = strings.TrimSpace(s) 3520 if strings.Contains(s, " -s ") { 3521 return s 3522 } 3523 3524 x = strings.Index(s2, tag2) 3525 s2 = s2[x+len(tag):] 3526 x = strings.Index(s2, "\n") 3527 s2 = s2[:x] 3528 return fmt.Sprintf("%s -s %s", s, strings.TrimSpace(s2)) 3529 }