diff options
Diffstat (limited to 'vendor/modernc.org/ccgo')
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/Makefile | 18 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/ccgo.go | 369 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/dmesg.go | 1 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/go.go | 575 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/init.go | 225 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/mem.go | 1 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/nodmesg.go | 1 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/util.go | 22 |
8 files changed, 837 insertions, 375 deletions
diff --git a/vendor/modernc.org/ccgo/v3/lib/Makefile b/vendor/modernc.org/ccgo/v3/lib/Makefile index 776f7eb46..ec6f53518 100644 --- a/vendor/modernc.org/ccgo/v3/lib/Makefile +++ b/vendor/modernc.org/ccgo/v3/lib/Makefile @@ -72,13 +72,17 @@ test_windows_amd64: time /T | tee -a %TEMP%\testlog-windows-amd64 build_all_targets: - GOOS=darwin GOARCH=amd64 go build -v ./... - GOOS=linux GOARCH=386 go build -v ./... - GOOS=linux GOARCH=amd64 go build -v ./... - GOOS=linux GOARCH=arm go build -v ./... - GOOS=linux GOARCH=arm64 go build -v ./... - GOOS=windows GOARCH=386 go build -v ./... - GOOS=windows GOARCH=amd64 go build -v ./... + GOOS=darwin GOARCH=amd64 go test -c -o /dev/null + GOOS=darwin GOARCH=arm64 go test -c -o /dev/null + GOOS=freebsd GOARCH=amd64 go test -c -o /dev/null + GOOS=linux GOARCH=386 go test -c -o /dev/null + GOOS=linux GOARCH=amd64 go test -c -o /dev/null + GOOS=linux GOARCH=arm go test -c -o /dev/null + GOOS=linux GOARCH=arm64 go test -c -o /dev/null + GOOS=linux GOARCH=s390x go test -c -o /dev/null + GOOS=netbsd GOARCH=amd64 go test -c -o /dev/null + GOOS=windows GOARCH=386 go test -c -o /dev/null + GOOS=windows GOARCH=amd64 go test -c -o /dev/null devbench: date 2>&1 | tee log-devbench diff --git a/vendor/modernc.org/ccgo/v3/lib/ccgo.go b/vendor/modernc.org/ccgo/v3/lib/ccgo.go index 7865ab8f6..0c62d76b2 100644 --- a/vendor/modernc.org/ccgo/v3/lib/ccgo.go +++ b/vendor/modernc.org/ccgo/v3/lib/ccgo.go @@ -18,6 +18,7 @@ import ( "go/parser" "go/token" "io" + "io/ioutil" "os" "os/exec" "path/filepath" @@ -32,17 +33,20 @@ import ( "github.com/kballard/go-shellquote" "golang.org/x/tools/go/packages" "modernc.org/cc/v3" + "modernc.org/libc" "modernc.org/opt" ) const ( - Version = "3.10.0-20210904132603" + Version = "3.12.6-20210922111124" experimentsEnvVar = "CCGO_EXPERIMENT" maxSourceLine = 1 << 20 ) var ( + _ = libc.Xstdin + coverExperiment bool ) @@ -201,9 +205,11 @@ char *__builtin___strncpy_chk(char *dest, char *src, size_t n, size_t os); char *__builtin_strchr(const char *s, int c); char *__builtin_strcpy(char *dest, const char *src); double __builtin_copysign ( double x, double y ); +double __builtin_copysignl (long double x, long double y ); double __builtin_fabs(double x); double __builtin_huge_val (void); double __builtin_inf (void); +double __builtin_nan (const char *str); float __builtin_copysignf ( float x, float y ); float __builtin_huge_valf (void); float __builtin_inff (void); @@ -214,18 +220,23 @@ int __builtin___vsnprintf_chk (char *s, size_t maxlen, int flag, size_t os, cons int __builtin__snprintf_chk(char * str, size_t maxlen, int flag, size_t strlen, const char * format); int __builtin_abs(int j); int __builtin_add_overflow(); +int __builtin_clz (unsigned); +int __builtin_clzl (unsigned long); int __builtin_clzll (unsigned long long); int __builtin_constant_p_impl(int, ...); +int __builtin_getentropy(void*, size_t); int __builtin_isnan(double); int __builtin_memcmp(const void *s1, const void *s2, size_t n); int __builtin_mul_overflow(); int __builtin_popcount (unsigned int x); +int __builtin_popcountl (unsigned long x); int __builtin_printf(const char *format, ...); int __builtin_snprintf(char *str, size_t size, const char *format, ...); int __builtin_sprintf(char *str, const char *format, ...); int __builtin_strcmp(const char *s1, const char *s2); int __builtin_sub_overflow(); long __builtin_expect (long exp, long c); +long double __builtin_nanl (const char *str); long long __builtin_llabs(long long j); size_t __builtin_object_size (void * ptr, int type); size_t __builtin_strlen(const char *s); @@ -243,9 +254,30 @@ void __builtin_free(void *ptr); void __builtin_prefetch (const void *addr, ...); void __builtin_trap (void); void __builtin_unreachable (void); +void __ccgo_dmesg(char*, ...); void __ccgo_va_end(__builtin_va_list ap); void __ccgo_va_start(__builtin_va_list ap); +#define __sync_add_and_fetch(ptr, val) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(*ptr), unsigned), \ + __sync_add_and_fetch_uint32(ptr, val), \ + __TODO__ \ + ) + +#define __sync_fetch_and_add(ptr, val) \ + __TODO__ \ + +#define __sync_sub_and_fetch(ptr, val) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(*ptr), unsigned), \ + __sync_sub_and_fetch_uint32(ptr, val), \ + __TODO__ \ + ) + +unsigned __sync_add_and_fetch_uint32(unsigned*, unsigned); +unsigned __sync_sub_and_fetch_uint32(unsigned*, unsigned); + ` defaultCrt = "modernc.org/libc" ) @@ -296,8 +328,7 @@ func trc(s string, args ...interface{}) string { //TODO- default: s = fmt.Sprintf(s, args...) } - _, fn, fl, _ := runtime.Caller(1) - r := fmt.Sprintf("%s:%d: TRC %s", fn, fl, s) + r := fmt.Sprintf("%s: TRC %s", origin(2), s) fmt.Fprintf(os.Stdout, "%s\n", r) os.Stdout.Sync() return r @@ -313,6 +344,8 @@ type Task struct { args []string asts []*cc.AST capif string + saveConfig string // -save-config + saveConfigErr error cc string // $CC, default "gcc" ccLookPath string // LookPath(cc) cdb string // foo.json, use compile DB @@ -331,9 +364,14 @@ type Task struct { hide map[string]struct{} // -hide hostConfigCmd string // -host-config-cmd hostConfigOpts string // -host-config-opts - ignoredIncludes string // -ignored-includes + hostIncludes []string + hostPredefined string + hostSysIncludes []string + ignoredIncludes string // -ignored-includes imported []*imported + includedFiles map[string]struct{} l []string // -l + loadConfig string // --load-config o string // -o out io.Writer pkgName string // -pkgname @@ -346,6 +384,7 @@ type Task struct { stderr io.Writer stdout io.Writer symSearchOrder []int // >= 0: asts[i], < 0 : imported[-i-1] + verboseCompiledb bool // -verbose-compiledb volatiles map[cc.StringID]struct{} // -volatile // Path to a binary that will be called instead of executing @@ -359,6 +398,8 @@ type Task struct { E bool // -E allErrors bool // -all-errors compiledbValid bool // -compiledb present + configSaved bool + configured bool // hostPredefined, hostIncludes, hostSysIncludes are valid cover bool // -cover-instrumentation coverC bool // -cover-instrumentation-c defaultUnExport bool // -unexported-by-default @@ -372,6 +413,7 @@ type Task struct { fullPathComments bool // -full-path-comments funcSig bool // -func-sig header bool // -header + ignoreUndefined bool // -ignoreUndefined isScripted bool mingw bool noCapi bool // -nocapi @@ -575,14 +617,23 @@ func (t *Task) capi2(files []string) (pkgName string, exports map[string]struct{ // Main executes task. func (t *Task) Main() (err error) { + // trc("%p: %q", t, t.args) if dmesgs { defer func() { if err != nil { + // trc("FAIL %p: %q: %v", t, t.args, err) dmesg("%v: returning from Task.Main: %v", origin(1), err) } }() } + + defer func() { + if t.saveConfigErr != nil && err == nil { + err = t.saveConfigErr + } + }() + if !t.isScripted && coverExperiment { defer func() { fmt.Fprintf(os.Stderr, "cover report:\n%s\n", coverReport()) @@ -630,24 +681,105 @@ func (t *Task) Main() (err error) { opts.Opt("full-path-comments", func(opt string) error { t.fullPathComments = true; return nil }) opts.Opt("func-sig", func(opt string) error { t.funcSig = true; return nil }) opts.Opt("header", func(opt string) error { t.header = true; return nil }) + opts.Opt("ignore-undefined", func(opt string) error { t.ignoreUndefined = true; return nil }) opts.Opt("nocapi", func(opt string) error { t.noCapi = true; return nil }) opts.Opt("nostdinc", func(opt string) error { t.nostdinc = true; return nil }) opts.Opt("panic-stubs", func(opt string) error { t.panicStubs = true; return nil }) - opts.Opt("trace-translation-units", func(opt string) error { t.traceTranslationUnits = true; return nil }) opts.Opt("trace-pinning", func(opt string) error { t.tracePinning = true; return nil }) + opts.Opt("trace-translation-units", func(opt string) error { t.traceTranslationUnits = true; return nil }) opts.Opt("unexported-by-default", func(opt string) error { t.defaultUnExport = true; return nil }) + opts.Opt("verbose-compiledb", func(opt string) error { t.verboseCompiledb = true; return nil }) opts.Opt("verify-structs", func(opt string) error { t.verifyStructs = true; return nil }) opts.Opt("version", func(opt string) error { t.version = true; return nil }) opts.Opt("watch-instrumentation", func(opt string) error { t.watch = true; return nil }) opts.Opt("windows", func(opt string) error { t.windows = true; return nil }) + opts.Opt("trace-included-files", func(opt string) error { + if t.includedFiles == nil { + t.includedFiles = map[string]struct{}{} + } + prev := t.cfg.IncludeFileHandler + t.cfg.IncludeFileHandler = func(pos token.Position, pathName string) { + if prev != nil { + prev(pos, pathName) + } + if _, ok := t.includedFiles[pathName]; !ok { + t.includedFiles[pathName] = struct{}{} + fmt.Fprintf(os.Stderr, "#include %s\n", pathName) + } + } + return nil + }) + opts.Arg("save-config", false, func(arg, value string) error { + if value == "" { + return nil + } + + abs, err := filepath.Abs(value) + if err != nil { + return err + } + + t.saveConfig = abs + if t.includedFiles == nil { + t.includedFiles = map[string]struct{}{} + } + prev := t.cfg.IncludeFileHandler + t.cfg.IncludeFileHandler = func(pos token.Position, pathName string) { + if prev != nil { + prev(pos, pathName) + } + if _, ok := t.includedFiles[pathName]; !ok { + t.includedFiles[pathName] = struct{}{} + full := filepath.Join(abs, pathName) + switch _, err := os.Stat(full); { + case err != nil && os.IsNotExist(err): + // ok + case err != nil: + t.saveConfigErr = err + return + default: + return + } + + b, err := ioutil.ReadFile(pathName) + if err != nil { + t.saveConfigErr = err + return + } + + dir, _ := filepath.Split(full) + if err := os.MkdirAll(dir, 0700); err != nil { + t.saveConfigErr = err + return + } + + if err := ioutil.WriteFile(full, b, 0600); err != nil { + t.saveConfigErr = err + } + } + } + return nil + }) + opts.Arg("-load-config", false, func(arg, value string) error { + if value == "" { + return nil + } + + abs, err := filepath.Abs(value) + if err != nil { + return err + } + + t.loadConfig = abs + return nil + }) opts.Arg("volatile", false, func(arg, value string) error { for _, v := range strings.Split(strings.TrimSpace(value), ",") { t.volatiles[cc.String(v)] = struct{}{} } return nil }) - opts.Opt("nostdlib", func(opt string) error { t.nostdlib = true t.crt = "" @@ -711,6 +843,10 @@ func (t *Task) Main() (err error) { return t.createCompileDB(cmd) case t.cdb != "": // foo.json ..., use DB + if err := t.configure(); err != nil { + return err + } + return t.useCompileDB(t.cdb, x) } @@ -721,6 +857,20 @@ func (t *Task) Main() (err error) { } if t.version { + gobin, err := exec.LookPath("go") + var b []byte + if err == nil { + var bin string + bin, err = exec.LookPath(os.Args[0]) + if err == nil { + b, err = exec.Command(gobin, "version", "-m", bin).CombinedOutput() + } + } + if err == nil { + fmt.Fprintf(t.stdout, "%s", b) + return nil + } + fmt.Fprintf(t.stdout, "%s\n", Version) return nil } @@ -746,7 +896,13 @@ func (t *Task) Main() (err error) { } t.imported[len(t.imported)-1].used = true // crt is always imported } + + if err := t.configure(); err != nil { + return err + } + abi, err := cc.NewABI(t.goos, t.goarch) + abi.Types[cc.LongDouble] = abi.Types[cc.Double] if err != nil { return err } @@ -764,27 +920,19 @@ func (t *Task) Main() (err error) { t.cfg.ReplaceMacroTclIeeeDoubleRounding = t.replaceTclIeeeDoubleRounding t.cfg.Config3.IgnoreInclude = re t.cfg.Config3.NoFieldAndBitfieldOverlap = true - t.cfg.Config3.PreserveWhiteSpace = true + t.cfg.Config3.PreserveWhiteSpace = t.saveConfig == "" t.cfg.Config3.UnsignedEnums = true - hostConfigOpts := strings.Split(t.hostConfigOpts, ",") - if t.hostConfigOpts == "" { - hostConfigOpts = nil - } - hostPredefined, hostIncludes, hostSysIncludes, err := cc.HostConfig(t.hostConfigCmd, hostConfigOpts...) - if err != nil { - return err - } - if t.mingw = detectMingw(hostPredefined); t.mingw { + if t.mingw = detectMingw(t.hostPredefined); t.mingw { t.windows = true } if t.nostdinc { - hostIncludes = nil - hostSysIncludes = nil + t.hostIncludes = nil + t.hostSysIncludes = nil } var sources []cc.Source - if hostPredefined != "" { - sources = append(sources, cc.Source{Name: "<predefined>", Value: hostPredefined}) + if t.hostPredefined != "" { + sources = append(sources, cc.Source{Name: "<predefined>", Value: t.hostPredefined}) } sources = append(sources, cc.Source{Name: "<builtin>", Value: builtin}) if len(t.D) != 0 { @@ -816,12 +964,12 @@ func (t *Task) Main() (err error) { // line, then in directories named in -I options, and last in the usual // places includePaths := append([]string{"@"}, t.I...) - includePaths = append(includePaths, hostIncludes...) - includePaths = append(includePaths, hostSysIncludes...) + includePaths = append(includePaths, t.hostIncludes...) + includePaths = append(includePaths, t.hostSysIncludes...) // For headers whose names are enclosed in angle brackets ( "<>" ), the // header shall be searched for only in directories named in -I options // and then in the usual places. - sysIncludePaths := append(t.I, hostSysIncludes...) + sysIncludePaths := append(t.I, t.hostSysIncludes...) if t.traceTranslationUnits { fmt.Printf("target: %s/%s\n", t.goos, t.goarch) if t.hostConfigCmd != "" { @@ -830,11 +978,17 @@ func (t *Task) Main() (err error) { } for i, v := range t.sources { tuSources := append(sources, v) + out := t.stdout + if t.saveConfig != "" { + out = io.Discard + t.E = true + } if t.E { t.cfg.PreprocessOnly = true - if err := cc.Preprocess(t.cfg, includePaths, sysIncludePaths, tuSources, t.stdout); err != nil { + if err := cc.Preprocess(t.cfg, includePaths, sysIncludePaths, tuSources, out); err != nil { return err } + memGuard(i, t.isScripted) continue } @@ -861,6 +1015,81 @@ func (t *Task) Main() (err error) { return t.link() } +func (t *Task) configure() (err error) { + if t.configured { + return nil + } + + type jsonConfig struct { + Predefined string + IncludePaths []string + SysIncludePaths []string + OS string + Arch string + } + + t.configured = true + if t.loadConfig != "" { + path := filepath.Join(t.loadConfig, "config.json") + // trc("%p: LOAD_CONFIG(%s)", t, path) + b, err := ioutil.ReadFile(path) + if err != nil { + return err + } + + loadConfig := &jsonConfig{} + if err := json.Unmarshal(b, loadConfig); err != nil { + return err + } + + t.goos = loadConfig.OS + t.goarch = loadConfig.Arch + for _, v := range loadConfig.IncludePaths { + t.hostIncludes = append(t.hostIncludes, filepath.Join(t.loadConfig, v)) + } + for _, v := range loadConfig.SysIncludePaths { + t.hostSysIncludes = append(t.hostSysIncludes, filepath.Join(t.loadConfig, v)) + } + t.hostPredefined = loadConfig.Predefined + return nil + } + + hostConfigOpts := strings.Split(t.hostConfigOpts, ",") + if t.hostConfigOpts == "" { + hostConfigOpts = nil + } + if t.hostPredefined, t.hostIncludes, t.hostSysIncludes, err = cc.HostConfig(t.hostConfigCmd, hostConfigOpts...); err != nil { + return err + } + + if t.saveConfig != "" && !t.configSaved { + t.configSaved = true + // trc("%p: SAVE_CONFIG(%s)", t, t.saveConfig) + cfg := &jsonConfig{ + Predefined: t.hostPredefined, + IncludePaths: t.hostIncludes, + SysIncludePaths: t.hostSysIncludes, + OS: t.goos, + Arch: t.goarch, + } + b, err := json.Marshal(cfg) + if err != nil { + return err + } + + full := filepath.Join(t.saveConfig, "config.json") + if err := os.MkdirAll(t.saveConfig, 0700); err != nil { + return err + } + + if err := ioutil.WriteFile(full, b, 0600); err != nil { + return err + } + } + + return nil +} + func (t *Task) setLookPaths() (err error) { if t.ccLookPath, err = exec.LookPath(t.cc); err != nil { return err @@ -955,11 +1184,20 @@ func (t *Task) scriptBuild2(script [][]string) error { fmt.Printf("%s\n", cmd) } t2 := NewTask(append(ccgo, args...), t.stdout, t.stderr) + t2.cfg.IncludeFileHandler = t.cfg.IncludeFileHandler t2.cfg.SharedFunctionDefinitions = t.cfg.SharedFunctionDefinitions + t2.configSaved = t.configSaved + t2.configured = t.configured + t2.hostIncludes = t.hostIncludes + t2.hostPredefined = t.hostPredefined + t2.hostSysIncludes = t.hostSysIncludes + t2.includedFiles = t.includedFiles + t2.isScripted = true + t2.loadConfig = t.loadConfig t2.replaceFdZero = t.replaceFdZero t2.replaceTclDefaultDoubleRounding = t.replaceTclDefaultDoubleRounding t2.replaceTclIeeeDoubleRounding = t.replaceTclIeeeDoubleRounding - t2.isScripted = true + t2.saveConfig = t.saveConfig if err := inDir(dir, t2.Main); err != nil { return err } @@ -982,6 +1220,10 @@ func (t *Task) scriptBuild2(script [][]string) error { } t.imported[len(t.imported)-1].used = true // crt is always imported } + if t.saveConfig != "" { + return nil + } + return t.link() } @@ -990,7 +1232,8 @@ type cdb struct { outputIndex map[string][]*cdbItem } -func (db *cdb) find(obj map[string]*cdbItem, nm string, ver, seqLimit int, trace bool, path []string, cc, ar string) error { +func (db *cdb) find(obj map[string]*cdbItem, nm string, ver, seqLimit int, path []string, cc, ar string) error { + // trc("%v: nm %q ver %v seqLimit %v path %q cc %q ar %q", origin(1), nm, ver, seqLimit, path, cc, ar) var item *cdbItem var k string switch { @@ -1059,7 +1302,7 @@ func (db *cdb) find(obj map[string]*cdbItem, nm string, ver, seqLimit int, trace obj[k] = item var errs []string for _, v := range item.sources(cc, ar) { - if err := db.find(obj, v, -1, item.seq, trace, append(path, nm), cc, ar); err != nil { + if err := db.find(obj, v, -1, item.seq, append(path, nm), cc, ar); err != nil { errs = append(errs, err.Error()) } } @@ -1137,7 +1380,7 @@ func (t *Task) useCompileDB(fn string, args []string) error { notFound := false for _, v := range args { v, ver := suffixNum(v, 0) - if err := cdb.find(obj, v, ver, -1, t.traceTranslationUnits, nil, t.ccLookPath, t.arLookPath); err != nil { + if err := cdb.find(obj, v, ver, -1, nil, t.ccLookPath, t.arLookPath); err != nil { notFound = true fmt.Fprintln(os.Stderr, err) } @@ -1174,6 +1417,13 @@ func (t *Task) cdbBuild(obj map[string]*cdbItem, list []string) error { return err } + for _, v := range t.D { + args = append(args, "-D"+v) + } + for _, v := range t.U { + args = append(args, "-U"+v) + } + line := append([]string{it.Directory}, args...) script = append(script, line) } @@ -1212,9 +1462,12 @@ func (t *Task) createCompileDB(command []string) (rerr error) { var cmd *exec.Cmd var parser func(s string) ([]string, error) out: - switch { - case t.goos == "darwin", t.goos == "freebsd": - if command[0] != "make" { + switch t.goos { + case "darwin", "freebsd", "netbsd": + switch command[0] { + case "make", "gmake": + // ok + default: return fmt.Errorf("usupported build command: %s", command[0]) } @@ -1226,7 +1479,7 @@ out: command = append([]string{sh, "-c"}, join(" ", command[0], "SHELL='sh -x'", command[1:])) cmd = exec.Command(command[0], command[1:]...) parser = makeXParser - case t.goos == "windows": + case "windows": if command[0] != "make" { return fmt.Errorf("usupported build command: %s", command[0]) } @@ -1257,7 +1510,12 @@ out: } cmd.Env = append(os.Environ(), "LC_ALL=C") cw := t.newCdbMakeWriter(cwr, cwd, parser) - cmd.Stdout = io.MultiWriter(cw, os.Stdout) + switch { + case t.verboseCompiledb: + cmd.Stdout = io.MultiWriter(cw, os.Stdout) + default: + cmd.Stdout = cw + } cmd.Stderr = cmd.Stdout if dmesgs { dmesg("%v: %v", origin(1), cmd.Args) @@ -1317,12 +1575,32 @@ func isCreateArchive(s string) bool { return false } -func makeXParser(s string) ([]string, error) { - if !strings.HasPrefix(s, "+ ") { +func hasPlusPrefix(s string) (n int, r string) { + for strings.HasPrefix(s, "+") { + n++ + s = s[1:] + } + return n, s +} + +func makeXParser(s string) (r []string, err error) { + n, s := hasPlusPrefix(s) + if n == 0 { return nil, nil } - return shellquote.Split(s[2:]) + if !strings.HasPrefix(s, " ") { + return nil, nil + } + + s = s[1:] + r, err = shellquote.Split(s) + if err != nil { + if strings.Contains(err.Error(), "Unterminated single-quoted string") { + return nil, nil // ignore + } + } + return r, err } func straceParser(s string) ([]string, error) { @@ -1393,12 +1671,16 @@ func (it *cdbItem) ccgoArgs(cc string) (r []string, err error) { set.Arg("o", true, func(opt, arg string) error { return nil }) set.Arg("std", true, func(opt, arg string) error { return nil }) set.Opt("MD", func(opt string) error { return nil }) + set.Opt("MMD", func(opt string) error { return nil }) set.Opt("MP", func(opt string) error { return nil }) + set.Opt("ansi", func(opt string) error { return nil }) set.Opt("c", func(opt string) error { return nil }) set.Opt("g", func(opt string) error { return nil }) set.Opt("pedantic", func(opt string) error { return nil }) set.Opt("pipe", func(opt string) error { return nil }) set.Opt("pthread", func(opt string) error { return nil }) + set.Opt("s", func(opt string) error { return nil }) + set.Opt("w", func(opt string) error { return nil }) if err := set.Parse(it.Arguments[1:], func(arg string) error { switch { case strings.HasSuffix(arg, ".c"): @@ -1411,7 +1693,7 @@ func (it *cdbItem) ccgoArgs(cc string) (r []string, err error) { // nop default: - return fmt.Errorf("unknown/unsupported option: %s", arg) + return fmt.Errorf("unknown/unsupported CC option: %s", arg) } return nil @@ -1470,7 +1752,7 @@ func (it *cdbItem) sources(cc, ar string) (r []string) { return nil } - switch it.Arguments[0] { + switch arg0 := it.Arguments[0]; arg0 { case "libtool", ar, @@ -1478,8 +1760,13 @@ func (it *cdbItem) sources(cc, ar string) (r []string) { var prev string for _, v := range it.Arguments { - if prev != "-o" && strings.HasSuffix(v, ".o") { - r = append(r, filepath.Join(it.Directory, v)) + switch prev { + case "-o", "-MT", "-MF": + // nop + default: + if strings.HasSuffix(v, ".o") { + r = append(r, filepath.Join(it.Directory, v)) + } } prev = v } @@ -1517,7 +1804,7 @@ func (t *Task) newCdbMakeWriter(w *cdbWriter, dir string, parser func(s string) func (w *cdbMakeWriter) fail(err error) { if w.err == nil { - w.err = err + w.err = fmt.Errorf("%v (%v)", err, origin(2)) } } diff --git a/vendor/modernc.org/ccgo/v3/lib/dmesg.go b/vendor/modernc.org/ccgo/v3/lib/dmesg.go index 6a0eb1d63..c7da87ee9 100644 --- a/vendor/modernc.org/ccgo/v3/lib/dmesg.go +++ b/vendor/modernc.org/ccgo/v3/lib/dmesg.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ccgo.dmesg // +build ccgo.dmesg package ccgo // import "modernc.org/ccgo/v3/lib" diff --git a/vendor/modernc.org/ccgo/v3/lib/go.go b/vendor/modernc.org/ccgo/v3/lib/go.go index ede74b734..0b826161d 100644 --- a/vendor/modernc.org/ccgo/v3/lib/go.go +++ b/vendor/modernc.org/ccgo/v3/lib/go.go @@ -6,7 +6,6 @@ package ccgo // import "modernc.org/ccgo/v3/lib" import ( "bytes" - "encoding/binary" "fmt" "go/scanner" "go/token" @@ -84,6 +83,7 @@ const ( exprSelect // foo in foo.bar exprValue // foo in bar = foo exprVoid // + exprGoPtr ) const ( @@ -1902,7 +1902,17 @@ func (p *project) structType(n cc.Node, t cc.Type) string { } } +func (p *project) padName(n *int) string { + if !p.task.exportFieldsValid { + return "_" + } + + *n++ + return fmt.Sprintf("%s__ccgo_pad%d", p.task.exportFields, *n) +} + func (p *project) structLiteral(n cc.Node, t cc.Type) string { + var npad int b := bytesBufferPool.Get().(*bytes.Buffer) defer func() { b.Reset(); bytesBufferPool.Put(b) }() switch t.Kind() { @@ -1911,7 +1921,7 @@ func (p *project) structLiteral(n cc.Node, t cc.Type) string { // trc("%v: %q\n%s", p.pos(n), t.Tag(), info) b.WriteString("struct {") if info.NeedExplicitAlign { - fmt.Fprintf(b, "_[0]uint%d;", 8*p.align(t)) + fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(t)) } var max uintptr for _, off := range info.Offsets { @@ -1937,7 +1947,7 @@ func (p *project) structLiteral(n cc.Node, t cc.Type) string { case pad < 0: continue case pad > 0: - fmt.Fprintf(b, "_ [%d]byte;", pad) + fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) } switch { case f.IsBitField(): @@ -1968,7 +1978,7 @@ func (p *project) structLiteral(n cc.Node, t cc.Type) string { } } if info.PaddingAfter != 0 { - fmt.Fprintf(b, "_ [%d]byte;", info.PaddingAfter) + fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), info.PaddingAfter) } b.WriteByte('}') case cc.Union: @@ -1986,7 +1996,7 @@ func (p *project) structLiteral(n cc.Node, t cc.Type) string { al0 = f.BitFieldBlockWidth() >> 3 } if al != uintptr(al0) { - fmt.Fprintf(b, "_ [0]uint%d;", 8*al) + fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*al) } fsz := ft.Size() switch { @@ -1998,7 +2008,7 @@ func (p *project) structLiteral(n cc.Node, t cc.Type) string { fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(nil, ft)) } if pad := sz - fsz; pad != 0 { - fmt.Fprintf(b, "_ [%d]byte;", pad) + fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) } b.WriteByte('}') default: @@ -3155,8 +3165,8 @@ func (p *project) declaratorValueUnion(n cc.Node, f *function, d *cc.Declarator, p.declaratorDefault(n, d) } -func (p *project) isVolatile(d *cc.Declarator) bool { - if d.Type().IsVolatile() { +func (p *project) isVolatileOrAtomic(d *cc.Declarator) bool { + if d.Type().IsVolatile() || d.Type().IsAtomic() { return true } @@ -3166,7 +3176,7 @@ func (p *project) isVolatile(d *cc.Declarator) bool { func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { if x := p.tlds[d]; x != nil && d.IsStatic() { - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { p.atomicLoadNamedAddr(n, d.Type(), x.name) return } @@ -3177,7 +3187,7 @@ func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { switch x := p.symtab[d.Name().String()].(type) { case *tld: - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { p.atomicLoadNamedAddr(n, d.Type(), x.name) return } @@ -3185,7 +3195,7 @@ func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { p.w("%s", x.name) case *imported: x.used = true - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { p.atomicLoadNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", x.qualifier, d.Name())) return } @@ -3215,6 +3225,31 @@ func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { return } + if !d.IsImplicit() { + nm := d.Name() + name := nm.String() + switch d.Linkage { + case cc.External: + name = p.task.exportExterns + name + tld := &tld{name: name} + p.externs[nm] = tld + p.w("%s", name) + return + case cc.Internal: + if token.IsExported(name) { + name = "s" + name + } + tld := &tld{name: p.scope.take(cc.String(name))} + for _, v := range p.ast.Scope[nm] { + if d, ok := v.(*cc.Declarator); ok { + p.tlds[d] = tld + } + } + p.w("%s", name) + return + } + } + p.err(n, "back-end: undefined: %s", d.Name()) } } @@ -3245,7 +3280,7 @@ func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator if f != nil { if local := f.locals[d]; local != nil { if local.isPinned { - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { p.w("%sAtomicLoadP%s(%s%s/* %s */)", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) return } @@ -3254,7 +3289,7 @@ func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator return } - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { p.atomicLoadNamedAddr(n, d.Type(), local.name) return } @@ -3376,7 +3411,7 @@ func (p *project) declaratorLValueArray(n cc.Node, f *function, d *cc.Declarator } func (p *project) declaratorLValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { panic(todo("", n.Position(), d.Position())) } @@ -3420,6 +3455,7 @@ func (p *project) declaratorLValueDefault(n cc.Node, d *cc.Declarator) { } } } + panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) } } @@ -3643,6 +3679,7 @@ func (p *project) declaratorAddrOfArray(n cc.Node, f *function, d *cc.Declarator } func (p *project) convertType(n cc.Node, from, to cc.Type, flags flags) string { + // trc("%v: %v: %v -> %v %v", n.Position(), origin(1), from, to, flags) //TODO- DBG if from != nil { switch from.Kind() { case cc.Int128: @@ -3907,6 +3944,10 @@ func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) str return p.convertInt(n, op, to, flags) } + if from == to { + return "" + } + switch from.Kind() { case cc.Ptr: if !force && from.Kind() == to.Kind() { @@ -3918,16 +3959,27 @@ func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) str return ")" } - panic(todo("%v: %q -> %q", p.pos(n), from, to)) + if to.Kind() == cc.Ptr { + return "" + } + + panic(todo("%v: force %v, %q %v -> %q %v", p.pos(n), force, from, from.Kind(), to, to.Kind())) case cc.Function, cc.Struct, cc.Union: if !force && from.Kind() == to.Kind() { return "" } - panic(todo("%q -> %q", from, to)) + trc("%p %p", from, to) + panic(todo("%q %v -> %q %v", from, from.Kind(), to, to.Kind())) case cc.Double, cc.Float: - p.w("%s(", p.typ(n, to)) - return ")" + switch { + case to.IsIntegerType(): + p.w("%s(", p.helperType2(n, from, to)) + return ")" + default: + p.w("%s(", p.typ(n, to)) + return ")" + } case cc.Array: if from.Kind() == to.Kind() { return "" @@ -5080,7 +5132,7 @@ func (p *project) assignmentExpressionValueAddrOf(f *function, n *cc.AssignmentE lhs := n.UnaryExpression switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { - case opStruct: + case opStruct, opUnion: p.assignmentExpressionValueAssignStructAddrof(f, n, n.Operand.Type(), mode, flags) default: panic(todo("", n.Position(), k)) @@ -5098,10 +5150,19 @@ func (p *project) assignmentExpressionValueAssignStructAddrof(f *function, n *cc if d := n.UnaryExpression.Declarator(); d != nil { if local := f.locals[d]; local != nil { if local.isPinned { - panic(todo("", p.pos(n))) + if !p.pass1 { + p.w("%sXmemmove(tls, ", p.task.crt) + p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags|fOutermost) + p.w(", ") + p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags|fOutermost) + p.w(", %d)", lhs.Size()) + return + } } - panic(todo("", p.pos(n))) + if !p.pass1 { + panic(todo("", p.pos(n))) + } } } @@ -5185,30 +5246,11 @@ func (p *project) assignmentExpressionValueAssignBitfield(f *function, n *cc.Ass lt := lhs.Operand.Type() bf := lt.BitField() defer p.w("%s", p.convertType(n, lt, t, flags)) - switch { - case bf.Type().IsSignedType(): - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - break - } - - p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) - p.unaryExpression(f, lhs, lt, exprAddrOf, flags) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags|fOutermost) - p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) - default: - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - break - } - - p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) - p.unaryExpression(f, lhs, lt, exprAddrOf, flags) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags|fOutermost) - p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) - } + p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) + p.unaryExpression(f, lhs, lt, exprAddrOf, flags) + p.w(", ") + p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags|fOutermost) + p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) } func (p *project) assignmentExpressionValueAssignNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { @@ -5268,7 +5310,7 @@ func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpressi p.assignmentExpression(f, n.AssignmentExpression, lt, exprCondInit, flags|fOutermost) p.w(";") default: - if d != nil && p.isVolatile(d) { + if d != nil && p.isVolatileOrAtomic(d) { p.setVolatileDeclarator(d, f, n.AssignmentExpression, lt, mode, flags|fOutermost) return } @@ -5278,11 +5320,6 @@ func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpressi p.assignmentExpression(f, n.AssignmentExpression, lt, mode, flags|fOutermost) } case opBitfield: - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - panic(todo("", n.Position())) - break - } - bf := lt.BitField() p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) p.unaryExpression(f, lhs, lt, exprAddrOf, flags) @@ -5561,7 +5598,34 @@ func (p *project) conditionalExpressionFunc(f *function, n *cc.ConditionalExpres case cc.ConditionalExpressionLOr: // LogicalOrExpression p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - panic(todo("", p.pos(n))) + switch ot := n.Operand.Type(); ot.Kind() { + case cc.Function: + if t.Kind() != cc.Function { + panic(todo("", n.Position())) + } + default: + panic(todo("", ot.Kind())) + } + + p.w(" func() ") + p.functionSignature(f, t, "") + p.w("{ if ") + p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags|fOutermost) + p.w(" { return ") + switch d := n.Expression.Declarator(); { + case d != nil: + p.declaratorDefault(n, d) + default: + panic(todo("", n.Position())) + } + p.w("}; return ") + switch d := n.ConditionalExpression.Declarator(); { + case d != nil: + p.declaratorDefault(n, d) + default: + panic(todo("", n.Position())) + } + p.w("}()") default: panic(todo("%v: internal error: %v", n.Position(), n.Case)) } @@ -7129,16 +7193,11 @@ func (p *project) binaryShiftExpressionBool(f *function, n *cc.ShiftExpression, defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) switch { case n.ShiftExpression.Operand.Type().IsBitFieldType(): - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - return - } - p.w("(") p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) p.w(" %s%s", oper, tidyComment(" ", &n.Token)) p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w(")&%#x", n.ShiftExpression.Operand.Type().BitField().Mask()) + p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) p.w(" %s%s", oper, tidyComment(" ", &n.Token)) @@ -7166,6 +7225,10 @@ func shiftOp(s string) string { } } +func bfValueMask(bf cc.Field) uint64 { + return uint64(1)<<bf.BitFieldWidth() - 1 +} + func (p *project) binaryShiftExpressionValue(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { // ShiftExpression "<<" AdditiveExpression flags &^= fOutermost @@ -7178,16 +7241,11 @@ func (p *project) binaryShiftExpressionValue(f *function, n *cc.ShiftExpression, p.additiveExpression(f, n.AdditiveExpression, p.intType, exprValue, flags|fOutermost) p.w(")") case n.ShiftExpression.Operand.Type().IsBitFieldType(): - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - return - } - p.w("(") p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) p.w(" %s%s", oper, tidyComment(" ", &n.Token)) p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w(")&%#x", n.ShiftExpression.Operand.Type().BitField().Mask()) + p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) p.w(" %s%s", oper, tidyComment(" ", &n.Token)) @@ -8174,7 +8232,7 @@ func (p *project) castExpressionValueNormal(f *function, n *cc.CastExpression, t case cc.Void: p.castExpression(f, n.CastExpression, tn, exprVoid, flags) default: - panic(todo("", n.Position(), t, t.Kind())) + panic(todo("%s: %s %s -> %s %s -> %s %s", n.Position(), op.Type(), op.Type().Kind(), tn, tn.Kind(), t, t.Kind())) } } } @@ -8268,6 +8326,10 @@ func (p *project) unaryExpressionSelect(f *function, n *cc.UnaryExpression, t cc default: panic(todo("", p.pos(n), et, et.Kind())) } + case cc.Array: + p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) + p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) + p.w(")))") default: panic(todo("", p.pos(n), ot, ot.Kind())) } @@ -8318,11 +8380,8 @@ func (p *project) unaryExpressionFunc(f *function, n *cc.UnaryExpression, t cc.T case cc.Ptr: switch et2 := et.Elem(); et2.Kind() { case cc.Function: - p.w("(**(**") - p.functionSignature(f, et2, "") - p.w(")(unsafe.Pointer(") - p.castExpression(f, n.CastExpression, ot, exprAddrOf, flags|fAddrOfFuncPtrOk) - p.w(")))") + // C: (**)() + p.fnVal(n, f, func() { p.castExpression(f, n.CastExpression, p.ptrType, exprValue, flags|fAddrOfFuncPtrOk) }, n.CastExpression.Declarator(), n.CastExpression.Operand.Type(), 1, mode, flags) default: panic(todo("", p.pos(n), et2, et2.Kind())) } @@ -8580,6 +8639,8 @@ func (p *project) unaryExpressionValue(f *function, n *cc.UnaryExpression, t cc. et.Kind() == cc.Union: p.unaryExpressionDeref(f, n, t, mode, flags) + case et.Kind() == cc.Function: + p.castExpression(f, n.CastExpression, t, mode, flags) default: panic(todo("", p.pos(n), et, et.Kind())) } @@ -8908,7 +8969,7 @@ func (p *project) unaryExpressionPreIncDecVoidArrayParameter(f *function, n *cc. func (p *project) unaryExpressionPreIncDecVoidNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { // "++" UnaryExpression etc. ut := n.UnaryExpression.Operand.Type() - if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatile(d) { + if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { x := "Dec" if oper == "++" { x = "Inc" @@ -9180,6 +9241,7 @@ func (p *project) postfixExpressionBool(f *function, n *cc.PostfixExpression, t } func (p *project) postfixExpressionPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { + // PostfixExpression "->" IDENTIFIER switch n.Case { case cc.PostfixExpressionPrimary: // PrimaryExpression p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) @@ -9422,9 +9484,27 @@ func (p *project) postfixExpressionSelectPSelectStruct(f *function, n *cc.Postfi } pe := n.PostfixExpression.Operand.Type() defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w(")).%s", p.fieldName(n, n.Token2.Value)) + et := n.PostfixExpression.Operand.Type().Elem() + fld, path, ok := et.FieldByName2(n.Token2.Value) + switch { + case !ok: + panic(todo("", n.Token.Position())) + case fld.InUnion(): + p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) + p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) + p.w("%s)))", nonZeroUintptr(pathOff(et, path))) + case len(path) != 1: + panic(todo("", n.Token.Position())) + default: + p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) + switch { + case pe.Kind() == cc.Array: + p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) + default: + p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) + } + p.w(")).%s", p.fieldName(n, n.Token2.Value)) + } } } @@ -9570,13 +9650,32 @@ func (p *project) postfixExpressionAddrOf(f *function, n *cc.PostfixExpression, case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' p.postfixExpressionAddrOfIndex(f, n, t, mode, flags) case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - panic(todo("", p.pos(n))) + ot := n.Operand.Type() + switch ot.Kind() { + case cc.Struct, cc.Union: + // ok + default: + p.err(n, "cannot take address of value of type %v", n.Operand.Type()) + return + } + + if p.pass1 { + off := roundup(f.off, uintptr(ot.Align())) + f.complits[n] = off + f.off += ot.Size() + return + } + + off := f.complits[n] + p.w("func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, ot), f.bpName, nonZeroUintptr(off)) + p.postfixExpressionValue(f, n, ot, exprValue, flags) + p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER p.postfixExpressionAddrOfSelect(f, n, t, mode, flags) case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER p.postfixExpressionAddrOfPSelect(f, n, t, mode, flags) case cc.PostfixExpressionInc: // PostfixExpression "++" - panic(todo("", p.pos(n))) + p.postfixExpressionIncDec(f, n, "++", "+=", t, exprLValue, flags) case cc.PostfixExpressionDec: // PostfixExpression "--" panic(todo("", p.pos(n))) case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' @@ -9734,11 +9833,7 @@ func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t case cc.Ptr: switch et := n.Operand.Type().Elem(); et.Kind() { case cc.Function: - p.w("(*(*") - p.functionSignature(f, n.Operand.Type().Elem(), "") - p.w(")(unsafe.Pointer(") - p.postfixExpression(f, n, n.Operand.Type(), exprAddrOf, flags) - p.w(")))") + p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) default: panic(todo("", p.pos(n), et, et.Kind())) } @@ -9749,26 +9844,7 @@ func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t panic(todo("", n.Position(), n.Operand.Type())) } case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - switch n.Operand.Type().Kind() { - case cc.Ptr: - switch n.Operand.Type().Kind() { - case cc.Ptr: - switch et := n.Operand.Type().Elem(); et.Kind() { - case cc.Function: - p.w("(*(*") - p.functionSignature(f, n.Operand.Type().Elem(), "") - p.w(")(unsafe.Pointer(") - p.postfixExpression(f, n, n.Operand.Type(), exprAddrOf, flags) - p.w(")))") - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("", p.pos(n), n.Operand.Type(), n.Operand.Type().Kind())) - } - default: - panic(todo("", n.Position(), n.Operand.Type())) - } + p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) case cc.PostfixExpressionInc: // PostfixExpression "++" panic(todo("", p.pos(n))) case cc.PostfixExpressionDec: // PostfixExpression "--" @@ -9804,7 +9880,30 @@ func (p *project) postfixExpressionVoid(f *function, n *cc.PostfixExpression, t case cc.PostfixExpressionDec: // PostfixExpression "--" p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) + tn := n.TypeName.Type() + switch tn.Decay().Kind() { + case cc.Ptr: + switch tn.Kind() { + case cc.Array: + switch { + case p.pass1: + off := roundup(f.off, uintptr(tn.Elem().Align())) + f.complits[n] = off + f.off += tn.Size() + default: + off := f.complits[n] + p.w("*(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) + p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) + } + return + default: + panic(todo("%v: %v", n.Position(), tn)) + } + } + + defer p.w("%s", p.convertType(n, tn, t, flags)) + p.w("_ = ") + p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' panic(todo("", p.pos(n))) case cc.PostfixExpressionChooseExpr: @@ -9903,6 +10002,39 @@ func (p *project) postfixExpressionValue(f *function, n *cc.PostfixExpression, t // Note: This construct is only available for C. p.w(" %d ", n.Operand.Value()) case cc.PostfixExpressionChooseExpr: // "__builtin_choose_expr" '(' AssignmentExpression ',' AssignmentExpression ',' AssignmentExpression ')' + // You can use the built-in function __builtin_choose_expr to evaluate code + // depending on the value of a constant expression. This built-in function + // returns exp1 if const_exp, which is an integer constant expression, is + // nonzero. Otherwise it returns exp2. + // + // This built-in function is analogous to the ‘? :’ operator in C, except that + // the expression returned has its type unaltered by promotion rules. Also, the + // built-in function does not evaluate the expression that is not chosen. For + // example, if const_exp evaluates to true, exp2 is not evaluated even if it + // has side effects. + // + // This built-in function can return an lvalue if the chosen argument is an + // lvalue. + // + // If exp1 is returned, the return type is the same as exp1’s type. Similarly, + // if exp2 is returned, its return type is the same as exp2. + // + // Example: + // + // #define foo(x) \ + // __builtin_choose_expr ( \ + // __builtin_types_compatible_p (typeof (x), double), \ + // foo_double (x), \ + // __builtin_choose_expr ( \ + // __builtin_types_compatible_p (typeof (x), float), \ + // foo_float (x), \ + // /* The void expression results in a compile-time error \ + // when assigning the result to something. */ \ + // (void)0)) + // + // Note: This construct is only available for C. Furthermore, the unused + // expression (exp1 or exp2 depending on the value of const_exp) may still + // generate syntax errors. This may change in future revisions. switch op := n.AssignmentExpression.Operand; { case op.IsNonZero(): p.assignmentExpression(f, n.AssignmentExpression2, t, mode, flags) @@ -9965,11 +10097,6 @@ func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.Postfix defer p.w("%s", p.convertType(n, fld.Promote(), t, flags)) switch pe.Kind() { case cc.Array: - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - return - } - x := p.convertType(n, nil, fld.Promote(), flags) p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) @@ -9981,18 +10108,6 @@ func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.Postfix p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) } default: - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - x := p.convertType(n, nil, fld.Promote(), flags) - p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.bitFldOff(pe.Elem(), n.Token2) - p.w("))>>%d&%#x%s", fld.BitFieldBlockWidth()-fld.BitFieldOffset()-fld.BitFieldWidth(), uint64(1)<<fld.BitFieldWidth()-1, x) - if fld.Type().IsSignedType() { - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - break - } - x := p.convertType(n, nil, fld.Promote(), flags) p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) @@ -10015,10 +10130,33 @@ func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.Postfix p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) } defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w(")).%s", p.fieldName(n, n.Token2.Value)) + et := pe.Elem() + fld, path, ok := et.FieldByName2(n.Token2.Value) + switch { + case !ok: + panic(todo("")) + case fld.InUnion(): + p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) + p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) + p.w("%s))", nonZeroUintptr(pathOff(et, path))) + case len(path) != 1: + panic(todo("")) + default: + p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) + p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) + p.w(")).%s", p.fieldName(n, n.Token2.Value)) + } + } +} + +func pathOff(t cc.Type, path []int) (r uintptr) { + for len(path) != 0 { + f := t.FieldByIndex(path[:1]) + r += f.Offset() + path = path[1:] + t = f.Type() } + return r } func (p *project) postfixExpressionValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { @@ -10154,16 +10292,8 @@ func (p *project) postfixExpressionValueSelectUnion(f *function, n *cc.PostfixEx // PostfixExpression '.' IDENTIFIER pe := n.PostfixExpression.Operand.Type() fld := n.Field - if fld.Offset() != 0 { - p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) - } switch { case n.Operand.Type().IsBitFieldType(): - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.todo(n, t) - return - } - p.w("(") defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) x := p.convertType(n, nil, fld.Promote(), flags) @@ -10193,20 +10323,6 @@ func (p *project) postfixExpressionValueSelectStruct(f *function, n *cc.PostfixE fld := n.Field switch { case n.Operand.Type().IsBitFieldType(): - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - p.w("(") - defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) - x := p.convertType(n, nil, fld.Promote(), flags) - p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.bitFldOff(pe, n.Token2) - p.w("))>>%d&%#x%s", fld.BitFieldBlockWidth()-fld.BitFieldOffset()-fld.BitFieldWidth(), uint64(1)<<fld.BitFieldWidth()-1, x) - if fld.Type().IsSignedType() { - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - break - } - p.w("(") defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) x := p.convertType(n, nil, fld.Promote(), flags) @@ -10509,10 +10625,6 @@ func (p *project) postfixExpressionIncDecValueArrayParameter(f *function, n *cc. } func (p *project) postfixExpressionIncDecValueBitfield(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - panic(todo("", n.Position())) - } - // PostfixExpression "++" pe := n.PostfixExpression.Operand.Type() defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) @@ -10534,7 +10646,7 @@ func (p *project) postfixExpressionIncDecValueNormal(f *function, n *cc.PostfixE if oper == "++" { x = "Inc" } - if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatile(d) { + if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { p.w("%sPost%sAtomic%s(&", p.task.crt, x, p.helperType(n, pe)) var local *local var tld *tld @@ -10594,7 +10706,7 @@ func (p *project) postfixExpressionIncDecVoid(f *function, n *cc.PostfixExpressi } func (p *project) postfixExpressionIncDecVoidNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatile(d) { + if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { switch d.Type().Size() { case 4, 8: if !d.Type().IsIntegerType() { @@ -10750,8 +10862,12 @@ func (p *project) postfixExpressionCallBool(f *function, n *cc.PostfixExpression } } + var va uintptr + if f != nil { + va = f.vaLists[n] + } p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags&^fOutermost) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, f.vaLists[n]) + p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) } func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { @@ -10796,8 +10912,12 @@ func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpressio return } } + var va uintptr + if f != nil { + va = f.vaLists[n] + } p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags&^fOutermost) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, f.vaLists[n]) + p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) } // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) @@ -10991,8 +11111,12 @@ func (p *project) postfixExpressionCallVoid(f *function, n *cc.PostfixExpression return } } + var va uintptr + if f != nil { + va = f.vaLists[n] + } p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags&^fOutermost) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, f.vaLists[n]) + p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) } // void __atomic_store_n (type *ptr, type val, int memorder) @@ -11057,7 +11181,12 @@ func (p *project) argList(n *cc.ArgumentExpressionList) (r []*cc.AssignmentExpre } func (p *project) argumentExpressionList(f *function, pe *cc.PostfixExpression, n *cc.ArgumentExpressionList, bpOff uintptr) { - p.w("(%s", f.tlsName) + switch { + case f == nil: + p.w("(nil") + default: + p.w("(%s", f.tlsName) + } ft := funcType(pe.Operand.Type()) isVariadic := ft.IsVariadic() params := ft.Parameters() @@ -11368,7 +11497,7 @@ func (p *project) primaryExpressionBool(f *function, n *cc.PrimaryExpression, t case cc.PrimaryExpressionChar: // CHARCONST panic(todo("", p.pos(n))) case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) + p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) case cc.PrimaryExpressionString: // STRINGLITERAL p.w(" 1 ") case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL @@ -11478,7 +11607,7 @@ func (p *project) primaryExpressionAddrOf(f *function, n *cc.PrimaryExpression, case cc.PrimaryExpressionString: // STRINGLITERAL p.w("%s", p.stringLiteral(n.Operand.Value())) case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) + p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) case cc.PrimaryExpressionExpr: // '(' Expression ')' p.expression(f, n.Expression, t, mode, flags) case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' @@ -11491,28 +11620,7 @@ func (p *project) primaryExpressionAddrOf(f *function, n *cc.PrimaryExpression, func (p *project) primaryExpressionFunc(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { switch n.Case { case cc.PrimaryExpressionIdent: // IDENTIFIER - switch d := n.Declarator(); { - case d != nil: - switch d.Type().Kind() { - case cc.Function: - p.declarator(n, f, d, t, mode, flags) - case cc.Ptr: - switch et := d.Type().Elem(); et.Kind() { - case cc.Function: - p.w("(*(*") - p.functionSignature(f, et, "") - p.w(")(unsafe.Pointer(&") - p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) - p.w(")))") - default: - panic(todo("", p.pos(n), p.pos(d), d.Type(), d.Type().Kind())) - } - default: - panic(todo("", p.pos(n), p.pos(d), d.Type(), d.Type().Kind())) - } - default: - panic(todo("", p.pos(n))) - } + p.fnVal(n, f, func() { p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) }, n.Declarator(), n.Operand.Type(), 0, mode, flags) case cc.PrimaryExpressionInt: // INTCONST panic(todo("", p.pos(n))) case cc.PrimaryExpressionFloat: // FLOATCONST @@ -11725,6 +11833,7 @@ func (p *project) charConst(n cc.Node, src string, op cc.Operand, to cc.Type, fl defer p.w("%s", p.convert(n, op, to, flags)) case to.Kind() == cc.Ptr && op.IsZero(): p.w(" 0 ") + return default: panic(todo("%v: t %v, to %v, to.Alias() %v", n.Position(), op.Type(), to, to.Alias())) } @@ -12066,10 +12175,6 @@ func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, panic(todo("")) } - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - panic(todo("", n.Position())) - } - ot := n.Operand.Type() lhs := n.UnaryExpression bf := lhs.Operand.Type().BitField() @@ -12099,10 +12204,6 @@ func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, } func (p *project) readBitfield(n cc.Node, ptr string, bf cc.Field, promote cc.Type) { - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - panic(todo("", n.Position())) - } - bw := bf.BitFieldBlockWidth() m := bf.Mask() o := bf.BitFieldOffset() @@ -12234,10 +12335,6 @@ func (p *project) assignOpVoidArrayParameter(f *function, n *cc.AssignmentExpres } func (p *project) assignOpVoidBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - if p.task.cfg.ABI.ByteOrder == binary.BigEndian { - panic(todo("", n.Position())) - } - // UnaryExpression "*=" AssignmentExpression etc. lhs := n.UnaryExpression lt := lhs.Operand.Type() @@ -12277,7 +12374,7 @@ func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t rop := n.AssignmentExpression.Operand if d := n.UnaryExpression.Declarator(); d != nil { if local := f.locals[d]; local != nil && local.isPinned { - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { panic(todo("")) } @@ -12301,7 +12398,7 @@ func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t return } - if p.isVolatile(d) { + if p.isVolatileOrAtomic(d) { var local *local var tld *tld var nm string @@ -12539,32 +12636,38 @@ func (p *project) iterationStatement(f *function, n *cc.IterationStatement) { } p.statement(f, n.Statement, true, false, false, 0) case cc.IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement - if f.hasJumps { - panic(todo("", p.pos(n))) - } - var ids []*cc.InitDeclarator for list := n.Declaration.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { ids = append(ids, list.InitDeclarator) } - if len(ids) != 1 { - panic(todo("")) - } - id := ids[0] - d := id.Declarator - local := f.locals[d] - p.w("for %s := ", local.name) - p.assignmentExpression(f, id.Initializer.AssignmentExpression, d.Type(), exprValue, fForceConv) + // declaration + // a: if !expr goto c + // stmt + // b: expr2 // label for continue + // goto a + // c: + a := f.flatLabel() + b := f.flatLabel() + f.continueCtx = b + c := f.flatLabel() + f.breakCtx = c + p.w("{") + p.declaration(f, n.Declaration, false) p.w(";") + p.w("__%d:", a) if n.Expression != nil { + p.w("if !(") p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, fOutermost) + p.w(") { goto __%d }", c) } - p.w("; ") + p.w(";") + p.statement(f, n.Statement, false, false, false, 0) + p.w(";goto __%d; __%[1]d:", b) if n.Expression2 != nil { p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fOutermost|fNoCondAssignment) } - p.statement(f, n.Statement, true, false, false, 0) + p.w("; goto __%d; goto __%d;__%[2]d:\n}", a, c) default: panic(todo("%v: internal error: %v", n.Position(), n.Case)) } @@ -12903,3 +13006,63 @@ func (p *project) paramTyp(n cc.Node, t cc.Type) string { func (p *project) dbg(a ...interface{}) { p.w("/*DBG.%v %v */", a, origin(2)) } + +func (p *project) fnVal(n cc.Node, f *function, expr func(), exprDecl *cc.Declarator, exprType cc.Type, deref int, mode exprMode, flags flags) { + // C type Go type + // fn N/A: produce name from exprDecl + // (*)() func() + // (**)() *func() + + if deref < 0 || deref > 1 { + panic(todo("")) + } + + switch exprType.Kind() { + case cc.Function: + // C: fn + switch deref { + case 0: + p.declarator(n, f, exprDecl, exprType, mode, flags) + default: + panic(todo("", n.Position())) + } + case cc.Ptr: + switch et := exprType.Elem(); et.Kind() { + case cc.Function: + // C: (*)() + switch deref { + case 0: + // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() + p.w("(*struct{ f ") + p.functionSignature(f, et, "") + p.w("})(unsafe.Pointer(&struct{uintptr}{") + expr() + p.w("})).f") + default: + p.declarator(n, f, exprDecl, et, mode, flags) + } + case cc.Ptr: + switch et2 := et.Elem(); et2.Kind() { + case cc.Function: + // C: (**)() + switch deref { + case 0: + panic(todo("", n.Position())) + default: + // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() + p.w("(*(**struct{ f ") + p.functionSignature(f, et2, "") + p.w("})(unsafe.Pointer(&struct{uintptr}{") + expr() + p.w("}))).f") + } + default: + panic(todo("", n.Position(), et2.Kind(), deref)) + } + default: + panic(todo("", n.Position(), et.Kind(), deref)) + } + default: + panic(todo("", n.Position(), exprType.Kind(), deref)) + } +} diff --git a/vendor/modernc.org/ccgo/v3/lib/init.go b/vendor/modernc.org/ccgo/v3/lib/init.go index d57113a9a..ad443cd2e 100644 --- a/vendor/modernc.org/ccgo/v3/lib/init.go +++ b/vendor/modernc.org/ccgo/v3/lib/init.go @@ -38,7 +38,7 @@ func (p *project) initializer(f *function, n *cc.Initializer, t cc.Type, sc cc.S } if a.Field == nil || b.Field == nil || !a.Field.IsBitField() || !b.Field.IsBitField() { - panic(todo("%v: internal error: %#x, %v: %#x", a.Position(), a.Offset, b.Position(), b.Offset)) + panic(todo("%v: internal error: off %#x, %v: off %#x, t %v", a.Position(), a.Offset, b.Position(), b.Offset, t)) } return a.Field.BitFieldOffset() < b.Field.BitFieldOffset() @@ -87,9 +87,6 @@ func (p *project) initializerInner(tag string, off uintptr, f *function, s []*cc if k == cc.Array && len(s) == 1 { et := t.Elem() - if dmesgs { //TODO- - dmesg("%v: %v", s[0].Position(), et) - } switch { case isCharType(et): // 14: An array of character type may be initialized by a character string @@ -147,13 +144,13 @@ func (p *project) initializerInner(tag string, off uintptr, f *function, s []*cc case cc.Union: p.initializerUnion(tag, off, f, s, t, sc, tld, lm, tm) default: - panic(todo("%v: internal error: %v %v", s[0].Position(), t, len(s))) + panic(todo("%v: internal error: %v alias %v %v", s[0].Position(), t, t.Alias(), len(s))) } } func (p *project) initializerArray(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) { if len(s) == 0 { - p.w("%s{}", p.typ(nil, t)) + p.w("%s%s{}", tag, p.typ(nil, t)) return } @@ -172,7 +169,7 @@ func (p *project) initializerArray(tag string, off uintptr, f *function, s []*cc for _, parts = range a { var comma *cc.Token comma = parts[len(parts)-1].TrailingComma() - elemOff := parts[0].Offset - off + elemOff := (parts[0].Offset - off) / esz * esz tag = "" if mustIndex { tag = fmt.Sprintf("%d:", elemOff/esz) @@ -217,7 +214,7 @@ func (p *project) initializerArrayElement(off uintptr, s []*cc.Initializer, elem func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) { if len(s) == 0 { - p.w("%s{}", p.typ(nil, t)) + p.w("%s%s{}", tag, p.typ(nil, t)) return } @@ -232,7 +229,7 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c var fld cc.Field for len(s) != 0 { var comma *cc.Token - s, fld, parts, isZero = p.initializerStructField(off, s, t) + s, fld, parts, isZero = p.structInitializerParts(off, s, t) if isZero { continue } @@ -246,6 +243,8 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c ft := fld.Type() switch { case fld.IsBitField(): + bft := p.bitFileType(parts[0], fld.BitFieldBlockWidth()) + off0 := fld.Offset() first := true for _, v := range parts { if v.AssignmentExpression.Operand.IsZero() { @@ -257,12 +256,11 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c } first = false bitFld := v.Field - bft := p.bitFileType(bitFld.BitFieldBlockWidth()) p.w("%s%s", tidyComment("", v.AssignmentExpression), tag) tag = "" p.assignmentExpression(f, v.AssignmentExpression, bft, exprValue, fOutermost) p.w("&%#x", uint64(1)<<uint64(bitFld.BitFieldWidth())-1) - if o := bitFld.BitFieldOffset(); o != 0 { + if o := bitFld.BitFieldOffset() + 8*int((bitFld.Offset()-off0)); o != 0 { p.w("<<%d", o) } } @@ -283,154 +281,141 @@ func (p *project) preCommaSep(comma *cc.Token) { p.w("%s", strings.TrimSpace(comma.Sep.String())) } -func (p *project) initializerStructField(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) { - r = s - isZero = true - valueOff := s[0].Offset - nf := t.NumField() - nextOff := off + t.Size() - bits := false - for i := []int{0}; i[0] < nf; i[0]++ { - fld2 := t.FieldByIndex(i) - if fld2.Name() == 0 { - continue - } +func (p *project) structInitializerParts(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) { + if len(s) == 0 { + return nil, nil, nil, true + } - if fld == nil { - fld = fld2 - } - if fld2.Offset()+off > valueOff { - nextOff = off + fld2.Offset() + part := s[0] + isZero = part.AssignmentExpression.Operand.IsZero() + parts = append(parts, part) + s = s[1:] + fld, _, fNext := p.containingStructField(part, off, t) + for len(s) != 0 { + part = s[0] + vOff := part.Offset + if vOff >= fNext { break } - if !fld2.IsBitField() { - fld = fld2 - continue - } - - fld = fld2.BitFieldBlockFirst() + isZero = isZero && part.AssignmentExpression.Operand.IsZero() + parts = append(parts, part) + s = s[1:] } - for len(s) != 0 { - if v := s[0]; v.Offset < nextOff || v.Type().Size() == 0 { - if v.Field != nil && v.Field.IsBitField() { - bits = true - } - s = s[1:] - parts = append(parts, v) - if !v.AssignmentExpression.Operand.IsZero() { - isZero = false - } + return s, fld, parts, isZero +} + +func (p *project) containingStructField(part *cc.Initializer, off uintptr, t cc.Type) (f cc.Field, fOff, fNext uintptr) { + nf := t.NumField() + vOff := part.Offset + for i := []int{0}; i[0] < nf; i[0]++ { + f = t.FieldByIndex(i) + if f.IsBitField() && f.Name() == 0 { // Anonymous bit fields cannot be initialized. continue } - break - } - if bits && fld.Name() == 0 { - for _, v := range parts { - if v.Field != nil && v.Field.Name() != 0 { - fld = v.Field - break - } + fOff = off + f.Offset() + switch { + case f.IsBitField(): + fNext = fOff + uintptr(f.BitFieldBlockWidth())>>3 + default: + fNext = fOff + f.Type().Size() + } + if vOff >= fOff && vOff < fNext { + return f, fOff, fNext } } - return r[len(parts):], fld, parts, isZero + + panic(todo("%v: internal error", pos(part))) } func (p *project) initializerUnion(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) { if len(s) == 0 { - p.w("%s{}", p.typ(nil, t)) + p.w("%s%s{}", tag, p.typ(nil, t)) return } - s0 := s[0] - var parts []*cc.Initializer - var isZero bool - var fld cc.Field - s, fld, parts, isZero = p.initializerUnionField(off, s, t) - if len(s) != 0 { - panic(todo("%v: internal error: %v", s0.Position(), t)) - } - - if isZero { - p.w("%s%s%s{", initComment(s0, lm), tag, p.typ(s0, t)) - p.w("%s}", initComment(parts[len(parts)-1], tm)) + if t.HasFlexibleMember() { + p.err(s[0], "flexible array members not supported") return } - if fld0 := parts[0].FirstDesignatorField(); fld0 != nil && fld0.Index() != 0 { - if fld0.IsBitField() || fld.IsBitField() { - panic(todo("")) - } - - fld := parts[0].Field - if fld.IsBitField() { - panic(todo("")) - } - - // tag: *(*T)(unsafe.Pointer(&struct{f: ft; pad _[n]byte}{f: expr})) - p.w("%s *(*%s)(unsafe.Pointer(&struct{f %s", tag, p.typ(s0, t), p.typ(s0, fld.Type())) - if pad := t.Size() - fld.Type().Size(); pad != 0 { - p.w("; _ [%v]byte", pad) - } - p.w("}{") - p.initializerInner("f:", off+fld.Offset(), f, parts, fld.Type(), sc, tld, fld, lm, tm) - p.w("}))") + parts, isZero := p.initializerUnionField(off, s, t) + if len(parts) == 0 || isZero { + p.w("%s%s%s{", initComment(s[0], lm), tag, p.typ(s[0], t)) + p.w("%s}", initComment(parts[len(parts)-1], tm)) return } - p.w("%s%s%s{", initComment(s0, lm), tag, p.typ(s0, t)) - ft := fld.Type() - tag = fmt.Sprintf("%s:", p.fieldName2(parts[0], fld)) - switch { - case fld.IsBitField(): - first := true - for _, v := range parts { - if v.AssignmentExpression.Operand.IsZero() { - continue - } - - if !first { - p.w("|") + p.w("%sfunc() (r %s) {", tag, p.typ(parts[0], t)) + for _, part := range parts { + var ft cc.Type + fld := part.Field + if fld != nil && fld.IsBitField() { + } + + if ft == nil { + ft = part.Type() + } + if ft.Kind() == cc.Array { + et := ft.Elem() + switch { + case isCharType(et): + switch x := part.AssignmentExpression.Operand.Value().(type) { + case cc.StringValue: + str := cc.StringID(x).String() + slen := uintptr(len(str)) + 1 + alen := ft.Len() + switch { + case alen < slen-1: + p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str[:alen])) + case alen < slen: + p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str)) + default: // alen >= slen + p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str+strings.Repeat("\x00", int(alen-slen)))) + } + continue + default: + panic(todo("%v: %v <- %T", pos(part), et, x)) + } + case p.isWCharType(et): + panic(todo("")) } - first = false - bitFld := v.Field - bft := p.bitFileType(bitFld.BitFieldBlockWidth()) - p.w("%s%s", tidyComment("", v.AssignmentExpression), tag) - tag = "" - p.assignmentExpression(f, v.AssignmentExpression, bft, exprValue, fOutermost) - p.w("&%#x", uint64(1)<<uint64(bitFld.BitFieldWidth())-1) - if o := bitFld.BitFieldOffset(); o != 0 { + ft = et + } + switch { + case fld != nil && fld.IsBitField(): + bft := p.bitFileType(part, fld.BitFieldBlockWidth()) + p.w("*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)) |= ", p.typ(part, bft), part.Offset-off) + p.assignmentExpression(f, part.AssignmentExpression, bft, exprValue, fOutermost) + p.w("&%#x", uint64(1)<<uint64(fld.BitFieldWidth())-1) + if o := fld.BitFieldOffset(); o != 0 { p.w("<<%d", o) } + default: + p.w("*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)) = ", p.typ(part, ft), part.Offset-off) + p.assignmentExpression(f, part.AssignmentExpression, ft, exprValue, fOutermost) } - default: - p.initializerInner(tag, off+fld.Offset(), f, parts, ft, sc, tld, fld, lm, tm) + p.w("\n") } - comma := parts[len(parts)-1].TrailingComma() - p.preCommaSep(comma) - p.w(",") - p.w("%s}", initComment(parts[len(parts)-1], tm)) + p.w("return r\n") + p.w("}()") } -func (p *project) initializerUnionField(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) { - r = s +func (p *project) initializerUnionField(off uintptr, s []*cc.Initializer, t cc.Type) (parts []*cc.Initializer, isZero bool) { isZero = true - fld = t.FieldByIndex([]int{0}) nextOff := off + t.Size() for len(s) != 0 { if v := s[0]; v.Offset < nextOff { s = s[1:] parts = append(parts, v) - if !v.AssignmentExpression.Operand.IsZero() { - isZero = false - } + isZero = isZero && v.AssignmentExpression.Operand.IsZero() continue } break } - return r[len(parts):], fld, parts, isZero + return parts, isZero } func compatibleStructOrUnion(t1, t2 cc.Type) bool { @@ -498,7 +483,7 @@ func compatibleType(t1, t2 cc.Type) bool { return true } -func (p *project) bitFileType(bits int) cc.Type { +func (p *project) bitFileType(n cc.Node, bits int) cc.Type { switch bits { case 8: return p.task.cfg.ABI.Type(cc.UChar) @@ -509,7 +494,7 @@ func (p *project) bitFileType(bits int) cc.Type { case 64: return p.task.cfg.ABI.Type(cc.ULongLong) default: - panic(todo("%v: internal error: %v", bits)) + panic(todo("%v: internal error: %v", n.Position(), bits)) } } diff --git a/vendor/modernc.org/ccgo/v3/lib/mem.go b/vendor/modernc.org/ccgo/v3/lib/mem.go index ff7b8584e..daf6c9239 100644 --- a/vendor/modernc.org/ccgo/v3/lib/mem.go +++ b/vendor/modernc.org/ccgo/v3/lib/mem.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package ccgo // import "modernc.org/ccgo/v3/lib" diff --git a/vendor/modernc.org/ccgo/v3/lib/nodmesg.go b/vendor/modernc.org/ccgo/v3/lib/nodmesg.go index 6388aa33b..8871c8ecc 100644 --- a/vendor/modernc.org/ccgo/v3/lib/nodmesg.go +++ b/vendor/modernc.org/ccgo/v3/lib/nodmesg.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !ccgo.dmesg // +build !ccgo.dmesg package ccgo // import "modernc.org/ccgo/v3/lib" diff --git a/vendor/modernc.org/ccgo/v3/lib/util.go b/vendor/modernc.org/ccgo/v3/lib/util.go index aeef2055f..f11e439ca 100644 --- a/vendor/modernc.org/ccgo/v3/lib/util.go +++ b/vendor/modernc.org/ccgo/v3/lib/util.go @@ -375,7 +375,7 @@ func Shell(cmd string, args ...string) ([]byte, error) { func MustShell(stackTrace bool, cmd string, args ...string) []byte { b, err := Shell(cmd, args...) if err != nil { - Fatalf(stackTrace, "%s\n%s", b, err) + Fatalf(stackTrace, "%v %s\noutput: %s\nerr: %s", cmd, args, b, err) } return b @@ -389,6 +389,26 @@ func MustCompile(stackTrace bool, args ...string) []byte { return MustShell(stackTrace, "ccgo", args...) } +// Run is like Compile, but executes in-process. +func Run(args ...string) ([]byte, error) { + var b bytes.Buffer + t := NewTask(append([]string{"ccgo"}, args...), &b, &b) + err := t.Main() + return b.Bytes(), err +} + +// MustRun is like Run but if executes Fatal(stackTrace, err) if it fails. +func MustRun(stackTrace bool, args ...string) []byte { + var b bytes.Buffer + args = append([]string{"ccgo"}, args...) + t := NewTask(args, &b, &b) + if err := t.Main(); err != nil { + Fatalf(stackTrace, "%v\noutput: %s\nerr: %s", args, b.Bytes(), err) + } + + return b.Bytes() +} + // AbsCwd returns the absolute working directory. func AbsCwd() (string, error) { wd, err := os.Getwd() |