LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Annotate Ref in Prog with C types by parsing gcc debug output. | 5 // Annotate Ref in Prog with C types by parsing gcc debug output. |
6 // Conversion of debug output to Go types. | 6 // Conversion of debug output to Go types. |
7 | 7 |
8 package main | 8 package main |
9 | 9 |
10 import ( | 10 import ( |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 | 676 |
677 // Remove functions only used as expressions, so their respective | 677 // Remove functions only used as expressions, so their respective |
678 // bridge functions are not generated. | 678 // bridge functions are not generated. |
679 for name, used := range functions { | 679 for name, used := range functions { |
680 if !used { | 680 if !used { |
681 delete(f.Name, name) | 681 delete(f.Name, name) |
682 } | 682 } |
683 } | 683 } |
684 } | 684 } |
685 | 685 |
686 // gccName returns the name of the compiler to run. Use $CC if set in | 686 // gccBaseCmd returns the start of the compiler command line. |
687 // the environment, otherwise just "gcc". | 687 // It uses $CC if set, or else $GCC, or else the compiler recorded |
688 | 688 // during the initial build as defaultCC. |
689 func (p *Package) gccName() string { | 689 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. |
| 690 func (p *Package) gccBaseCmd() []string { |
690 // Use $CC if set, since that's what the build uses. | 691 // Use $CC if set, since that's what the build uses. |
691 » if ret := os.Getenv("CC"); ret != "" { | 692 » if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { |
692 return ret | 693 return ret |
693 } | 694 } |
694 » // Fall back to $GCC if set, since that's what we used to use. | 695 » // Try $GCC if set, since that's what we used to use. |
695 » if ret := os.Getenv("GCC"); ret != "" { | 696 » if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { |
696 return ret | 697 return ret |
697 } | 698 } |
698 » return "gcc" | 699 » return strings.Fields(defaultCC) |
699 } | 700 } |
700 | 701 |
701 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". | 702 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". |
702 func (p *Package) gccMachine() []string { | 703 func (p *Package) gccMachine() []string { |
703 switch goarch { | 704 switch goarch { |
704 case "amd64": | 705 case "amd64": |
705 return []string{"-m64"} | 706 return []string{"-m64"} |
706 case "386": | 707 case "386": |
707 return []string{"-m32"} | 708 return []string{"-m32"} |
708 case "arm": | 709 case "arm": |
709 return []string{"-marm"} // not thumb | 710 return []string{"-marm"} // not thumb |
710 } | 711 } |
711 return nil | 712 return nil |
712 } | 713 } |
713 | 714 |
714 func gccTmp() string { | 715 func gccTmp() string { |
715 return *objDir + "_cgo_.o" | 716 return *objDir + "_cgo_.o" |
716 } | 717 } |
717 | 718 |
718 // gccCmd returns the gcc command line to use for compiling | 719 // gccCmd returns the gcc command line to use for compiling |
719 // the input. | 720 // the input. |
720 func (p *Package) gccCmd() []string { | 721 func (p *Package) gccCmd() []string { |
721 » c := []string{ | 722 » c := append(p.gccBaseCmd(), |
722 » » p.gccName(), | |
723 "-Wall", // many warnings | 723 "-Wall", // many warnings |
724 "-Werror", // warnings are errors | 724 "-Werror", // warnings are errors |
725 » » "-o" + gccTmp(), // write object to tmp | 725 » » "-o"+gccTmp(), // write object to tmp |
726 "-gdwarf-2", // generate DWARF v2 debugg
ing symbols | 726 "-gdwarf-2", // generate DWARF v2 debugg
ing symbols |
727 "-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped
enum otherwise | 727 "-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped
enum otherwise |
728 "-c", // do not link | 728 "-c", // do not link |
729 "-xc", // input language is C | 729 "-xc", // input language is C |
730 » } | 730 » ) |
731 » if strings.Contains(p.gccName(), "clang") { | 731 » if strings.Contains(c[0], "clang") { |
732 c = append(c, | 732 c = append(c, |
733 "-ferror-limit=0", | 733 "-ferror-limit=0", |
734 // Apple clang version 1.7 (tags/Apple/clang-77) (based
on LLVM 2.9svn) | 734 // Apple clang version 1.7 (tags/Apple/clang-77) (based
on LLVM 2.9svn) |
735 // doesn't have -Wno-unneeded-internal-declaration, so w
e need yet another | 735 // doesn't have -Wno-unneeded-internal-declaration, so w
e need yet another |
736 // flag to disable the warning. Yes, really good diagnos
tics, clang. | 736 // flag to disable the warning. Yes, really good diagnos
tics, clang. |
737 "-Wno-unknown-warning-option", | 737 "-Wno-unknown-warning-option", |
738 "-Wno-unneeded-internal-declaration", | 738 "-Wno-unneeded-internal-declaration", |
739 "-Wno-unused-function", | 739 "-Wno-unused-function", |
740 "-Qunused-arguments", | 740 "-Qunused-arguments", |
741 ) | 741 ) |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 | 830 |
831 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp()) | 831 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp()) |
832 panic("not reached") | 832 panic("not reached") |
833 } | 833 } |
834 | 834 |
835 // gccDefines runs gcc -E -dM -xc - over the C program stdin | 835 // gccDefines runs gcc -E -dM -xc - over the C program stdin |
836 // and returns the corresponding standard output, which is the | 836 // and returns the corresponding standard output, which is the |
837 // #defines that gcc encountered while processing the input | 837 // #defines that gcc encountered while processing the input |
838 // and its included files. | 838 // and its included files. |
839 func (p *Package) gccDefines(stdin []byte) string { | 839 func (p *Package) gccDefines(stdin []byte) string { |
840 » base := []string{p.gccName(), "-E", "-dM", "-xc"} | 840 » base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") |
841 base = append(base, p.gccMachine()...) | 841 base = append(base, p.gccMachine()...) |
842 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) | 842 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) |
843 return stdout | 843 return stdout |
844 } | 844 } |
845 | 845 |
846 // gccErrors runs gcc over the C program stdin and returns | 846 // gccErrors runs gcc over the C program stdin and returns |
847 // the errors that gcc prints. That is, this function expects | 847 // the errors that gcc prints. That is, this function expects |
848 // gcc to fail. | 848 // gcc to fail. |
849 func (p *Package) gccErrors(stdin []byte) string { | 849 func (p *Package) gccErrors(stdin []byte) string { |
850 // TODO(rsc): require failure | 850 // TODO(rsc): require failure |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 } | 1588 } |
1589 if prefix == "" { | 1589 if prefix == "" { |
1590 prefix = n.Name[:i+1] | 1590 prefix = n.Name[:i+1] |
1591 } else if prefix != n.Name[:i+1] { | 1591 } else if prefix != n.Name[:i+1] { |
1592 return "" | 1592 return "" |
1593 } | 1593 } |
1594 } | 1594 } |
1595 } | 1595 } |
1596 return prefix | 1596 return prefix |
1597 } | 1597 } |
LEFT | RIGHT |