diff options
author | 2024-03-04 09:42:11 +0000 | |
---|---|---|
committer | 2024-03-04 09:42:11 +0000 | |
commit | adb4cdcf6c9eacd369eaaf5b21774b198d57c040 (patch) | |
tree | a4f9c8fe2ce147fa952bcb795690afb9bb2affcb /vendor/modernc.org/ccgo | |
parent | [bugfix] update postgresqlstmt to correctly use postgres err hook (#2711) (diff) | |
download | gotosocial-adb4cdcf6c9eacd369eaaf5b21774b198d57c040.tar.xz |
[chore]: Bump modernc.org/sqlite from 1.28.0 to 1.29.2 (#2718)
Diffstat (limited to 'vendor/modernc.org/ccgo')
-rw-r--r-- | vendor/modernc.org/ccgo/v3/LICENSE | 27 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/Makefile | 141 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/ccgo.go | 2148 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/cover.go | 39 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/design-notes.adoc | 91 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/dmesg.go | 43 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/etc.go | 110 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/go.go | 13164 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/init.go | 553 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/mem.go | 10 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/mem_linux.go | 20 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/nodmesg.go | 12 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/stringer.go | 58 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/unconvert.sh | 4 | ||||
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/util.go | 458 |
15 files changed, 0 insertions, 16878 deletions
diff --git a/vendor/modernc.org/ccgo/v3/LICENSE b/vendor/modernc.org/ccgo/v3/LICENSE deleted file mode 100644 index 06f07c131..000000000 --- a/vendor/modernc.org/ccgo/v3/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2017 The CCGO Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the names of the authors nor the names of the -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/modernc.org/ccgo/v3/lib/Makefile b/vendor/modernc.org/ccgo/v3/lib/Makefile deleted file mode 100644 index eade00ebe..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/Makefile +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2019 The CCGO Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -.PHONY: all bench clean cover cpu editor internalError later mem nuke todo edit devbench - -grep=--include=*.go -ngrep='TODOOK\|internalError\|testdata' -testlog=testdata/testlog-$(shell echo $$GOOS)-$(shell echo $$GOARCH)-on-$(shell go env GOOS)-$(shell go env GOARCH) - -all: - LC_ALL=C make all_log 2>&1 | tee log - -all_log: - date - go version - uname -a - ./unconvert.sh - gofmt -l -s -w *.go - GOOS=darwin GOARCH=amd64 go build -o /dev/null - GOOS=linux GOARCH=386 go build -o /dev/null - GOOS=linux GOARCH=amd64 go build -o /dev/null - GOOS=linux GOARCH=arm go build -o /dev/null - GOOS=windows GOARCH=386 go build -o /dev/null - GOOS=windows GOARCH=amd64 go build -o /dev/null - go vet 2>&1 | grep -v $(ngrep) || true - golint 2>&1 | grep -v $(ngrep) || true - make todo - misspell *.go - staticcheck | grep -v 'lexer\.go' || true - maligned || true - grep -n 'files.*, ok' log - @grep -n --color=never 'FAIL\|PASS' log - @grep -n --color=always 'FAIL' log - grep -n --color=always 'nil pointer' log - grep -c 'exit status 1' log || true - grep -c 'exit status 2' log || true - LC_ALL=C date 2>&1 | tee -a log - -test: - LC_ALL=C make test_log 2>&1 | tee $(testlog) - grep -ni --color=always fail $(testlog) || true - -test_log: - go version - uname -a - go test -v -timeout 24h - date | tee -a $(testlog) - -test_linux_amd64: - GOOS=linux GOARCH=amd64 make test - -test_linux_386: - GOOS=linux GOARCH=386 make test - -test_linux_arm: - GOOS=linux GOARCH=arm make test - -test_linux_arm64: - GOOS=linux GOARCH=arm64 make test - -test_windows_386: - go version | tee %TEMP%\testlog-windows-386 - go test -v -timeout 24h | tee -a %TEMP%\testlog-windows-386 - date /T | tee -a %TEMP%\testlog-windows-386 - time /T | tee -a %TEMP%\testlog-windows-386 - -test_windows_amd64: - go version | tee %TEMP%\testlog-windows-amd64 - go test -v -timeout 24h | tee -a %TEMP%\testlog-windows-amd64 - date /T | tee -a %TEMP%\testlog-windows-amd64 - time /T | tee -a %TEMP%\testlog-windows-amd64 - -build_all_targets: - GOOS=darwin GOARCH=amd64 go test -c -o /dev/null - GOOS=darwin GOARCH=arm64 go test -c -o /dev/null - GOOS=freebsd GOARCH=386 go test -c -o /dev/null - GOOS=freebsd GOARCH=amd64 go test -c -o /dev/null - GOOS=freebsd GOARCH=arm 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=riscv64 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 - #TODO GOOS=netbsd GOARCH=arm go test -c -o /dev/null - GOOS=openbsd GOARCH=amd64 go test -c -o /dev/null - GOOS=openbsd GOARCH=arm64 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 - GOOS=windows GOARCH=arm64 go test -c -o /dev/null - -devbench: - date 2>&1 | tee log-devbench - go test -timeout 24h -dev -run @ -bench . 2>&1 | tee -a log-devbench - grep -n 'FAIL\|SKIP' log-devbench || true - -bench: - date 2>&1 | tee log-bench - go test -timeout 24h -v -run '^[^E]' -bench . 2>&1 | tee -a log-bench - grep -n 'FAIL\|SKIP' log-bench || true - -clean: - go clean - rm -f *~ *.test *.out - -cover: - t=$(shell mktemp) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t - -cpu: clean - go test -run @ -bench . -cpuprofile cpu.out - go tool pprof -lines *.test cpu.out - -edit: - @touch log - @if [ -f "Session.vim" ]; then gvim -S & else gvim -p Makefile *.go & fi - - -editor: - gofmt -l -s -w *.go - go build -v -o $(GOPATH)/bin/ccgo3 modernc.org/ccgo/v3 - go test -c -o /dev/null - -later: - @grep -n $(grep) LATER * || true - @grep -n $(grep) MAYBE * || true - -mem: clean - go test -run Mem -mem -memprofile mem.out -timeout 24h - go tool pprof -lines -web -alloc_space *.test mem.out - -nuke: clean - go clean -i - -todo: - @grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true - @grep -nr $(grep) 'TODO\|panic' * | grep -v $(ngrep) || true - @grep -nr $(grep) BUG * | grep -v $(ngrep) || true - @grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true - @grep -nir $(grep) 'work.*progress' || true diff --git a/vendor/modernc.org/ccgo/v3/lib/ccgo.go b/vendor/modernc.org/ccgo/v3/lib/ccgo.go deleted file mode 100644 index a2efca3e0..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/ccgo.go +++ /dev/null @@ -1,2148 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate stringer -output stringer.go -type=exprMode,opKind - -// Package ccgo implements the ccgo command. -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "bufio" - "bytes" - "encoding/csv" - "encoding/json" - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "runtime/debug" - "sort" - "strconv" - "strings" - "time" - - "github.com/kballard/go-shellquote" - "golang.org/x/tools/go/packages" - "modernc.org/cc/v3" - "modernc.org/libc" - "modernc.org/opt" -) - -const ( - Version = "3.12.6-20210922111124" - - experimentsEnvVar = "CCGO_EXPERIMENT" - maxSourceLine = 1 << 20 -) - -var ( - _ = libc.Xstdin - - coverExperiment bool -) - -func init() { - s := strings.TrimSpace(os.Getenv(experimentsEnvVar)) - if s == "" { - return - } - - for _, v := range strings.Split(s, ",") { - switch strings.TrimSpace(v) { - case "cover": - coverExperiment = true - } - } -} - -//TODO CPython -//TODO Cython -//TODO gmp -//TODO gofrontend -//TODO gsl -//TODO minigmp -//TODO mpc -//TODO mpfr -//TODO pcre -//TODO pcre2 -//TODO quickjs -//TODO redis -//TODO sdl2 -//TODO wolfssl -//TODO zdat -//TODO zstd - -//TODO 2020-07-17 -// -// Fix += and friends -// -// Audit all unsafe.Pointer conversions -// -// Remove double dereferencing ** -// -// Shifts must not use n.Promote on left opearand -// -// Un-array -// -// Pass more CSmith tests. - -//TODO merge VaList slots of distinct top level statements. - -//TODO turn void -// -// a = b = c = d -// -// where all but the first and last of a, b, c, ... are declarators, into -// -// c = d -// b = c -// a = b - -//TODO define and use all tagged struct types, including inner ones, for example SQLite's SrcList_item. - -//TODO rewrite return conditionalExpression so it has no closures. Partially done. - -//TODO define and restore simple named constants. Having -// -// #define FOO 42 -// ... -// case FOO: -// -// we do not yet define FOO and generate -// -// case 42: - -//TODO do not generate a terminating semicolon for empty statements. - -//TODO replace -// -// var sqlite3_data_directory uintptr = uintptr(0) /* sqlite3.c:156345:17 */ -// -// by -// -// var sqlite3_data_directory uintptr = 0 /* sqlite3.c:156345:17 */ -// -// or -// -// var sqlite3_data_directory = uintptr(0) /* sqlite3.c:156345:17 */ - -//TODO drop all non-referenced declarators unless forced by a command line flag. - -const ( - builtin = ` -#ifdef __PTRDIFF_TYPE__ -typedef __PTRDIFF_TYPE__ ptrdiff_t; -#else -#error __PTRDIFF_TYPE__ undefined -#endif - -#ifdef __SIZE_TYPE__ -typedef __SIZE_TYPE__ size_t; -#else -#error __SIZE_TYPE__ undefined -#endif - -#ifdef __WCHAR_TYPE__ -typedef __WCHAR_TYPE__ wchar_t; -#else -#error __WCHAR_TYPE__ undefined -#endif - -#ifdef __SIZEOF_INT128__ -typedef struct { __INT64_TYPE__ lo, hi; } __int128_t; // must match modernc.org/mathutil.Int128 -typedef struct { __UINT64_TYPE__ lo, hi; } __uint128_t; // must match modernc.org/mathutil.Int128 -#endif; - -#define _FILE_OFFSET_BITS 64 -#define __FUNCTION__ __func__ -#define __PRETTY_FUNCTION__ __func__ -#define __asm __asm__ -#define __builtin_constant_p(x) __builtin_constant_p_impl(0, x) -#define __builtin_offsetof(type, member) ((__SIZE_TYPE__)&(((type*)0)->member)) -#define __builtin_va_arg(ap, type) ((type)__ccgo_va_arg(ap)) -#define __builtin_va_copy(dst, src) dst = src -#define __builtin_va_end(ap) __ccgo_va_end(ap) -#define __builtin_va_start(ap, v) __ccgo_va_start(ap) -#define __ccgo_fd_zero(set) __builtin_memset(set, 0, sizeof(fd_set)) -#define __ccgo_tcl_default_double_rounding(set) ((void)0) -#define __ccgo_tcl_ieee_double_rounding(set) ((void)0) -#define __extension__ -#define __has_include(...) __has_include_impl(#__VA_ARGS__) -#define __has_include_impl(x) -#define __inline__ inline -#define __signed signed -#define asm __asm__ -#define in6addr_any (*__ccgo_in6addr_anyp()) - -typedef void *__builtin_va_list; -typedef long double __float128; - -#if defined(__MINGW32__) || defined(__MINGW64__) -typedef __builtin_va_list va_list; -int gnu_printf(const char *format, ...); -int gnu_scanf(const char *format, ...); -int ms_printf(const char *format, ...); -int ms_scanf(const char *format, ...); -#define _VA_LIST_DEFINED -#define __extension__ -#endif - -__UINT16_TYPE__ __builtin_bswap16 (__UINT16_TYPE__ x); -__UINT32_TYPE__ __builtin_bswap32 (__UINT32_TYPE__ x); -__UINT64_TYPE__ __builtin_bswap64 (__UINT64_TYPE__ x); -char *__builtin___strcat_chk (char *dest, const char *src, size_t os); -char *__builtin___strcpy_chk (char *dest, const char *src, size_t os); -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_fabsf(float x); -float __builtin_huge_valf (void); -float __builtin_inff (void); -float __builtin_nanf (const char *str); -int __builtin___snprintf_chk (char *s, size_t maxlen, int flag, size_t os, const char *fmt, ...); -int __builtin___sprintf_chk (char *s, int flag, size_t os, const char *fmt, ...); -int __builtin___vsnprintf_chk (char *s, size_t maxlen, int flag, size_t os, const char *fmt, __builtin_va_list ap); -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_isunordered(double x, double y); -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_fabsl(long double x); -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); -void *__builtin___memcpy_chk (void *dest, const void *src, size_t n, size_t os); -void *__builtin___memmove_chk (void *dest, const void *src, size_t n, size_t os); -void *__builtin___memset_chk (void *dstpp, int c, size_t len, size_t dstlen); -void *__builtin_malloc(size_t size); -void *__builtin_memcpy(void *dest, const void *src, size_t n); -void *__builtin_memset(void *s, int c, size_t n); -void *__builtin_mmap(void *addr, size_t length, int prot, int flags, int fd, __INTPTR_TYPE__ offset); -void *__ccgo_va_arg(__builtin_va_list ap); -void __builtin_abort(void); -void __builtin_bzero(void *s, size_t n); -void __builtin_exit(int status); -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); - -#ifdef __APPLE__ -int (*__darwin_check_fd_set_overflow)(int, void *, int); -#endif - -` - defaultCrt = "modernc.org/libc" -) - -func origin(skip int) string { - pc, fn, fl, _ := runtime.Caller(skip) - f := runtime.FuncForPC(pc) - var fns string - if f != nil { - fns = f.Name() - if x := strings.LastIndex(fns, "."); x > 0 { - fns = fns[x+1:] - } - } - return fmt.Sprintf("%s:%d:%s", fn, fl, fns) -} - -func todo(s string, args ...interface{}) string { - switch { - case s == "": - s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...) - default: - s = fmt.Sprintf(s, args...) - } - r := fmt.Sprintf("%s\n\tTODO %s", origin(2), s) //TODOOK - fmt.Fprintf(os.Stdout, "%s\n", r) - os.Stdout.Sync() - return r -} - -func trc(s string, args ...interface{}) string { - switch { - case s == "": - s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...) - default: - s = fmt.Sprintf(s, args...) - } - r := fmt.Sprintf("%s: TRC %s", origin(2), s) - fmt.Fprintf(os.Stderr, "%s\n", r) - os.Stderr.Sync() - return r -} - -// Task represents a compilation job. -type Task struct { - D []string // -D - I []string // -I - U []string // -U - ar string // $AR, default "ar" - arLookPath string // LookPath(ar) - 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 - cfg *cc.Config - compiledb string // -compiledb - crt string - crtImportPath string // -crt-import-path - exportDefines string // -export-defines - exportEnums string // -export-enums - exportExterns string // -export-externs - exportFields string // -export-fields - exportStructs string // -export-structs - exportTypedefs string // -export-typedefs - goarch string - goos string - hide map[string]struct{} // -hide - hostConfigCmd string // -host-config-cmd - hostConfigOpts string // -host-config-opts - hostIncludes []string - hostPredefined string - hostSysIncludes []string - ignoredIncludes string // -ignored-includes - ignoredObjects map[string]struct{} // -ignore-object - imported []*imported - includedFiles map[string]struct{} - l []string // -l - loadConfig string // --load-config - o string // -o - out io.Writer - pkgName string // -pkgname - replaceFdZero string // -replace-fd-zero - replaceTclDefaultDoubleRounding string // -replace-tcl-default-double-rounding - replaceTclIeeeDoubleRounding string // -replace-tcl-default-double-rounding - scriptFn string // -script - sources []cc.Source - staticLocalsPrefix string // -static-locals-prefix - 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 - // Task.Main(). Intended to support TestGenerate in stable vs latest - // modes. This is _not_ supposed to be used when the Task instance is - // constructed by a ccgo _command_ (ccgo/v3) - it should never set this - // field. Only programs importing ccgo/v3/lib that opt-in into this - // feature should ever set it. - CallOutBinary string - - 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 - errTrace bool // -err-trace - exportDefinesValid bool // -export-defines present - exportEnumsValid bool // -export-enums present - exportExternsValid bool // -export-externs present - exportFieldsValid bool // -export-fields present - exportStructsValid bool // -export-structs present - exportTypedefsValid bool // -export-typedefs present - fullPathComments bool // -full-path-comments - funcSig bool // -func-sig - header bool // -header - ignoreUnsupportedAligment bool // -ignore-unsupported-alignment - isScripted bool - mingw bool - noCapi bool // -nocapi - nostdinc bool // -nostdinc - nostdlib bool // -nostdlib - panicStubs bool // -panic-stubs - tracePinning bool // -trace-pinning - traceTranslationUnits bool // -trace-translation-units - verifyStructs bool // -verify-structs - version bool // -version - watch bool // -watch-instrumentation - windows bool // -windows -} - -// NewTask returns a newly created Task. -func NewTask(args []string, stdout, stderr io.Writer) *Task { - if dmesgs { - dmesg("%v: %v", origin(1), args) - } - if stdout == nil { - stdout = os.Stdout - } - if stderr == nil { - stderr = os.Stderr - } - return &Task{ - args: args, - cfg: &cc.Config{ - Config3: cc.Config3{ - MaxSourceLine: maxSourceLine, - }, - DoNotTypecheckAsm: true, - EnableAssignmentCompatibilityChecking: true, - LongDoubleIsDouble: true, - SharedFunctionDefinitions: &cc.SharedFunctionDefinitions{}, - }, - ar: env("AR", "ar"), - cc: env("CC", "gcc"), - crt: "libc.", - crtImportPath: defaultCrt, - goarch: env("TARGET_GOARCH", env("GOARCH", runtime.GOARCH)), - goos: env("TARGET_GOOS", env("GOOS", runtime.GOOS)), - hide: map[string]struct{}{}, - hostConfigCmd: env("CCGO_CPP", ""), - pkgName: "main", - stderr: stderr, - stdout: stdout, - volatiles: map[cc.StringID]struct{}{}, - } -} - -func env(name, deflt string) (r string) { - r = deflt - if s := os.Getenv(name); s != "" { - r = s - } - return r -} - -// Get exported symbols from package having import path 'path'. -func (t *Task) capi(path string) (pkgName string, exports map[string]struct{}, err error) { - // defer func() { - // var a []string - // for k := range exports { - // a = append(a, k) - // } - // sort.Strings(a) - // trc("%s\n%s", path, strings.Join(a, "\n")) - // }() - var errModule, errGopath error - defer func() { - if err != nil { - a := []string{err.Error()} - if errModule != nil { - a = append(a, fmt.Sprintf("module mode error: %s", errModule)) - } - if errGopath != nil { - a = append(a, fmt.Sprintf("gopath mode error: %s", errGopath)) - } - wd, err2 := os.Getwd() - err = fmt.Errorf( - "(wd %q, %v): loading C exports from %s (GOPATH=%v GO111MODULE=%v): %v", - wd, err2, path, os.Getenv("GOPATH"), os.Getenv("GO111MODULE"), strings.Join(a, "\n\t"), - ) - } - }() - - mod := os.Getenv("GO111MODULE") - if mod == "" || mod == "on" { - var pkgs []*packages.Package - pkgs, errModule = packages.Load( - &packages.Config{ - Mode: packages.NeedFiles, - Env: append(os.Environ(), fmt.Sprintf("GOOS=%s", t.goos), fmt.Sprintf("GOARCH=%s", t.goarch)), - }, - path, - ) - switch { - case errModule == nil: - if len(pkgs) != 1 { - errModule = fmt.Errorf("expected one package, loaded %d", len(pkgs)) - break - } - - pkg := pkgs[0] - if len(pkg.Errors) != 0 { - var a []string - for _, v := range pkg.Errors { - a = append(a, v.Error()) - } - errModule = fmt.Errorf("%s", strings.Join(a, "\n")) - break - } - - return t.capi2(pkg.GoFiles) - } - } - - gopath0 := os.Getenv("GOPATH") - for _, gopath := range strings.Split(gopath0, string(os.PathListSeparator)) { - if gopath == "" || !filepath.IsAbs(gopath) { - continue - } - - ctx := build.Context{ - GOARCH: t.goarch, - GOOS: t.goos, - GOPATH: gopath, - Compiler: "gc", - } - arg := filepath.Join(gopath, "src", path) - pkg, err := ctx.ImportDir(arg, 0) - if err != nil { - errGopath = err - continue - } - - for i, v := range pkg.GoFiles { - pkg.GoFiles[i] = filepath.Join(gopath, "src", path, v) - } - return t.capi2(pkg.GoFiles) - } - return "", nil, fmt.Errorf("cannot load CAPI") -} - -func (t *Task) capi2(files []string) (pkgName string, exports map[string]struct{}, err error) { - exports = map[string]struct{}{} - base := fmt.Sprintf("capi_%s_%s.go", t.goos, t.goarch) - var fn string - for _, v := range files { - if filepath.Base(v) == base { - fn = v - break - } - } - if fn == "" { - return "", nil, fmt.Errorf("file %s not found", base) - } - - fset := token.NewFileSet() - file, err := parser.ParseFile(fset, fn, nil, 0) - if err != nil { - return "", nil, err - } - - obj, ok := file.Scope.Objects["CAPI"] - if !ok { - return "", nil, fmt.Errorf("CAPI not declared in %s", fn) - } - - switch obj.Kind { - case ast.Var: - // ok - default: - return "", nil, fmt.Errorf("unexpected CAPI object kind: %v", obj.Kind) - } - - spec, ok := obj.Decl.(*ast.ValueSpec) - if !ok { - return "", nil, fmt.Errorf("unexpected CAPI object type: %T", obj.Decl) - } - - if len(spec.Values) != 1 { - return "", nil, fmt.Errorf("expected one CAPI expression, got %v", len(spec.Values)) - } - - ast.Inspect(spec.Values[0], func(n ast.Node) bool { - if x, ok := n.(*ast.BasicLit); ok { - var key string - if key, err = strconv.Unquote(x.Value); err != nil { - err = fmt.Errorf("invalid CAPI key value: %s", x.Value) - return false - } - - exports[key] = struct{}{} - } - return true - }) - return file.Name.String(), exports, err -} - -// Main executes task. -func (t *Task) Main() (err error) { - 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()) - }() - } - if t.CallOutBinary != "" { - if dmesgs { - dmesg("%v: calling out '%s' instead", origin(1)) - } - cmd := exec.Command(t.CallOutBinary, t.args[1:]...) - out, err := cmd.CombinedOutput() - if err != nil { - err = fmt.Errorf("%v\n%s", err, out) - } - return err - } - - opts := opt.NewSet() - opts.Arg("D", true, func(arg, value string) error { t.D = append(t.D, value); return nil }) - opts.Arg("I", true, func(opt, arg string) error { t.I = append(t.I, arg); return nil }) - opts.Arg("U", true, func(arg, value string) error { t.U = append(t.U, value); return nil }) - opts.Arg("compiledb", false, func(arg, value string) error { t.compiledb = value; t.compiledbValid = true; return opt.Skip(nil) }) - opts.Arg("crt-import-path", false, func(arg, value string) error { t.crtImportPath = value; return nil }) - opts.Arg("export-defines", false, func(arg, value string) error { t.exportDefines = value; t.exportDefinesValid = true; return nil }) - opts.Arg("export-enums", false, func(arg, value string) error { t.exportEnums = value; t.exportEnumsValid = true; return nil }) - opts.Arg("export-externs", false, func(arg, value string) error { t.exportExterns = value; t.exportExternsValid = true; return nil }) - opts.Arg("export-fields", false, func(arg, value string) error { t.exportFields = value; t.exportFieldsValid = true; return nil }) - opts.Arg("export-structs", false, func(arg, value string) error { t.exportStructs = value; t.exportStructsValid = true; return nil }) - opts.Arg("export-typedefs", false, func(arg, value string) error { t.exportTypedefs = value; t.exportTypedefsValid = true; return nil }) - opts.Arg("host-config-cmd", false, func(arg, value string) error { t.hostConfigCmd = value; return nil }) - opts.Arg("host-config-opts", false, func(arg, value string) error { t.hostConfigOpts = value; return nil }) - opts.Arg("ignored-includes", false, func(arg, value string) error { t.ignoredIncludes = value; return nil }) - opts.Arg("pkgname", false, func(arg, value string) error { t.pkgName = value; return nil }) - opts.Arg("replace-fd-zero", false, func(arg, value string) error { t.replaceFdZero = value; return nil }) - opts.Arg("replace-tcl-default-double-rounding", false, func(arg, value string) error { t.replaceTclDefaultDoubleRounding = value; return nil }) - opts.Arg("replace-tcl-ieee-double-rounding", false, func(arg, value string) error { t.replaceTclIeeeDoubleRounding = value; return nil }) - opts.Arg("script", false, func(arg, value string) error { t.scriptFn = value; return nil }) - opts.Arg("static-locals-prefix", false, func(arg, value string) error { t.staticLocalsPrefix = value; return nil }) - - opts.Opt("E", func(opt string) error { t.E = true; return nil }) - opts.Opt("all-errors", func(opt string) error { t.allErrors = true; return nil }) - opts.Opt("cover-instrumentation", func(opt string) error { t.cover = true; return nil }) - opts.Opt("cover-instrumentation-c", func(opt string) error { t.coverC = true; return nil }) - opts.Opt("err-trace", func(opt string) error { t.errTrace = true; return nil }) - 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-unsupported-alignment", func(opt string) error { t.ignoreUnsupportedAligment = 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-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("ignore-object", false, func(arg, value string) error { - if t.ignoredObjects == nil { - t.ignoredObjects = map[string]struct{}{} - } - t.ignoredObjects[value] = struct{}{} - 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 = "" - t.crtImportPath = "" - return nil - }) - opts.Arg("hide", false, func(arg, value string) error { - value = strings.TrimSpace(value) - a := strings.Split(value, ",") - for _, v := range a { - t.hide[v] = struct{}{} - } - return nil - }) - opts.Arg("l", true, func(arg, value string) error { - value = strings.TrimSpace(value) - a := strings.Split(value, ",") - for _, v := range a { - t.l = append(t.l, v) - t.symSearchOrder = append(t.symSearchOrder, -len(t.l)) - } - return nil - }) - opts.Arg("o", false, func(arg, value string) error { - if t.o != "" { - return fmt.Errorf("multiple argument: -o %s", value) - } - - t.o = value - return nil - }) - if err := opts.Parse(t.args[1:], func(arg string) error { - if strings.HasPrefix(arg, "-") { - return fmt.Errorf("unexpected option: %s", arg) - } - - switch filepath.Ext(arg) { - case ".h": - t.symSearchOrder = append(t.symSearchOrder, len(t.sources)) - t.sources = append(t.sources, cc.Source{Name: arg}) - case ".c": - t.symSearchOrder = append(t.symSearchOrder, len(t.sources)) - t.sources = append(t.sources, cc.Source{Name: arg, DoNotCache: true}) - case ".json": - t.cdb = arg - return opt.Skip(nil) - default: - return fmt.Errorf("unexpected file type: %s", arg) - } - - return nil - }); err != nil { - switch x := err.(type) { - case opt.Skip: - switch { - case t.compiledbValid: // -compiledb foo.json, create DB - cmd := []string(x)[1:] - if len(cmd) == 0 { - return fmt.Errorf("missing command after -compiledb <file>") - } - - 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) - } - - return err - default: - return err - } - } - - 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 - } - - if t.scriptFn != "" { - return t.scriptBuild(t.scriptFn) - } - - if len(t.sources) == 0 { - return fmt.Errorf("no input files specified") - } - - if t.crtImportPath != "" { - t.l = append(t.l, t.crtImportPath) - t.symSearchOrder = append(t.symSearchOrder, -len(t.l)) - m := map[string]struct{}{} - for _, v := range t.l { - v = strings.TrimSpace(v) - if _, ok := m[v]; !ok { - t.imported = append(t.imported, &imported{path: v}) - m[v] = struct{}{} - } - } - 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) - if err != nil { - return err - } - abi.Types[cc.LongDouble] = abi.Types[cc.Double] - - var re *regexp.Regexp - if t.ignoredIncludes != "" { - if re, err = regexp.Compile(t.ignoredIncludes); err != nil { - return err - } - } - - t.cfg.ABI = abi - t.cfg.ReplaceMacroFdZero = t.replaceFdZero - t.cfg.ReplaceMacroTclDefaultDoubleRounding = t.replaceTclDefaultDoubleRounding - t.cfg.ReplaceMacroTclIeeeDoubleRounding = t.replaceTclIeeeDoubleRounding - t.cfg.Config3.IgnoreInclude = re - t.cfg.Config3.NoFieldAndBitfieldOverlap = true - t.cfg.Config3.PreserveWhiteSpace = t.saveConfig == "" - t.cfg.Config3.UnsignedEnums = true - - if t.mingw = detectMingw(t.hostPredefined); t.mingw { - t.windows = true - } - if t.nostdinc { - t.hostIncludes = nil - t.hostSysIncludes = nil - } - var sources []cc.Source - 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 { - var a []string - for _, v := range t.D { - if i := strings.IndexByte(v, '='); i > 0 { - a = append(a, fmt.Sprintf("#define %s %s", v[:i], v[i+1:])) - continue - } - - a = append(a, fmt.Sprintf("#define %s 1", v)) - } - a = append(a, "\n") - sources = append(sources, cc.Source{Name: "<defines>", Value: strings.Join(a, "\n"), DoNotCache: true}) - } - if len(t.U) != 0 { - var a []string - for _, v := range t.U { - a = append(a, fmt.Sprintf("#undef %s", v)) - } - a = append(a, "\n") - sources = append(sources, cc.Source{Name: "<undefines>", Value: strings.Join(a, "\n"), DoNotCache: true}) - } - - // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html - // - // Headers whose names are enclosed in double-quotes ( "" ) shall be - // searched for first in the directory of the file with the #include - // line, then in directories named in -I options, and last in the usual - // places - includePaths := append([]string{"@"}, t.I...) - 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, t.hostSysIncludes...) - if t.traceTranslationUnits { - fmt.Printf("target: %s/%s\n", t.goos, t.goarch) - if t.hostConfigCmd != "" { - fmt.Printf("host config cmd: %s\n", t.hostConfigCmd) - } - } - 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, out); err != nil { - return err - } - memGuard(i, t.isScripted) - continue - } - - var t0 time.Time - if t.traceTranslationUnits { - fmt.Printf("C front end %d/%d: %s ... ", i+1, len(t.sources), v.Name) - t0 = time.Now() - } - ast, err := cc.Translate(t.cfg, includePaths, sysIncludePaths, tuSources) - if err != nil { - return err - } - - if t.traceTranslationUnits { - fmt.Println(time.Since(t0)) - } - t.asts = append(t.asts, ast) - memGuard(i, t.isScripted) - } - if t.E || t.isScripted { - return nil - } - - 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 - } - - t.arLookPath, err = exec.LookPath(t.ar) - return err -} - -func (t *Task) link() (err error) { - if len(t.asts) == 0 { - return fmt.Errorf("no objects to link") - } - - if t.o == "" { - t.o = fmt.Sprintf("a_%s_%s.go", t.goos, t.goarch) - } - dir := filepath.Dir(t.o) - t.capif = filepath.Join(dir, fmt.Sprintf("capi_%s_%s.go", t.goos, t.goarch)) - f, err2 := os.Create(t.o) - if err2 != nil { - return err2 - } - - defer func() { - if e := f.Close(); e != nil && err == nil { - err = e - return - } - - if out, e := exec.Command("gofmt", "-r", "(x) -> x", "-l", "-s", "-w", t.o).CombinedOutput(); e != nil && err == nil { - err = fmt.Errorf(strings.Join([]string{string(out), e.Error()}, ": ")) - } - if out, e := exec.Command("gofmt", "-l", "-s", "-w", t.o).CombinedOutput(); e != nil && err == nil { - err = fmt.Errorf(strings.Join([]string{string(out), e.Error()}, ": ")) - } - }() - - w := bufio.NewWriter(f) - - defer func() { - if e := w.Flush(); e != nil && err == nil { - err = e - } - }() - - t.out = w - p, err := newProject(t) - if err != nil { - return err - } - - return p.main() -} - -func (t *Task) scriptBuild(fn string) error { - f, err := os.Open(fn) - if err != nil { - return err - } - - defer f.Close() - - r := csv.NewReader(f) - r.Comment = '#' - r.FieldsPerRecord = -1 - r.TrimLeadingSpace = true - script, err := r.ReadAll() - if err != nil { - return err - } - - return t.scriptBuild2(script) -} - -func (t *Task) scriptBuild2(script [][]string) error { - var ldir string - ccgo := []string{t.args[0]} - for i, line := range script { - dir := line[0] - args := line[1:] - for _, v := range args { - if strings.HasSuffix(v, ".c") || strings.HasSuffix(v, ".h") { - v = filepath.Join(dir, v) - t.symSearchOrder = append(t.symSearchOrder, len(t.sources)) - t.sources = append(t.sources, cc.Source{Name: v}) - } - } - cmd := append(ccgo, args...) - if t.traceTranslationUnits { - if dir != ldir { - fmt.Println(dir) - ldir = dir - } - 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.saveConfig = t.saveConfig - if err := inDir(dir, t2.Main); err != nil { - return err - } - - t.asts = append(t.asts, t2.asts...) - if i == 0 { - t.cfg = t2.cfg - } - } - if t.crtImportPath != "" { - t.l = append(t.l, t.crtImportPath) - t.symSearchOrder = append(t.symSearchOrder, -len(t.l)) - m := map[string]struct{}{} - for _, v := range t.l { - v = strings.TrimSpace(v) - if _, ok := m[v]; !ok { - t.imported = append(t.imported, &imported{path: v}) - m[v] = struct{}{} - } - } - t.imported[len(t.imported)-1].used = true // crt is always imported - } - if t.saveConfig != "" { - return nil - } - - return t.link() -} - -type cdb struct { - items []*cdbItem - outputIndex map[string][]*cdbItem -} - -func (db *cdb) find(obj map[string]*cdbItem, nm string, ver, seqLimit int, path []string, cc, ar string, ignored map[string]struct{}) 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 { - case ver < 0: - // find highest ver with .seq < seqLimit - for i, v := range db.outputIndex[nm] { - if v.seq >= seqLimit { - break - } - - item = v - ver = i - } - if item == nil { - ver = -1 - for _, v := range db.items { - if seqLimit >= 0 && v.seq >= seqLimit { - break - } - - if filepath.Base(v.Output) == filepath.Base(nm) { - item = v - ver = v.ver - break - } - } - } - - k = fmt.Sprintf("%s#%d", nm, ver) - default: - // match ver exactly - k = fmt.Sprintf("%s#%d", nm, ver) - if obj[k] != nil { - return nil - } - - items := db.outputIndex[nm] - switch { - case ver < len(items): - panic(todo("", nm, ver, seqLimit)) - default: - n := -1 - for _, v := range db.items { - if seqLimit >= 0 && v.seq >= seqLimit { - break - } - - if filepath.Base(v.Output) == filepath.Base(nm) { - n++ - if n == ver { - item = v - break - } - } - } - } - } - if item == nil { - for k := range ignored { - if k == nm || strings.HasSuffix(nm, k) { - return nil - } - } - - return fmt.Errorf("not found in compile DB: %s (max seq %d), path %v", k, seqLimit, path) - } - - if obj[k] != nil { - return nil - } - - obj[k] = item - var errs []string - for _, v := range item.sources(cc, ar) { - if err := db.find(obj, v, -1, item.seq, append(path, nm), cc, ar, ignored); err != nil { - errs = append(errs, err.Error()) - } - } - if len(errs) != 0 { - sort.Strings(errs) - w := 0 - for _, v := range errs { - if w == 0 || w > 0 && v != errs[w-1] { - errs[w] = v - w++ - } - } - errs = errs[:w] - return fmt.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} - -func suffixNum(s string, dflt int) (string, int) { - x := strings.LastIndexByte(s, '#') - if x < 0 { - return s, dflt - } - - // foo#42 - // 012345 - // x == 3 - num := s[x+1:] - n, err := strconv.ParseUint(num, 10, 32) - if err != nil { - return s, dflt - } - - return s[:x], int(n) -} - -func (t *Task) useCompileDB(fn string, args []string) error { - if err := t.setLookPaths(); err != nil { - return err - } - - var cdb cdb - f, err := os.Open(fn) - if err != nil { - return err - } - - de := json.NewDecoder(f) - err = de.Decode(&cdb.items) - f.Close() - if err != nil { - return err - } - - cdb.outputIndex = map[string][]*cdbItem{} - for i, v := range cdb.items { - v.seq = i - if len(v.Arguments) == 0 { - if len(v.Command) == 0 { - return fmt.Errorf("either arguments or command is required: %+v", v) - } - - if v.Arguments, err = shellquote.Split(v.Command); err != nil { - return err - } - } - - k := v.output(t.ccLookPath, t.arLookPath) - a := cdb.outputIndex[k] - v.ver = len(a) - cdb.outputIndex[k] = append(a, v) - } - obj := map[string]*cdbItem{} - notFound := false - for _, v := range args { - v, ver := suffixNum(v, 0) - if err := cdb.find(obj, v, ver, -1, nil, t.ccLookPath, t.arLookPath, t.ignoredObjects); err != nil { - notFound = true - fmt.Fprintln(os.Stderr, err) - } - } - if notFound { - var a []string - for k, v := range cdb.outputIndex { - for _, w := range v { - a = append(a, fmt.Sprintf("%5d %s", w.seq, k)) - } - } - sort.Strings(a) - fmt.Fprintf(os.Stderr, "compile DB index:\n\t%s\n", strings.Join(a, "\n\t")) - } - - var a []string - for k := range obj { - a = append(a, k) - } - sort.Strings(a) - return t.cdbBuild(obj, a) -} - -func (t *Task) cdbBuild(obj map[string]*cdbItem, list []string) error { - var script [][]string - for _, nm := range list { - it := obj[nm] - if !strings.HasSuffix(it.Output, ".o") || it.Arguments[0] != t.cc { - continue - } - - args, err := it.ccgoArgs(t.cc) - if err != nil { - 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) - } - return t.scriptBuild2(script) -} - -func (t *Task) createCompileDB(command []string) (rerr error) { - if err := t.setLookPaths(); err != nil { - return err - } - - cwd, err := os.Getwd() - if err != nil { - return err - } - - f, err := os.Create(t.compiledb) - if err != nil { - return err - } - - defer func() { - if err := f.Close(); err != nil && rerr == nil { - rerr = err - } - }() - - cwr := newCDBWriter(f) - - defer func() { - if err := cwr.finish(); err != nil && rerr == nil { - rerr = err - } - }() - - var cmd *exec.Cmd - var parser func(s string) ([]string, error) -out: - switch t.goos { - case "darwin", "freebsd", "netbsd": - switch command[0] { - case "make", "gmake": - // ok - default: - return fmt.Errorf("usupported build command: %s", command[0]) - } - - sh, err := exec.LookPath("sh") - if err != nil { - return err - } - - command = append([]string{sh, "-c"}, join(" ", command[0], "SHELL='sh -x'", command[1:])) - cmd = exec.Command(command[0], command[1:]...) - parser = makeXParser - case "openbsd": - switch command[0] { - case "make", "gmake": - // ok - default: - return fmt.Errorf("usupported build command: %s", command[0]) - } - - sh, err := exec.LookPath("sh") - if err != nil { - return err - } - - command = append([]string{sh, "-c"}, join(" ", command[0], "SHELL='sh -x'", command[1:])) - cmd = exec.Command(command[0], command[1:]...) - parser = makeXParser2 - case "windows": - if command[0] != "make" && command[0] != "make.exe" { - return fmt.Errorf("usupported build command: %s", command[0]) - } - - switch s := runtime.GOOS; s { - case "windows": - argv := append([]string{"-d"}, command[1:]...) - if !strings.HasSuffix(command[0], ".exe") { - command[0] += ".exe" - } - cmd = exec.Command(command[0], argv...) - parser = makeDParser - break out - case "linux": - // ok - default: - return fmt.Errorf("usupported cross compile host: %s", s) - } - - fallthrough - default: - strace, err := exec.LookPath("strace") - if err != nil { - return err - } - - argv := append([]string{"-f", "-s1000000", "-e", "trace=execve"}, command...) - cmd = exec.Command(strace, argv...) - parser = straceParser - } - cmd.Env = append(os.Environ(), "LC_ALL=C") - cw := t.newCdbMakeWriter(cwr, cwd, parser) - 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) - } - if err := cmd.Run(); err != nil { - if dmesgs { - dmesg("%v: cmd.Run: %v", origin(1), err) - } - return err - } - - return cw.err -} - -func makeDParser(s string) ([]string, error) { - const prefix = "CreateProcess(" - if !strings.HasPrefix(s, prefix) { - return nil, nil - } - - // s: `CreateProcess(C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe,gcc -O3 -Wall -c -o compress.o compress.c,...)` - s = s[len(prefix):] - // s: `C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe,gcc -O3 -Wall -c -o compress.o compress.c,...)` - x := strings.IndexByte(s, ',') - if x < 0 { - return nil, nil - } - - cmd := s[:x] - // cmd: `C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe` - - s = s[x+1:] - // s: `gcc -O3 -Wall -c -o compress.o compress.c,...)` - if x = strings.LastIndexByte(s, ','); x < 0 { - return nil, nil - } - - s = s[:x] - // s: `gcc -O3 -Wall -c -o compress.o compress.c` - a, err := shellquote.Split(strings.TrimSpace(s)) - if err != nil || len(a) == 0 { - return nil, err - } - - return append([]string{cmd}, a[1:]...), nil -} - -func isCreateArchive(s string) bool { - // ar modifiers may be in any order so sort characters in s before checking. - // This turns eg `rc` into `cr`. - b := []byte(s) - sort.Slice(b, func(i, j int) bool { return b[i] < b[j] }) - switch string(b) { - case "cq", "cr", "crs", "cru", "r": - return true - } - return false -} - -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) { - switch { - case strings.HasPrefix(s, "libtool: link: ar "): - s = s[len("libtool: link:"):] - case strings.HasPrefix(s, "libtool: compile: "): - s = s[len("libtool: compile:"):] - for strings.HasPrefix(s, " ") { - s = s[1:] - } - default: - var n int - if n, s = hasPlusPrefix(s); n == 0 { - return nil, nil - } - } - - if !strings.HasPrefix(s, " ") { - return nil, nil - } - - s = s[1:] - if dmesgs { - dmesg("%v: source line `%s`, caller %v:", origin(1), s, origin(2)) - } - r, err = shellquote.Split(s) - if dmesgs { - dmesg("%v: shellquote.Split -> %v %[2]q, %v", origin(1), r, err) - } - if err != nil { - if strings.Contains(err.Error(), "Unterminated single-quoted string") { - return nil, nil // ignore - } - } - if len(r) != 0 && filepath.Base(r[0]) == "libtool" { - r[0] = "libtool" - } - return r, err -} - -func makeXParser2(s string) (r []string, err error) { - s = strings.TrimSpace(s) - switch { - case strings.HasPrefix(s, "libtool: link: ar "): - s = s[len("libtool: link:"):] - case strings.HasPrefix(s, "libtool: compile: "): - s = s[len("libtool: compile:"):] - for strings.HasPrefix(s, " ") { - s = s[1:] - } - default: - var n int - if n, s = hasPlusPrefix(s); n != 0 { - return nil, nil - } - } - - if dmesgs { - dmesg("%v: source line `%s`, caller %v:", origin(1), s, origin(2)) - } - r, err = shellquote.Split(s) - if dmesgs { - dmesg("%v: shellquote.Split -> %v %[2]q, %v", origin(1), r, err) - } - if err != nil { - if strings.Contains(err.Error(), "Unterminated single-quoted string") { - return nil, nil // ignore - } - } - if len(r) != 0 && filepath.Base(r[0]) == "libtool" { - r[0] = "libtool" - } - return r, err -} - -func straceParser(s string) ([]string, error) { - prefix := "execve(" - if strings.HasPrefix(s, "[pid ") { - s = strings.TrimSpace(s[strings.IndexByte(s, ']')+1:]) - } - if !strings.HasPrefix(s, prefix) || !strings.HasSuffix(s, ") = 0") { - return nil, nil - } - - // s: `execve("/usr/bin/ar", ["ar", "cr", "libtcl8.6.a", "regcomp.o", ... "bn_s_mp_sqr.o", "bn_s_mp_sub.o"], 0x55e6bbf49648 /* 60 vars */) = 0` - s = s[len(prefix):] - // s: `"/usr/bin/ar", ["ar", "cr", "libtcl8.6.a", "regcomp.o", ... "bn_s_mp_sqr.o", "bn_s_mp_sub.o"], 0x55e6bbf49648 /* 60 vars */) = 0` - a := strings.SplitN(s, ", [", 2) - // a[0]: `"/usr/bin/ar"`, a[1]: `"ar", "cr", "libtcl8.6.a", "regcomp.o", ... "bn_s_mp_sqr.o", "bn_s_mp_sub.o"], 0x55e6bbf49648 /* 60 vars */) = 0` - args := a[1] - // args: `"ar", "cr", "libtcl8.6.a", "regcomp.o", ... "bn_s_mp_sqr.o", "bn_s_mp_sub.o"], 0x55e6bbf49648 /* 60 vars */) = 0` - args = args[:strings.LastIndex(args, "], ")] - // args: `"ar", "cr", "libtcl8.6.a", "regcomp.o", ... "bn_s_mp_sqr.o", "bn_s_mp_sub.o"` - argv, err := shellquote.Split(args) - if err != nil { - return nil, err - } - - words, err := shellquote.Split(a[0]) - if err != nil { - return nil, err - } - - argv[0] = words[0] - for i, v := range argv { - if strings.HasSuffix(v, ",") { - v = v[:len(v)-1] - } - if v2, err := strconv.Unquote(`"` + v + `"`); err == nil { - v = v2 - } - argv[i] = v - } - - return argv, nil -} - -type cdbItem struct { - Arguments []string `json:"arguments"` - Command string `json:"command,omitempty"` - Directory string `json:"directory"` - File string `json:"file"` - Output string `json:"output,omitempty"` - - seq int - ver int -} - -func (it *cdbItem) cmpString() string { return fmt.Sprint(*it) } - -func (it *cdbItem) ccgoArgs(cc string) (r []string, err error) { - switch it.Arguments[0] { - case cc: - set := opt.NewSet() - set.Arg("D", true, func(opt, arg string) error { r = append(r, "-D"+arg); return nil }) - set.Arg("I", true, func(opt, arg string) error { r = append(r, "-I"+arg); return nil }) - set.Arg("MF", true, func(opt, arg string) error { return nil }) - set.Arg("MT", true, func(opt, arg string) error { return nil }) - set.Arg("O", true, func(opt, arg string) error { return nil }) - set.Arg("U", true, func(opt, arg string) error { r = append(r, "-U"+arg); return nil }) - 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"): - r = append(r, arg) - case - - strings.HasPrefix(arg, "-W"), - strings.HasPrefix(arg, "-f"), - strings.HasPrefix(arg, "-m"): - - // nop - case strings.HasPrefix(arg, ">"): - return opt.Skip(nil) - default: - return fmt.Errorf("unknown/unsupported CC option: %s", arg) - } - - return nil - }); err != nil { - switch err.(type) { - case opt.Skip: - // ok - default: - return nil, err - } - } - - return r, nil - default: - return nil, fmt.Errorf("command not supported: %q", it.Arguments[0]) - } -} - -func (it *cdbItem) output(cc, ar string) (r string) { - if it.Output != "" { - return it.Output - } - - if len(it.Arguments) == 0 { - return "" - } - - switch it.Arguments[0] { - case cc: - for i, v := range it.Arguments { - if v == "-o" && i < len(it.Arguments)-1 { - it.Output = filepath.Join(it.Directory, it.Arguments[i+1]) - break - } - } - if it.Output == "" && strings.HasSuffix(it.File, ".c") { - for _, v := range it.Arguments { - if v == "-c" { - bn := filepath.Base(it.File) - it.Output = filepath.Join(it.Directory, bn[:len(bn)-2]+".o") - break - } - } - } - case ar: - if isCreateArchive(it.Arguments[1]) { - it.Output = filepath.Join(it.Directory, it.Arguments[2]) - } - case "libtool": - for i, v := range it.Arguments { - if v == "-o" && i < len(it.Arguments)-1 { - it.Output = filepath.Join(it.Directory, it.Arguments[i+1]) - } - } - } - return it.Output -} - -func (it *cdbItem) sources(cc, ar string) (r []string) { - if len(it.Arguments) == 0 { - return nil - } - - switch arg0 := it.Arguments[0]; arg0 { - case - "libtool", - ar, - filepath.Base(ar), - cc: - - var prev string - for _, v := range it.Arguments { - switch prev { - case "-o", "-MT", "-MF": - // nop - default: - if strings.HasSuffix(v, ".o") { - r = append(r, filepath.Join(it.Directory, v)) - } - } - prev = v - } - return r - default: - panic(todo("cc: %q ar: %q it: %+v", cc, ar, it)) - } -} - -type cdbMakeWriter struct { - ar string - arBase string - b bytes.Buffer - cc string - dir string - err error - it cdbItem - parser func(s string) ([]string, error) - prefix string - sc *bufio.Scanner - t *Task - w *cdbWriter -} - -func (t *Task) newCdbMakeWriter(w *cdbWriter, dir string, parser func(s string) ([]string, error)) *cdbMakeWriter { - const sz = 1 << 16 - r := &cdbMakeWriter{ - ar: t.arLookPath, - arBase: filepath.Base(t.arLookPath), - cc: t.ccLookPath, - dir: dir, - parser: parser, - t: t, - w: w, - } - r.sc = bufio.NewScanner(&r.b) - r.sc.Buffer(make([]byte, sz), sz) - return r -} - -func (w *cdbMakeWriter) fail(err error) { - if w.err == nil { - w.err = fmt.Errorf("%v (%v)", err, origin(2)) - } -} - -func (w *cdbMakeWriter) Write(b []byte) (int, error) { - w.b.Write(b) - for bytes.Contains(w.b.Bytes(), []byte{'\n'}) { - if !w.sc.Scan() { - panic(todo("internal error")) - } - - s := w.sc.Text() - if strings.HasSuffix(s, "\\") { - w.prefix += s[:len(s)-1] - continue - } - - s = w.prefix + s - w.prefix = "" - s = strings.TrimSpace(s) - if edx := strings.Index(s, "Entering directory"); edx >= 0 { - s = s[edx+len("Entering directory"):] - s = strings.TrimSpace(s) - if len(s) == 0 { - continue - } - - if (s[0] == '\'' || s[0] == '`') && s[len(s)-1] == '\'' { - s = s[1:] - if len(s) == 0 { - continue - } - - s = s[:len(s)-1] - } - s = `"` + s + `"` - dir, err := strconv.Unquote(s) - if err != nil { - w.fail(err) - continue - } - - dir = filepath.Clean(dir) - if dir == w.dir { - continue - } - - w.dir = dir - fmt.Printf("cd %s\n", dir) - continue - } - - if dmesgs { - dmesg("%v: source line `%s`", origin(1), s) - } - args, err := w.parser(s) - if dmesgs { - dmesg("%v: parser -> %v %[2]q, %v", origin(1), args, err) - } - if err != nil { - w.fail(err) - continue - } - - if len(args) == 0 { - continue - } - - // TODO: change so eg handleGCC returns []cdbItem, skip if none. - - w.it = cdbItem{} - - err = nil - switch args[0] { - case w.cc: - if w.t.verboseCompiledb { - fmt.Printf("source line: %q\n", s) - } - fmt.Printf("CCGO CC: %q\n", args) - err = w.handleGCC(args) - case w.ar: - fallthrough - case w.arBase: - if isCreateArchive(args[1]) { - if w.t.verboseCompiledb { - fmt.Printf("source line: %q\n", s) - } - fmt.Printf("CCGO AR: %q\n", args) - err = w.handleAR(args) - } - case "libtool": - if w.t.verboseCompiledb { - fmt.Printf("source line: %q\n", s) - } - fmt.Printf("CCGO LIBTOOL: %q\n", args) - err = w.handleLibtool(args) - } - if err != nil { - w.fail(err) - continue - } - - if w.it.Output != "" { - w.w.add(w.it) - } - } - return len(b), nil -} - -func (w *cdbMakeWriter) handleLibtool(args []string) error { - w.it = cdbItem{ - Arguments: args, - Directory: w.dir, - } - for i, v := range args { - switch { - case v == "-o" && i < len(args)-1: - w.it.Output = filepath.Join(w.dir, args[i+1]) - } - } - w.it.output(w.cc, w.ar) - return nil -} - -func (w *cdbMakeWriter) handleAR(args []string) error { - w.it = cdbItem{ - Arguments: args, - Directory: w.dir, - } - // TODO: assumes isCreateArchive has already been checked - w.it.Output = filepath.Join(w.dir, args[2]) - return nil -} - -func (w *cdbMakeWriter) handleGCC(args []string) error { - w.it = cdbItem{ - Arguments: args, - Directory: w.dir, - } - for i, v := range args { - switch { - case v == "-o" && i < len(args)-1: - w.it.Output = filepath.Join(w.dir, args[i+1]) - case strings.HasSuffix(v, ".c"): - if w.it.File != "" { - return fmt.Errorf("multiple .c files: %s", v) - } - - w.it.File = filepath.Clean(v) - } - } - w.it.output(w.cc, w.ar) - return nil -} - -type cdbWriter struct { - w *bufio.Writer - items []cdbItem -} - -func newCDBWriter(w io.Writer) *cdbWriter { - return &cdbWriter{w: bufio.NewWriter(w)} -} - -func (w *cdbWriter) add(item cdbItem) { - w.items = append(w.items, item) -} - -func (w *cdbWriter) finish() error { - enc := json.NewEncoder(w.w) - enc.SetIndent("", " ") - if err := enc.Encode(w.items); err != nil { - return err - } - return w.w.Flush() -} - -func join(sep string, a ...interface{}) string { - var b []string - for _, v := range a { - switch x := v.(type) { - case string: - b = append(b, x) - case []string: - b = append(b, x...) - default: - panic(todo("internal error: %T", x)) - } - } - return strings.Join(b, sep) -} - -func inDir(dir string, f func() error) (err error) { - var cwd string - if cwd, err = os.Getwd(); err != nil { - return err - } - - defer func() { - if err2 := os.Chdir(cwd); err2 != nil { - err = err2 - } - }() - - if err = os.Chdir(dir); err != nil { - return err - } - - return f() -} - -func detectMingw(s string) bool { - return strings.Contains(s, "#define __MINGW") -} - -func memGuard(i int, force bool) { - if totalRam == 0 || totalRam > 64e9 { - return - } - - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - switch { - case ms.Alloc < totalRam/2: - return - case ms.Alloc < (8*totalRam)/10: - if force { - break - } - - switch { - case totalRam < 1e9: - // ok - case totalRam < 16e9: - if i&1 == 1 { - return - } - default: - if i&3 != 3 { - return - } - } - } - - debug.FreeOSMemory() -} diff --git a/vendor/modernc.org/ccgo/v3/lib/cover.go b/vendor/modernc.org/ccgo/v3/lib/cover.go deleted file mode 100644 index fdc39f3fa..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/cover.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "fmt" - "runtime" - "sort" - "strings" -) - -var ( - coverMap = map[uintptr]struct{}{} -) - -func pc2origin(pc uintptr) string { - f := runtime.FuncForPC(pc) - var fn, fns string - var fl int - if f != nil { - fn, fl = f.FileLine(pc) - fns = f.Name() - if x := strings.LastIndex(fns, "."); x > 0 { - fns = fns[x+1:] - } - } - return fmt.Sprintf("%s:%d:%s", fn, fl, fns) -} - -func coverReport() string { - var a []string - for pc := range coverMap { - a = append(a, pc2origin(pc)) - } - sort.Strings(a) - return strings.Join(a, "\n") -} diff --git a/vendor/modernc.org/ccgo/v3/lib/design-notes.adoc b/vendor/modernc.org/ccgo/v3/lib/design-notes.adoc deleted file mode 100644 index 880ce7eeb..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/design-notes.adoc +++ /dev/null @@ -1,91 +0,0 @@ -= Design Notes - -== Problems: - -Translating C to Go is harder than it looks. - -Jan says: It's impossible in the general case to turn C char* into Go -[]byte. It's possible to do it probably often for concrete C code -cases - based also on author's C coding style. The first problem this -runs into is that Go does not guarantee that the backing array will -keep its address stable due to Go movable stacks. C expects the -opposite, a pointer never magically modifies itself, so some code will -fail. - -INSERT CODE EXAMPLES ILLUSTRATING THE PROBLEM HERE - -== How the parser works - -There are no comment nodes in the C AST. Instead every cc.Token has a -Sep field: https://godoc.org/modernc.org/cc/v3#Token - -It captures, when configured to do so, all white space preceding the -token, combined, including comments, if any. So we have all white -space/comments information for every token in the AST. A final white -space/comment, preceding EOF, is available as field TrailingSeperator -in the AST: https://godoc.org/modernc.org/cc/v3#AST. - -To get the lexically first white space/comment for any node, use -tokenSeparator(): -https://gitlab.com/cznic/ccgo/-/blob/6551e2544a758fdc265c8fac71fb2587fb3e1042/v3/go.go#L1476 - -The same with a default value is comment(): -https://gitlab.com/cznic/ccgo/-/blob/6551e2544a758fdc265c8fac71fb2587fb3e1042/v3/go.go#L1467 - -== Looking forward - -Eric says: In my visualization of how the translator would work, the -output of a ccgo translation of a module at any given time is a file -of pseudo-Go code in which some sections may be enclosed by a Unicode -bracketing character (presently using the guillemot quotes U+ab and -U+bb) meaning "this is not Go yet" that intentionally makes the Go -compiler barf. This expresses a color on the AST nodes. - -So, for example, if I'm translating hello.c with a ruleset that does not -include print -> fmt.Printf, this: - ---------------------------------------------------------- -#include <stdio> - -/* an example comment */ - -int main(int argc, char *argv[]) -{ - printf("Hello, World") -} ---------------------------------------------------------- - -becomes this without any explicit rules at all: - ---------------------------------------------------------- -«#include <stdio>» - -/* an example comment */ - -func main -{ - «printf(»"Hello, World"!\n"«)» -} ---------------------------------------------------------- - -Then, when the rule print -> fmt.Printf is added, it becomes - ---------------------------------------------------------- -import ( - "fmt" -) - -/* an example comment */ - -func main -{ - fmt.Printf("Hello, World"!\n") -} ---------------------------------------------------------- - -because with that rule the AST node corresponding to the printf -call can be translated and colored "Go". This implies an import -of fmt. We observe that there are no longer C-colored spans -and drop the #includes. - -// end diff --git a/vendor/modernc.org/ccgo/v3/lib/dmesg.go b/vendor/modernc.org/ccgo/v3/lib/dmesg.go deleted file mode 100644 index 6ab93e567..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/dmesg.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 The CCGO Authors. All rights reserved. -// 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" - -import ( - "fmt" - "os" - "path/filepath" - "strings" -) - -const dmesgs = true - -var ( - pid = fmt.Sprintf("[%v %v] ", os.Getpid(), filepath.Base(os.Args[0])) - logf *os.File -) - -func init() { - var err error - if logf, err = os.OpenFile("/tmp/ccgo.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_SYNC, 0644); err != nil { - panic(err.Error()) - } -} - -func dmesg(s string, args ...interface{}) { - if s == "" { - s = strings.Repeat("%v ", len(args)) - } - s = fmt.Sprintf(s, args...) - s = pid + s - switch { - case len(s) != 0 && s[len(s)-1] == '\n': - fmt.Fprint(logf, s) - default: - fmt.Fprintln(logf, s) - } -} diff --git a/vendor/modernc.org/ccgo/v3/lib/etc.go b/vendor/modernc.org/ccgo/v3/lib/etc.go deleted file mode 100644 index e3b8c577a..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/etc.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "fmt" - "math" - "math/big" - - "modernc.org/cc/v3" -) - -var ( - reservedNames = map[string]bool{ - "bool": false, // ccgo can use - "break": true, // keyword - "case": true, // keyword - "chan": true, // keyword - "const": true, // keyword - "continue": true, // keyword - "default": true, // keyword - "defer": true, // keyword - "else": true, // keyword - "fallthrough": true, // keyword - "false": false, // ccgo can use - "float32": false, // ccgo can use - "float64": false, // ccgo can use - "for": true, // keyword - "func": true, // keyword - "go": true, // keyword - "goto": true, // keyword - "if": true, // keyword - "import": true, // keyword - "init": false, // special name - "int16": false, // ccgo can use - "int32": false, // ccgo can use - "int64": false, // ccgo can use - "int8": false, // ccgo can use - "interface": true, // keyword - "map": true, // keyword - "math": false, // package name - "nil": false, // ccgo can use - "package": true, // keyword - "range": true, // keyword - "return": true, // keyword - "select": true, // keyword - "struct": true, // keyword - "switch": true, // keyword - "true": false, // ccgo can use - "type": true, // keyword - "types": false, // package name - "uint16": false, // ccgo can use - "uint32": false, // ccgo can use - "uint64": false, // ccgo can use - "uint8": false, // ccgo can use - "uintptr": false, // ccgo can use - "unsafe": false, // package name - "var": true, // keyword - } - - reservedIds []cc.StringID - - maxInt32 = big.NewInt(math.MaxInt32) - maxInt64 = big.NewInt(math.MaxInt64) - maxUint32 = big.NewInt(math.MaxUint32) - maxUint64 = big.NewInt(0).SetUint64(math.MaxUint64) - minInt32 = big.NewInt(math.MinInt32) - minInt64 = big.NewInt(math.MinInt64) -) - -func init() { - for k := range reservedNames { - reservedIds = append(reservedIds, cc.String(k)) - } -} - -type scope map[cc.StringID]int32 - -func newScope() scope { - s := scope{} - for _, k := range reservedIds { - s[k] = 0 - } - return s -} - -func (s scope) take(t cc.StringID) string { - if t == 0 { - panic(todo("internal error")) - } - - n, ok := s[t] - if !ok { - s[t] = 0 - return t.String() - } - - for { - n++ - s[t] = n - r := fmt.Sprintf("%s%d", t, n) - id := cc.String(r) - if _, ok := s[id]; !ok { - s[id] = 0 - return r - } - } -} diff --git a/vendor/modernc.org/ccgo/v3/lib/go.go b/vendor/modernc.org/ccgo/v3/lib/go.go deleted file mode 100644 index 6238d0c98..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/go.go +++ /dev/null @@ -1,13164 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "bytes" - "fmt" - "go/scanner" - "go/token" - "hash/maphash" - "io/ioutil" - "math" - "math/big" - "os" - "os/exec" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "sync" - "time" - - "modernc.org/cc/v3" - "modernc.org/mathutil" -) - -var ( - idAddOverflow = cc.String("__builtin_add_overflow") // bool __builtin_add_overflow (type1 a, type2 b, type3 *res) - idAlias = cc.String("alias") - idAligned = cc.String("aligned") // int __attribute__ ((aligned (8))) foo; - idAtomicLoadN = cc.String("__atomic_load_n") // type __atomic_load_n (type *ptr, int memorder) - idAtomicStoreN = cc.String("__atomic_store_n") // void __atomic_store_n (type *ptr, type val, int memorder) - idBp = cc.String("bp") - idBuiltinConstantPImpl = cc.String("__builtin_constant_p_impl") - idCAPI = cc.String("CAPI") - idChooseExpr = cc.String("__builtin_choose_expr") - idEnviron = cc.String("environ") - idMain = cc.String("main") - idMulOverflow = cc.String("__builtin_mul_overflow") // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) - idPacked = cc.String("packed") // __attribute__((packed)) - idSubOverflow = cc.String("__builtin_sub_overflow") // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res) - idTls = cc.String("tls") - idTransparentUnion = cc.String("__transparent_union__") - idTs = cc.String("ts") - idVa = cc.String("va") - idVaArg = cc.String("__ccgo_va_arg") - idVaEnd = cc.String("__ccgo_va_end") - idVaList = cc.String("va_list") - idVaStart = cc.String("__ccgo_va_start") - idWcharT = cc.String("wchar_t") - idWinWchar = cc.String("WCHAR") - idWtext = cc.String("wtext") - - bytesBufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} - - oTraceG bool - oTraceW bool - oTracePin bool -) - -type exprMode int - -const ( - doNotExport = iota - doNotChange - exportCapitalize - exportPrefix -) - -const ( - _ exprMode = iota - exprAddrOf // &foo as uinptr (must be static/pinned) - exprBool // foo in foo != 0 - exprCondInit // foo or bar in int i = x ? foo : bar; - exprCondReturn // foo or bar in return x ? foo : bar; - exprDecay // &foo[0] in foo for array foo. - exprFunc // foo in foo(bar) - exprLValue // foo in foo = bar - exprPSelect // foo in foo->bar - exprSelect // foo in foo.bar - exprValue // foo in bar = foo - exprVoid // - exprGoPtr -) - -const ( - tooManyErrors = "too many errors" -) - -type opKind int - -const ( - opNormal opKind = iota - opArray - opArrayParameter - opFunction - opUnion - opBitfield - opStruct -) - -type flags byte - -const ( - fForceConv flags = 1 << iota - fForceNoConv - fForceRuntimeConv - fNoCondAssignment - fAddrOfFuncPtrOk -) - -type imported struct { - path string // Eg. "example.com/user/foo". - name string // Eg. "foo" from "package foo". - qualifier string // Eg. "foo." or "foo2." if renamed due to name conflict. - exports map[string]struct{} // Eg. {"New": {}, "Close": {}, ...}. - - used bool -} - -type taggedStruct struct { - ctyp cc.Type - gotyp string - name string - node cc.Node - - conflicts bool - emitted bool -} - -func (s *taggedStruct) emit(p *project, ds *cc.DeclarationSpecifiers) { - if s == nil || s.emitted { - return - } - - s.emitted = true - p.w("%stype %s = %s; /* %v */\n\n", tidyComment("\n", ds), s.name, s.gotyp, p.pos(s.node)) -} - -// Return first non empty token separator within n or dflt otherwise. -func comment(dflt string, n cc.Node) string { - if s := tokenSeparator(n); s != "" { - return s - } - - return dflt -} - -// tidyComment is like comment but makes comment more Go-like. -func tidyComment(dflt string, n cc.Node) (r string) { return tidyCommentString(comment(dflt, n)) } - -func tidyCommentString(s string) (r string) { - defer func() { - if !strings.Contains(r, "// <blockquote><pre>") { - return - } - - a := strings.Split(r, "\n") - in := false - for i, v := range a { - switch { - case in: - if strings.HasPrefix(v, "// </pre></blockquote>") { - in = false - a[i] = "//" - break - } - - a[i] = fmt.Sprintf("//\t%s", v[3:]) - default: - if strings.HasPrefix(v, "// <blockquote><pre>") { - a[i] = "//" - in = true - } - } - } - r = strings.Join(a, "\n") - }() - - s = strings.ReplaceAll(s, "\f", "") - b := bytesBufferPool.Get().(*bytes.Buffer) - defer func() { b.Reset(); bytesBufferPool.Put(b) }() - for len(s) != 0 { - c := s[0] - s = s[1:] - if len(s) == 0 { - b.WriteByte(c) - break - } - - if c != '/' { - b.WriteByte(c) - continue - } - - c2 := s[0] - s = s[1:] - switch c2 { - case '/': // line comment start - b.WriteByte(c) - b.WriteByte(c2) - for { - c := s[0] - s = s[1:] - b.WriteByte(c) - if c == '\n' { - break - } - } - case '*': // block comment start - b2 := bytesBufferPool.Get().(*bytes.Buffer) - defer func() { b2.Reset(); bytesBufferPool.Put(b2) }() - for { - c := s[0] - s = s[1:] - if c != '*' { - b2.WriteByte(c) - continue - } - - more: - c2 := s[0] - s = s[1:] - if c2 == '*' { - b2.WriteByte(c) - goto more - } - - if c2 != '/' { - b2.WriteByte(c) - b2.WriteByte(c2) - continue - } - - break - } - s2 := b2.String() // comment sans /* prefix and */ suffix - a := strings.Split(s2, "\n") - nl := len(s) != 0 && s[0] == '\n' - if len(a) == 1 { // /* foo */ form - if nl { - s = s[1:] - fmt.Fprintf(b, "//%s\n", s2) - break - } - - fmt.Fprintf(b, "/*%s*/", s2) - break - } - - if !nl { - fmt.Fprintf(b, "/*%s*/", s2) - break - } - - // Block comment followed by a newline can be safely replaced by a sequence of - // line comments. Try to enhance the comment. - if commentForm1(b, a) || - commentForm2(b, a) || - commentForm3(b, a) { - break - } - - // No enhancement posibilities detected, use the default form. - if a[len(a)-1] == "" { - a = a[:len(a)-1] - } - fmt.Fprintf(b, "//%s", a[0]) - for _, v := range a[1:] { - fmt.Fprintf(b, "\n// %s", v) - } - default: - b.WriteByte(c) - b.WriteByte(c2) - } - } - return b.String() -} - -func commentForm1(b *bytes.Buffer, a []string) bool { - // Example - // - // /* - // ** Initialize this module. - // ** - // ** This Tcl module contains only a single new Tcl command named "sqlite". - // ** (Hence there is no namespace. There is no point in using a namespace - // ** if the extension only supplies one new name!) The "sqlite" command is - // ** used to open a new SQLite database. See the DbMain() routine above - // ** for additional information. - // ** - // ** The EXTERN macros are required by TCL in order to work on windows. - // */ - if strings.TrimSpace(a[0]) != "" { - return false - } - - if strings.TrimSpace(a[len(a)-1]) != "" { - return false - } - - a = a[1 : len(a)-1] - if len(a) == 0 { - return false - } - - for i, v := range a { - v = strings.TrimSpace(v) - if !strings.HasPrefix(v, "*") { - return false - } - - a[i] = strings.TrimLeft(v, "*") - } - - fmt.Fprintf(b, "//%s", a[0]) - for _, v := range a[1:] { - fmt.Fprintf(b, "\n//%s", v) - } - return true -} - -func commentForm2(b *bytes.Buffer, a []string) bool { - // Example - // - // /**************************** sqlite3_column_ ******************************* - // ** The following routines are used to access elements of the current row - // ** in the result set. - // */ - if strings.TrimSpace(a[len(a)-1]) != "" { - return false - } - - a = a[:len(a)-1] - if len(a) == 0 { - return false - } - - for i, v := range a[1:] { - v = strings.TrimSpace(v) - if !strings.HasPrefix(v, "*") { - return false - } - - a[i+1] = strings.TrimLeft(v, "*") - } - - fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) - if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { - fmt.Fprintf(b, "\n//") - } - for _, v := range a[1:] { - fmt.Fprintf(b, "\n//%s", v) - } - return true -} - -func commentForm3(b *bytes.Buffer, a []string) bool { - // Example - // - // /* Call sqlite3_shutdown() once before doing anything else. This is to - // ** test that sqlite3_shutdown() can be safely called by a process before - // ** sqlite3_initialize() is. */ - for i, v := range a[1:] { - v = strings.TrimSpace(v) - if !strings.HasPrefix(v, "*") { - return false - } - - a[i+1] = strings.TrimLeft(v, "*") - } - - fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) - if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { - fmt.Fprintf(b, "\n//") - } - for _, v := range a[1:] { - fmt.Fprintf(b, "\n//%s", v) - } - return true -} - -// Return the preceding white space, including any comments, of the first token -// of n. -func tokenSeparator(n cc.Node) (r string) { - if n == nil { - return "" - } - - var tok cc.Token - cc.Inspect(n, func(n cc.Node, _ bool) bool { - if x, ok := n.(*cc.Token); ok { - if a, b := tok.Seq(), x.Seq(); a == 0 || a > x.Seq() && b != 0 { - tok = *x - } - } - return true - }) - return tok.Sep.String() -} - -func source(n ...cc.Node) (r string) { - if len(n) == 0 { - return "<nil>" - } - - var a []*cc.Token - for _, v := range n { - cc.Inspect(v, func(n cc.Node, _ bool) bool { - if x, ok := n.(*cc.Token); ok && x.Seq() != 0 { - a = append(a, x) - } - return true - }) - } - sort.Slice(a, func(i, j int) bool { - return a[i].Seq() < a[j].Seq() - }) - w := 0 - seq := -1 - for _, v := range a { - if n := v.Seq(); n != seq { - seq = n - a[w] = v - w++ - } - } - a = a[:w] - var b strings.Builder - for _, v := range a { - b.WriteString(v.Sep.String()) - b.WriteString(v.Src.String()) - } - return b.String() -} - -type initPatch struct { - t cc.Type - init *cc.Initializer - fld cc.Field -} - -type tld struct { - name string // Can differ from the original one. - patches []initPatch -} - -type block struct { - block *cc.CompoundStatement - decls []*cc.Declaration // What to declare in this block. - params []*cc.Parameter - parent *block - scope scope - - noDecl bool // Locals declared in one of the parent scopes. - topDecl bool // Declare locals at block start to avoid "jumps over declaration". -} - -func newBlock(parent *block, n *cc.CompoundStatement, decls []*cc.Declaration, params []*cc.Parameter, scope scope, topDecl bool) *block { - return &block{ - block: n, - decls: decls, - params: params, - parent: parent, - scope: scope, - topDecl: topDecl, - } -} - -type local struct { - name string - off uintptr // If isPinned: bp+off - - forceRead bool // Possibly never read. - isPinned bool // Prevent this local from being placed in Go movable stack. -} - -type switchState int - -const ( - _ switchState = iota // Not in switch. - inSwitchFirst // Before seeing "case/default". - inSwitchCase // Seen "case/default". - inSwitchSeenBreak // In switch "case/default" and seen "break/return". - inSwitchFlat -) - -type function struct { - block *block - blocks map[*cc.CompoundStatement]*block - bpName string - breakCtx int //TODO merge with continueCtx - complits map[*cc.PostfixExpression]uintptr - condInitPrefix func() - continueCtx int - flatLabels int - flatSwitchLabels map[*cc.LabeledStatement]int - fndef *cc.FunctionDefinition - gen *project - ifCtx cc.Node - ignore map[*cc.Declarator]bool // Pseudo declarators - labelNames map[cc.StringID]string - labels scope - locals map[*cc.Declarator]*local - off uintptr // bp+off allocs - params []*cc.Parameter // May differ from what fndef says - project *project - rt cc.Type // May differ from what fndef says - scope scope - switchCtx switchState - tlsName string - top *block - unusedLabels map[cc.StringID]struct{} - vaLists map[*cc.PostfixExpression]uintptr - vaName string - vaType cc.Type - vlas map[*cc.Declarator]struct{} - - hasJumps bool - mainSignatureForced bool -} - -func newFunction(p *project, n *cc.FunctionDefinition) *function { - d := n.Declarator - t := d.Type() - rt := t.Result() - params := t.Parameters() - var mainSignatureForced bool - var ignore map[*cc.Declarator]bool - if d.Name() == idMain && d.Linkage == cc.External { - if rt.Kind() != cc.Int { - rt = p.task.cfg.ABI.Type(cc.Int) - } - if len(params) != 2 { - mainSignatureForced = true - d1 := newDeclarator("argc") - t1 := p.task.cfg.ABI.Type(cc.Int) - d2 := newDeclarator("argv") - t2 := p.task.cfg.ABI.Ptr(n, p.task.cfg.ABI.Type(cc.Void)) - params = []*cc.Parameter{ - cc.NewParameter(d1, t1), - cc.NewParameter(d2, t2), - } - ignore = map[*cc.Declarator]bool{d1: true, d2: true} - } - } - f := &function{ - blocks: map[*cc.CompoundStatement]*block{}, - complits: map[*cc.PostfixExpression]uintptr{}, - fndef: n, - gen: p, - hasJumps: n.CompoundStatement.IsJumpTarget(), - ignore: ignore, - locals: map[*cc.Declarator]*local{}, - mainSignatureForced: mainSignatureForced, - params: params, - project: p, - rt: rt, - scope: p.newScope(), - unusedLabels: map[cc.StringID]struct{}{}, - vaLists: map[*cc.PostfixExpression]uintptr{}, - vlas: map[*cc.Declarator]struct{}{}, - } - f.tlsName = f.scope.take(idTls) - if t.IsVariadic() { - f.vaName = f.scope.take(idVa) - } - f.layoutLocals(nil, n.CompoundStatement, params) - var extern []cc.StringID - for _, v := range n.CompoundStatements() { // testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/scope-1.c - for _, v := range v.Declarations() { - for list := v.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { - if d := list.InitDeclarator.Declarator; d != nil && d.IsExtern() { - extern = append(extern, d.Name()) - } - } - } - } - for _, v := range n.CompoundStatements() { - block := f.blocks[v] - for _, v := range extern { - if tld := f.project.externs[v]; tld != nil { - block.scope.take(cc.String(tld.name)) - } - } - } - for _, v := range n.CompoundStatements() { - f.layoutBlocks(v) - } - f.renameLabels() - f.staticAllocsAndPinned(n.CompoundStatement) - return f -} - -func (f *function) flatLabel() int { - if f.project.pass1 { - return 1 - } - - f.flatLabels++ - return f.flatLabels -} - -func (f *function) renameLabels() { - var a []cc.StringID - for _, v := range f.fndef.Labels { - if v.Case != cc.LabeledStatementLabel { - continue - } - - a = append(a, v.Token.Value) - f.unusedLabels[v.Token.Value] = struct{}{} - } - for _, v := range f.fndef.Gotos { - delete(f.unusedLabels, v.Token2.Value) - } - if len(a) == 0 { - return - } - sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) - f.labels = newScope() - f.labelNames = map[cc.StringID]string{} - for _, id := range a { - f.labelNames[id] = f.labels.take(id) - } -} - -func (f *function) staticAllocsAndPinned(n *cc.CompoundStatement) { - for _, v := range f.params { - switch { - case v.Type().Kind() == cc.Array && v.Type().IsVLA(): - // trc("VLA") - f.project.err(f.fndef, "variable length arrays not supported") - } - } - - //TODO use pass1 for this - cc.Inspect(n, func(n cc.Node, entry bool) bool { - if !entry { - return true - } - - switch x := n.(type) { - case *cc.CastExpression: - switch x.Case { - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - if t := x.TypeName.Type(); t != nil && t.Kind() != cc.Void { - break - } - - if d := x.CastExpression.Declarator(); d != nil { - if local := f.locals[d]; local != nil { - local.forceRead = true - } - } - } - } - - x, ok := n.(*cc.PostfixExpression) - if !ok || x.Case != cc.PostfixExpressionCall { - return true - } - - if x.PostfixExpression == nil || x.PostfixExpression.Operand == nil || x.PostfixExpression.Operand.Type() == nil { - return true - } - - ft := funcType(x.PostfixExpression.Operand.Type()) - if ft.Kind() != cc.Function { - return true - } - - if !ft.IsVariadic() { - return true - } - - fixedParams := len(ft.Parameters()) - iArg := 0 - var need uintptr - for list := x.ArgumentExpressionList; list != nil; list, iArg = list.ArgumentExpressionList, iArg+1 { - if iArg < fixedParams { - continue - } - - t := list.AssignmentExpression.Operand.Type() - if t.IsIntegerType() { - need += 8 - continue - } - - switch t.Kind() { - case cc.Array, cc.Ptr, cc.Double, cc.Float, cc.Function: - need += 8 - default: - panic(todo("", f.project.pos(x), t, t.Kind())) - } - } - if need != 0 { - //TODO- if f.project.task.mingw { - //TODO- need += 8 // On windows the va list is prefixed with its length - //TODO- } - va := roundup(f.off, 8) - f.vaLists[x] = va - f.off = va + need - } - return true - }) -} - -func funcType(t cc.Type) cc.Type { - if t.Kind() == cc.Ptr { - t = t.Elem() - } - return t -} - -type declarator interface { - Declarator() *cc.Declarator - cc.Node -} - -func (p *project) isArrayParameterDeclarator(d *cc.Declarator) bool { - if d.Type().Kind() == cc.Array { - if d.Type().IsVLA() { - return false - } - - return d.IsParameter - } - - return false -} - -func (p *project) isArrayDeclarator(d *cc.Declarator) bool { - if d.Type().Kind() == cc.Array { - if d.Type().IsVLA() { - return false - } - - return !d.IsParameter - } - - return false -} - -func (p *project) isArrayParameter(n declarator, t cc.Type) bool { - if t.Kind() != cc.Array { - return false - } - - if t.IsVLA() { - return false - } - - if d := n.Declarator(); d != nil { - return d.IsParameter - } - - return false -} - -func (p *project) isArrayOrPinnedArray(f *function, n declarator, t cc.Type) (r bool) { - if t.Kind() != cc.Array { - return false - } - - if t.IsVLA() { - return false - } - - if d := n.Declarator(); d != nil { - return !d.IsParameter - } - - return p.detectArray(f, n.(cc.Node), true, true, nil) -} - -func (p *project) detectArray(f *function, n cc.Node, pinnedOk, recursiveOk bool, out **cc.Declarator) bool { - switch x := n.(type) { - case *cc.AssignmentExpression: - switch x.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - return p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.ConditionalExpression: - switch x.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) || - p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || - p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.LogicalOrExpression: - switch x.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - return p.detectArray(f, x.LogicalAndExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.LogicalAndExpression: - switch x.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - return p.detectArray(f, x.InclusiveOrExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.InclusiveOrExpression: - switch x.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - return p.detectArray(f, x.ExclusiveOrExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.ExclusiveOrExpression: - switch x.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - return p.detectArray(f, x.AndExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.AndExpression: - switch x.Case { - case cc.AndExpressionEq: // EqualityExpression - return p.detectArray(f, x.EqualityExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.EqualityExpression: - switch x.Case { - case cc.EqualityExpressionRel: // RelationalExpression - return p.detectArray(f, x.RelationalExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.RelationalExpression: - switch x.Case { - case cc.RelationalExpressionShift: // ShiftExpression - return p.detectArray(f, x.ShiftExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.ShiftExpression: - switch x.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.AdditiveExpression: - switch x.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - return p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) - case - cc.AdditiveExpressionSub, // AdditiveExpression '-' MultiplicativeExpression - cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - - return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.MultiplicativeExpression: - switch x.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) - default: - return false - } - case *cc.CastExpression: - switch x.Case { - case cc.CastExpressionUnary: // UnaryExpression - return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.UnaryExpression: - switch x.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - return p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) - case - cc.UnaryExpressionDeref, // '*' CastExpression - cc.UnaryExpressionAddrof: // '&' CastExpression - - return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) - case - cc.UnaryExpressionSizeofExpr, // "sizeof" UnaryExpression - cc.UnaryExpressionSizeofType, // "sizeof" '(' TypeName ')' - cc.UnaryExpressionMinus, // '-' CastExpression - cc.UnaryExpressionCpl, // '~' CastExpression - cc.UnaryExpressionAlignofExpr, // "_Alignof" UnaryExpression - cc.UnaryExpressionAlignofType, // "_Alignof" '(' TypeName ')' - cc.UnaryExpressionNot, // '!' CastExpression - cc.UnaryExpressionInc, // "++" UnaryExpression - cc.UnaryExpressionDec, // "--" UnaryExpression - cc.UnaryExpressionPlus: // '+' CastExpression - - return false - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.PostfixExpression: - switch x.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - return p.detectArray(f, x.PrimaryExpression, pinnedOk, recursiveOk, out) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - return recursiveOk && p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) - case - cc.PostfixExpressionSelect, // PostfixExpression '.' IDENTIFIER - cc.PostfixExpressionDec, // PostfixExpression "--" - cc.PostfixExpressionInc, // PostfixExpression "++" - cc.PostfixExpressionCall, // PostfixExpression '(' ArgumentExpressionList ')' - cc.PostfixExpressionComplit, // '(' TypeName ')' '{' InitializerList ',' '}' - cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - - return false - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.PrimaryExpression: - switch x.Case { - case - cc.PrimaryExpressionString, // STRINGLITERAL - cc.PrimaryExpressionEnum, // ENUMCONST - cc.PrimaryExpressionChar, // CHARCONST - cc.PrimaryExpressionLChar, // LONGCHARCONST - cc.PrimaryExpressionLString, // LONGSTRINGLITERAL - cc.PrimaryExpressionFloat, // FLOATCONST - cc.PrimaryExpressionInt: // INTCONST - - return false - case cc.PrimaryExpressionIdent: // IDENTIFIER - d := x.Declarator() - if d == nil || d.IsParameter { - return false - } - - if d.Type().Kind() != cc.Array { - return false - } - - if d.Type().IsVLA() { - return false - } - - if pinnedOk { - if out != nil { - *out = d - } - return true - } - - local := f.locals[d] - if local == nil || local.isPinned { - return false - } - - if out != nil { - *out = d - } - return true - case cc.PrimaryExpressionExpr: // '(' Expression ')' - return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.err(x, "statement expressions not supported") - return false - default: - panic(todo("", p.pos(x), x.Case)) - } - case *cc.Expression: - switch x.Case { - case cc.ExpressionAssign: // AssignmentExpression - return p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) - default: - panic(todo("", p.pos(x), x.Case)) - } - default: - panic(todo("%T", x)) - } -} - -func (p *project) isArray(f *function, n declarator, t cc.Type) (r bool) { - if t.Kind() != cc.Array { - return false - } - - if t.IsVLA() { - return false - } - - if f == nil { - return true - } - - if d := n.Declarator(); d != nil { - local := f.locals[d] - return !d.IsParameter && (local == nil || !local.isPinned) - } - - return p.detectArray(f, n.(cc.Node), false, true, nil) -} - -var home = os.Getenv("HOME") - -// Return n's position with path reduced to baseName(path) unless -// p.task.fullPathComments is true. -func (p *project) pos(n cc.Node) (r token.Position) { - if n == nil { - return r - } - - if r = token.Position(n.Position()); r.IsValid() { - switch { - case p.task.fullPathComments: - if strings.HasPrefix(r.Filename, home) { - r.Filename = "$HOME" + r.Filename[len(home):] - } - default: - r.Filename = filepath.Base(r.Filename) - } - } - return r -} - -// Return n's position with path reduced to baseName(path). -func pos(n cc.Node) (r token.Position) { - if n == nil { - return r - } - - r = token.Position(n.Position()) - if r.IsValid() { - r.Filename = filepath.Base(r.Filename) - } - return r -} - -func roundup(n, to uintptr) uintptr { - if r := n % to; r != 0 { - return n + to - r - } - - return n -} - -func (f *function) pin(n cc.Node, d *cc.Declarator) { - local := f.locals[d] - if local == nil || local.isPinned { - return - } - - local.isPinned = true - if oTracePin || f.project.task.tracePinning { - fmt.Printf("%v: %s at %v: is pinned (%v)\n", n.Position(), d.Name(), d.Position(), origin(2)) - } - local.off = roundup(f.off, uintptr(d.Type().Align())) - f.off = local.off + paramTypeDecay(d).Size() -} - -func paramTypeDecay(d *cc.Declarator) (r cc.Type) { - r = d.Type() - if d.IsParameter && r.Kind() == cc.Array { - r = r.Decay() - } - return r -} - -func (f *function) layoutBlocks(n *cc.CompoundStatement) { - block := f.blocks[n] - type item struct { - ds *cc.DeclarationSpecifiers - d *cc.Declarator - } - var work []item - for _, v := range block.params { - if v.Type().Kind() == cc.Void { - break - } - - work = append(work, item{nil, v.Declarator()}) - } - for _, decl := range block.decls { - ds := decl.DeclarationSpecifiers - for list := decl.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { - work = append(work, item{ds, list.InitDeclarator.Declarator}) - } - } - block.scope.take(cc.String(f.tlsName)) - if f.vaName != "" { - block.scope.take(cc.String(f.vaName)) - } - for _, item := range work { - d := item.d - if f.ignore[d] { - continue - } - - if !f.ignore[d] && d.IsStatic() { - continue - } - - if d.IsFunctionPrototype() || d.IsExtern() { - continue - } - - local := &local{forceRead: d.Read == 0} - if t := d.Type(); t != nil && t.Name() == idVaList { - local.forceRead = true - } - f.locals[d] = local - local.name = block.scope.take(d.Name()) - } -} - -func (f *function) layoutLocals(parent *block, n *cc.CompoundStatement, params []*cc.Parameter) { - block := newBlock(parent, n, n.Declarations(), params, f.project.newScope(), n.IsJumpTarget()) - f.blocks[n] = block - if parent == nil { - f.top = block - f.top.topDecl = f.hasJumps - } - for _, ch := range n.Children() { - f.layoutLocals(block, ch, nil) - if f.hasJumps { - chb := f.blocks[ch] - chb.noDecl = true - f.top.decls = append(f.top.decls, chb.decls...) - chb.decls = nil - } - } -} - -func newDeclarator(name string) *cc.Declarator { - return &cc.Declarator{ - DirectDeclarator: &cc.DirectDeclarator{ - Case: cc.DirectDeclaratorIdent, - Token: cc.Token{Rune: cc.IDENTIFIER, Value: cc.String(name)}, - }, - } -} - -type enumSpec struct { - decl *cc.Declaration - spec *cc.EnumSpecifier - - emitted bool -} - -func (n *enumSpec) emit(p *project) { - if n == nil || p.pass1 || n.emitted { - return - } - - n.emitted = true - ok := false - for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { - nm := list.Enumerator.Token.Value - if _, ok2 := p.emitedEnums[nm]; !ok2 && p.enumConsts[nm] != "" { - ok = true - break - } - } - if !ok { - return - } - - p.w("%s", tidyComment("\n", n.decl)) - p.w("const ( /* %v: */", p.pos(n.decl)) - for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { - en := list.Enumerator - nm := en.Token.Value - if _, ok := p.emitedEnums[nm]; ok || p.enumConsts[nm] == "" { - continue - } - - p.emitedEnums[nm] = struct{}{} - p.w("%s%s = ", tidyComment("\n", en), p.enumConsts[nm]) - p.intConst(en, "", en.Operand, en.Operand.Type(), fForceNoConv) - p.w(";") - } - p.w(");") -} - -type typedef struct { - sig uint64 - tld *tld -} - -type define struct { - name string - value cc.Value -} - -type project struct { - ast *cc.AST - buf bytes.Buffer - capi []string - defines map[cc.StringID]define - defineLines []string - emitedEnums map[cc.StringID]struct{} - enumConsts map[cc.StringID]string - enumSpecs map[*cc.EnumSpecifier]*enumSpec - errors scanner.ErrorList - externs map[cc.StringID]*tld - fn string - imports map[string]*imported // C name: import info - intType cc.Type - localTaggedStructs []func() - mainName string - ptrSize uintptr - ptrType cc.Type - scope scope - sharedFns map[*cc.FunctionDefinition]struct{} - sharedFnsEmitted map[*cc.FunctionDefinition]struct{} - staticQueue []*cc.InitDeclarator - structs map[cc.StringID]*taggedStruct // key: C tag - symtab map[string]interface{} // *tld or *imported - task *Task - tldScope scope - tlds map[*cc.Declarator]*tld - ts bytes.Buffer // Text segment - tsName string - tsNameP string - tsOffs map[cc.StringID]uintptr - tsW []rune // Text segment, wchar_t - tsWName string - tsWNameP string - tsWOffs map[cc.StringID]uintptr - typeSigHash maphash.Hash - typedefTypes map[cc.StringID]*typedef - typedefsEmited map[string]struct{} - verifyStructs map[string]cc.Type - wanted map[*cc.Declarator]struct{} - wcharSize uintptr - - isMain bool - pass1 bool - pauseCodegen bool -} - -func newProject(t *Task) (*project, error) { - voidType := t.cfg.ABI.Type(cc.Void) - ptrType := t.cfg.ABI.Ptr(nil, voidType) - intType := t.cfg.ABI.Type(cc.Int) - if intType.Size() != 4 { // We're assuming wchar_t is int32. - return nil, fmt.Errorf("unsupported C int size: %d", intType.Size()) - } - - if n := t.cfg.ABI.Types[cc.UChar].Size; n != 1 { - return nil, fmt.Errorf("unsupported C unsigned char size: %d", n) - } - - if n := t.cfg.ABI.Types[cc.UShort].Size; n != 2 { - return nil, fmt.Errorf("unsupported C unsigned short size: %d", n) - } - - if n := t.cfg.ABI.Types[cc.UInt].Size; n != 4 { - return nil, fmt.Errorf("unsupported C unsigned int size: %d", n) - } - - if n := t.cfg.ABI.Types[cc.ULongLong].Size; n != 8 { - return nil, fmt.Errorf("unsupported C unsigned long long size: %d", n) - } - - p := &project{ - defines: map[cc.StringID]define{}, - emitedEnums: map[cc.StringID]struct{}{}, - enumConsts: map[cc.StringID]string{}, - enumSpecs: map[*cc.EnumSpecifier]*enumSpec{}, - externs: map[cc.StringID]*tld{}, - imports: map[string]*imported{}, - intType: intType, - ptrSize: t.cfg.ABI.Types[cc.Ptr].Size, - ptrType: ptrType, - scope: newScope(), - sharedFns: t.cfg.SharedFunctionDefinitions.M, - sharedFnsEmitted: map[*cc.FunctionDefinition]struct{}{}, - symtab: map[string]interface{}{}, - task: t, - tlds: map[*cc.Declarator]*tld{}, - tsWOffs: map[cc.StringID]uintptr{}, - tsOffs: map[cc.StringID]uintptr{}, - typedefTypes: map[cc.StringID]*typedef{}, - typedefsEmited: map[string]struct{}{}, - verifyStructs: map[string]cc.Type{}, - wanted: map[*cc.Declarator]struct{}{}, - wcharSize: t.asts[0].WideCharType.Size(), - } - p.tldScope = p.scope - p.scope.take(idCAPI) - for _, v := range t.imported { - var err error - if v.name, v.exports, err = t.capi(v.path); err != nil { - return nil, err - } - - v.qualifier = p.scope.take(cc.String(v.name)) + "." - for k := range v.exports { - if p.imports[k] == nil { - p.imports[k] = v - } - } - } - p.tsNameP = p.scope.take(idTs) - p.tsName = p.scope.take(idTs) - p.tsWNameP = p.scope.take(idWtext) - p.tsWName = p.scope.take(idWtext) - if err := p.layout(); err != nil { - return nil, err - } - - return p, nil -} - -func (p *project) newScope() scope { - s := newScope() - var a []cc.StringID - for k := range p.structs { - a = append(a, k) - } - sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) - for _, k := range a { - s.take(cc.String(p.structs[k].name)) - } - return s -} - -func (p *project) err(n cc.Node, s string, args ...interface{}) { - if p.task.errTrace || strings.Contains(s, "internal error") { - s = s + "(" + origin(2) + ")" - } - if p.task.traceTranslationUnits { - trc("%v: error: %s (%v)", pos(n), fmt.Sprintf(s, args...), origin(2)) - } - if !p.task.allErrors && len(p.errors) >= 10 { - return - } - - switch { - case n == nil: - p.errors.Add(token.Position{}, fmt.Sprintf(s, args...)) - default: - p.errors.Add(token.Position(n.Position()), fmt.Sprintf(s, args...)) - if !p.task.allErrors && len(p.errors) == 10 { - p.errors.Add(token.Position(n.Position()), tooManyErrors) - } - } -} - -func (p *project) o(s string, args ...interface{}) { - if oTraceG { - fmt.Printf(s, args...) - } - fmt.Fprintf(p.task.out, s, args...) -} - -func (p *project) w(s string, args ...interface{}) { - if p.pass1 || p.pauseCodegen { - return - } - - if coverExperiment { - pc, _, _, ok := runtime.Caller(1) - if ok { - coverMap[pc] = struct{}{} - } - } - if oTraceW { - fmt.Printf(s, args...) - } - //fmt.Fprintf(&p.buf, "/* %s */", origin(2)) //TODO- - fmt.Fprintf(&p.buf, s, args...) -} - -func (p *project) layout() error { - if err := p.layoutTLDs(); err != nil { - return err - } - - if err := p.layoutSymtab(); err != nil { - return err - } - - if err := p.layoutStructs(); err != nil { - return err - } - - if err := p.layoutEnums(); err != nil { - return err - } - - if err := p.layoutDefines(); err != nil { - return err - } - - return p.layoutStaticLocals() -} - -func (p *project) layoutSymtab() error { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing symbol table ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - - for _, i := range p.task.symSearchOrder { - switch { - case i < 0: - imported := p.task.imported[-i-1] - for nm := range imported.exports { - if _, ok := p.symtab[nm]; !ok { - p.symtab[nm] = imported - } - } - default: - ast := p.task.asts[i] - for d := range ast.TLD { - if d.IsFunctionPrototype() || d.Linkage != cc.External { - continue - } - - nm := d.Name() - name := nm.String() - if _, ok := p.symtab[name]; !ok { - tld := p.externs[nm] - if tld == nil { - if d.Type().Kind() != cc.Function && !p.task.header { - p.err(d, "back-end: undefined: %s %v %v", d.Name(), d.Type(), d.Type().Kind()) - } - continue - } - - p.symtab[name] = tld - } - } - } - } - return nil -} - -func (p *project) layoutDefines() error { - if !p.task.exportDefinesValid { - return nil - } - - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing #defines ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - - var prefix = p.task.exportDefines - taken := map[cc.StringID]struct{}{} - for _, ast := range p.task.asts { - var a []cc.StringID - for nm, m := range ast.Macros { - if m.IsFnLike() { - continue - } - - if strings.HasPrefix(nm.String(), "__") { - continue - } - - if _, ok := taken[nm]; ok { - continue - } - - taken[nm] = struct{}{} - a = append(a, nm) - } - sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) - for _, nm := range a { - m := ast.Macros[nm] - val, src := evalMacro(m, ast) - if src == "" { - continue - } - - name := nm.String() - switch { - case prefix == "": - name = capitalize(name) - default: - name = prefix + name - } - name = p.scope.take(cc.String(name)) - p.defines[nm] = define{name, val} - p.defineLines = append(p.defineLines, fmt.Sprintf("%s = %s // %v:", name, src, p.pos(m))) - } - } - return nil -} - -func evalMacro(m *cc.Macro, ast *cc.AST) (cc.Value, string) { - toks := m.ReplacementTokens() - if len(toks) != 1 { - return evalMacro2(m, ast) - } - - src := strings.TrimSpace(toks[0].Src.String()) - if len(src) == 0 { - return nil, "" - } - - neg := "" - switch src[0] { - case '"': - if _, err := strconv.Unquote(src); err == nil { - return cc.StringValue(cc.String(src)), src - } - case '-': - neg = "-" - src = src[1:] - fallthrough - default: - src = strings.TrimRight(src, "lLuU") - if u64, err := strconv.ParseUint(src, 0, 64); err == nil { - switch { - case neg == "": - return cc.Uint64Value(u64), src - default: - return cc.Int64Value(-u64), neg + src - } - } - - src = strings.TrimRight(src, "fF") - if f64, err := strconv.ParseFloat(src, 64); err == nil { - return cc.Float64Value(f64), neg + src - } - } - - return evalMacro2(m, ast) -} - -func evalMacro2(m *cc.Macro, ast *cc.AST) (cc.Value, string) { - op, err := ast.Eval(m) - if err != nil { - return nil, "" - } - - switch x := op.Value().(type) { - case cc.Int64Value: - return op.Value(), fmt.Sprintf("%d", int64(x)) - case cc.Uint64Value: - return op.Value(), fmt.Sprintf("%d", uint64(x)) - default: - panic(todo("", pos(m))) - } -} - -func (p *project) layoutEnums() error { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing enum values ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - - export := doNotChange - if p.task.exportEnumsValid { - switch { - case p.task.exportEnums != "": - export = exportPrefix - default: - export = exportCapitalize - } - } else if p.task.defaultUnExport { - export = doNotExport - } - - var enumList []*cc.EnumSpecifier - for _, v := range p.task.asts { - for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { - decl := list.ExternalDeclaration - switch decl.Case { - case cc.ExternalDeclarationDecl: // Declaration - // ok - default: - continue - } - - cc.Inspect(decl.Declaration.DeclarationSpecifiers, func(n cc.Node, entry bool) bool { - if !entry { - return true - } - - x, ok := n.(*cc.EnumSpecifier) - if !ok || x.Case != cc.EnumSpecifierDef { - return true - } - - if _, ok := p.enumSpecs[x]; !ok { - enumList = append(enumList, x) - p.enumSpecs[x] = &enumSpec{decl: decl.Declaration, spec: x} - } - return true - }) - } - } - - vals := map[cc.StringID]interface{}{} - for _, v := range enumList { - for list := v.EnumeratorList; list != nil; list = list.EnumeratorList { - en := list.Enumerator - nm := en.Token.Value - var val int64 - switch x := en.Operand.Value().(type) { - case cc.Int64Value: - val = int64(x) - case cc.Uint64Value: - val = int64(x) - default: - panic(todo("")) - } - switch ex, ok := vals[nm]; { - case ok: - switch { - case ex == nil: // - continue - case ex == val: // same name and same value - continue - default: // same name, different value - vals[nm] = nil - } - default: - vals[nm] = val - } - p.enumConsts[nm] = "" - } - } - var a []cc.StringID - for nm := range p.enumConsts { - if val, ok := vals[nm]; ok && val == nil { - delete(p.enumConsts, nm) - continue - } - - a = append(a, nm) - } - sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) - for _, nm := range a { - name := nm.String() - switch export { - case doNotExport: - name = unCapitalize(name) - case doNotChange: - // nop - case exportCapitalize: - name = capitalize(name) - case exportPrefix: - name = p.task.exportEnums + name - } - name = p.scope.take(cc.String(name)) - p.enumConsts[nm] = name - } - return nil -} - -func (p *project) layoutStaticLocals() error { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing static local declarations ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - for _, v := range p.task.asts { - for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { - decl := list.ExternalDeclaration - switch decl.Case { - case cc.ExternalDeclarationFuncDef: // FunctionDefinition - // ok - default: - continue - } - - cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { - switch x := n.(type) { - case *cc.Declarator: - if !entry || !x.IsStatic() || x.Read == 0 || x.IsParameter { - break - } - - nm := x.Name() - if s := p.task.staticLocalsPrefix; s != "" { - nm = cc.String(s + nm.String()) - } - p.tlds[x] = &tld{name: p.scope.take(nm)} - } - return true - }) - } - } - return nil -} - -func (p *project) layoutStructs() error { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing struct/union types ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - - export := doNotChange - if p.task.exportStructsValid { - switch { - case p.task.exportStructs != "": - export = exportPrefix - default: - export = exportCapitalize - } - } else if p.task.defaultUnExport { - export = doNotExport - } - - m := map[cc.StringID]*taggedStruct{} - var tags []cc.StringID - for _, v := range p.task.asts { - cc.Inspect(v.TranslationUnit, func(n cc.Node, entry bool) bool { - if entry { - switch x := n.(type) { - case *cc.Declarator: - if nm := x.Name().String(); strings.HasPrefix(nm, "_") { - break - } - - p.captureStructTags(x, x.Type(), m, &tags) - case *cc.Declaration: - cc.Inspect(x.DeclarationSpecifiers, func(nn cc.Node, entry bool) bool { - switch y := nn.(type) { - case *cc.StructOrUnionSpecifier: - if tag := y.Token.Value; tag != 0 { - p.captureStructTags(y, y.Type(), m, &tags) - } - } - return true - }) - } - } - return true - }) - } - sort.Slice(tags, func(i, j int) bool { return tags[i].String() < tags[j].String() }) - for _, k := range tags { - v := m[k] - //TODO rename conflicts - if v.conflicts { - delete(m, k) - continue - } - - name := k.String() - switch export { - case doNotExport: - name = unCapitalize(name) - case doNotChange: - // nop - case exportCapitalize: - name = capitalize(name) - case exportPrefix: - name = p.task.exportStructs + name - } - v.name = p.scope.take(cc.String(name)) - } - for _, k := range tags { - v := m[k] - if v != nil { - v.gotyp = p.structType(nil, v.ctyp) - } - } - p.structs = m - return nil -} - -func (p *project) captureStructTags(n cc.Node, t cc.Type, m map[cc.StringID]*taggedStruct, tags *[]cc.StringID) { - if t == nil { - return - } - - t = t.Alias() - for t.Kind() == cc.Ptr { - t = t.Alias().Elem().Alias() - } - if t.Kind() == cc.Invalid || t.IsIncomplete() { - return - } - - switch t.Kind() { - case cc.Struct, cc.Union: - tag := t.Tag() - if tag == 0 { - return - } - - ex := m[tag] - if ex != nil { - ts := p.typeSignature(n, t) - exs := p.typeSignature(n, ex.ctyp) - if ts != exs { - ex.conflicts = true - } - return - } - - nf := t.NumField() - m[tag] = &taggedStruct{ctyp: t, node: n} - for idx := []int{0}; idx[0] < nf; idx[0]++ { - p.captureStructTags(n, t.FieldByIndex(idx).Type(), m, tags) - } - *tags = append(*tags, tag) - case cc.Array: - p.captureStructTags(n, t.Elem(), m, tags) - } -} - -func (p *project) typeSignature(n cc.Node, t cc.Type) (r uint64) { - p.typeSigHash.Reset() - p.typeSignature2(n, &p.typeSigHash, t) - return p.typeSigHash.Sum64() -} - -func (p *project) typeSignature2(n cc.Node, b *maphash.Hash, t cc.Type) { - t = t.Alias() - if t.IsIntegerType() { - if !t.IsSignedType() { - b.WriteByte('u') - } - fmt.Fprintf(b, "int%d", t.Size()*8) - return - } - - if t.IsArithmeticType() { - b.WriteString(t.Kind().String()) - return - } - - structOrUnion := "struct" - switch t.Kind() { - case cc.Ptr: - fmt.Fprintf(b, "*%s", t.Elem()) - case cc.Array: - if t.IsVLA() { - // trc("VLA") - p.err(n, "variable length arrays not supported: %v", t) - } - - fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) - case cc.Vector: - fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) - case cc.Union: - structOrUnion = "union" - fallthrough - case cc.Struct: - b.WriteString(structOrUnion) - nf := t.NumField() - fmt.Fprintf(b, " %d{", nf) - b.WriteByte('{') - for idx := []int{0}; idx[0] < nf; idx[0]++ { - f := t.FieldByIndex(idx) - fmt.Fprintf(b, "%s:%d:%d:%v:%d:%d:", - f.Name(), f.BitFieldOffset(), f.BitFieldWidth(), f.IsBitField(), f.Offset(), f.Padding(), - ) - p.typeSignature2(f.Declarator(), b, f.Type()) - b.WriteByte(';') - } - b.WriteByte('}') - case cc.Void: - b.WriteString("void") - case cc.Invalid: - b.WriteString("invalid") //TODO fix cc/v3 - default: - panic(todo("", p.pos(n), t, t.Kind())) - } -} - -func (p *project) structType(n cc.Node, t cc.Type) string { - switch t.Kind() { - case cc.Struct, cc.Union: - tag := t.Tag() - if tag != 0 && p.structs != nil { - s := p.structs[tag] - if s == nil { - return p.structLiteral(n, t) - } - - if s.gotyp == "" { - s.gotyp = p.structLiteral(n, t) - } - return s.gotyp - } - - return p.structLiteral(n, t) - default: - panic(todo("internal error: %v", t.Kind())) - } -} - -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() { - case cc.Struct: - info := cc.NewStructLayout(t) - // trc("%v: %q\n%s", p.pos(n), t.Tag(), info) - b.WriteString("struct {") - if info.NeedExplicitAlign { - fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) - } - var max uintptr - for _, off := range info.Offsets { - flds := info.OffsetToFields[off] - if off < max { - var a []string - var nmf cc.Field - for _, f := range flds { - if f.Name() != 0 && nmf == nil { - nmf = f - } - if !f.IsBitField() { - panic(todo("internal error %q, off %v max %v\n%s", f.Name(), off, max, info)) - } - a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) - } - fmt.Fprintf(b, "/* %s */", strings.Join(a, ", ")) - continue - } - - f := flds[0] - switch pad := info.PaddingsBefore[f]; { - case pad < 0: - continue - case pad > 0: - fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) - } - switch { - case f.IsBitField(): - max += uintptr(f.BitFieldBlockWidth()) >> 3 - var a []string - var nmf cc.Field - for _, f := range flds { - if f.Name() != 0 && nmf == nil { - nmf = f - } - if !f.IsBitField() { - panic(todo("internal error %q\n%s", f.Name(), info)) - } - a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) - } - if nmf == nil { - nmf = f - } - fmt.Fprintf(b, "%s uint%d /* %s */;", p.bitFieldName(n, nmf), f.BitFieldBlockWidth(), strings.Join(a, ", ")) - default: - ft := f.Type() - if ft.Kind() == cc.Array && ft.IsIncomplete() || ft.Size() == 0 { - break - } - - max += ft.Size() - fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) - } - } - if info.PaddingAfter != 0 { - fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), info.PaddingAfter) - } - b.WriteByte('}') - case cc.Union: - b.WriteString("struct {") - info := cc.NewStructLayout(t) - if info.NeedExplicitAlign { - fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) - } - al := uintptr(t.Align()) - sz := t.Size() - if al > sz { - panic(todo("", p.pos(n))) - } - - f := t.FieldByIndex([]int{0}) - ft := f.Type() - al0 := ft.Align() - if f.IsBitField() { - al0 = f.BitFieldBlockWidth() >> 3 - } - if al != uintptr(al0) { - fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*al) - } - fsz := ft.Size() - switch { - case f.IsBitField(): - fmt.Fprintf(b, "%s ", p.fieldName2(n, f)) - fmt.Fprintf(b, "uint%d;", f.BitFieldBlockWidth()) - fsz = uintptr(f.BitFieldBlockWidth()) >> 3 - default: - fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) - } - if pad := sz - fsz; pad != 0 { - fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) - } - b.WriteByte('}') - default: - panic(todo("internal error: %v", t.Kind())) - } - r := b.String() - if p.task.verifyStructs { - if _, ok := p.verifyStructs[r]; !ok { - p.verifyStructs[r] = t - } - } - return r -} - -func (p *project) align(nd cc.Node, t cc.Type) int { - switch n := t.Align(); { - case n <= 1: - return 1 - case n <= 2: - return 2 - case n <= 4: - return 4 - case n <= 8: - return 8 - default: - if !p.task.ignoreUnsupportedAligment { - p.err(nd, "unsupported alignment of type %s: %v", t, n) - } - return 8 - } -} - -func (p *project) bitFieldName(n cc.Node, f cc.Field) string { - if id := f.Name(); id != 0 { - return p.fieldName(n, id) - } - - return fmt.Sprintf("__%d", f.Offset()) -} - -func (p *project) fieldName2(n cc.Node, f cc.Field) string { - if f.Name() != 0 { - return p.fieldName(n, f.Name()) - } - - return p.fieldName(n, cc.String(fmt.Sprintf("__%d", f.Offset()))) -} - -func (p *project) fieldName(n cc.Node, id cc.StringID) string { - if id == 0 { - panic(todo("", p.pos(n))) - } - - if !p.task.exportFieldsValid { - s := id.String() - if p.task.defaultUnExport { - s = unCapitalize(s) - } - - if !reservedNames[s] { - return s - } - - return "__" + s - } - - if s := p.task.exportFields; s != "" { - return s + id.String() - } - - return capitalize(id.String()) -} - -func (p *project) dtyp(d *cc.Declarator) (r string) { - t := d.Type() - if t.IsIncomplete() { - if t.Kind() == cc.Array && d.IsParameter { - return "uintptr" - } - - panic(todo("")) - } - - return p.typ(d, t) -} - -func (p *project) typ(nd cc.Node, t cc.Type) (r string) { - if t.IsIncomplete() { - panic(todo("", p.pos(nd), t)) - } - - if t.IsAliasType() { - if tld := p.tlds[t.AliasDeclarator()]; tld != nil { - return tld.name - } - } - - b := bytesBufferPool.Get().(*bytes.Buffer) - defer func() { b.Reset(); bytesBufferPool.Put(b) }() - if t.IsIntegerType() { - switch t.Kind() { - case cc.Int128: - fmt.Fprintf(b, "%sInt128", p.task.crt) - return b.String() - case cc.UInt128: - fmt.Fprintf(b, "%sUint128", p.task.crt) - return b.String() - } - - if !t.IsSignedType() { - b.WriteByte('u') - } - if t.Size() > 8 { - p.err(nd, "unsupported C type: %v", t) - } - fmt.Fprintf(b, "int%d", 8*t.Size()) - return b.String() - } - - switch t.Kind() { - case cc.Ptr, cc.Function: - return "uintptr" - case cc.Double: - return "float64" - case cc.Float: - return "float32" - case cc.Array: - n := t.Len() - switch { - case t.IsVLA(): - fmt.Fprintf(b, "uintptr") - default: - fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) - } - return b.String() - case cc.Vector: - n := t.Len() - fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) - return b.String() - case cc.Struct, cc.Union: - if tag := t.Tag(); tag != 0 { - if s := p.structs[tag]; s != nil { - if s.name == "" { - panic(todo("internal error %q", tag)) - } - - return s.name - } - } - - return p.structType(nd, t) - } - - panic(todo("", p.pos(nd), t.Kind(), t)) -} - -func isScalarKind(k cc.Kind) bool { - switch k { - case - cc.Char, cc.SChar, cc.UChar, - cc.Short, cc.UShort, - cc.Int, cc.UInt, - cc.Long, cc.ULong, - cc.LongLong, cc.ULongLong, - cc.Float, cc.Double, - cc.Ptr: - - return true - } - - return false -} - -func (p *project) layoutTLDs() error { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("processing file scope declarations ... ") - t0 = time.Now() - defer func() { fmt.Println(time.Since(t0)) }() - } - - exportExtern, exportTypedef := doNotChange, doNotChange - if p.task.exportExternsValid { - switch { - case p.task.exportExterns != "": - exportExtern = exportPrefix - default: - exportExtern = exportCapitalize - } - } else if p.task.defaultUnExport { - exportExtern = doNotExport - } - - if p.task.exportTypedefsValid { - switch { - case p.task.exportTypedefs != "": - exportTypedef = exportPrefix - default: - exportTypedef = exportCapitalize - } - } else if p.task.defaultUnExport { - exportTypedef = doNotExport - } - - var a []*cc.Declarator - if p.task.pkgName == "" || p.task.pkgName == "main" { - out: - for _, ast := range p.task.asts { - if a := ast.Scope[idMain]; len(a) != 0 { - switch x := a[0].(type) { - case *cc.Declarator: - if x.Linkage == cc.External { - p.isMain = true - p.scope.take(idMain) - break out - } - } - } - } - } - sharedFns := map[*cc.FunctionDefinition]struct{}{} - for _, ast := range p.task.asts { - a = a[:0] - for d := range ast.TLD { - if d.IsFunctionPrototype() { - continue - } - - // https://gcc.gnu.org/onlinedocs/gcc/Inline.html - // - // If you specify both inline and extern in the function definition, then the - // definition is used only for inlining. In no case is the function compiled on - // its own, not even if you refer to its address explicitly. Such an address - // becomes an external reference, as if you had only declared the function, and - // had not defined it. - // - // This combination of inline and extern has almost the effect of a macro. The - // way to use it is to put a function definition in a header file with these - // keywords, and put another copy of the definition (lacking inline and extern) - // in a library file. The definition in the header file causes most calls to - // the function to be inlined. If any uses of the function remain, they refer - // to the single copy in the library. - if d.IsExtern() && d.Type().Inline() { - continue - } - - if fn := d.FunctionDefinition(); fn != nil { - if _, ok := p.sharedFns[fn]; ok { - if _, ok := sharedFns[fn]; ok { - continue - } - - sharedFns[fn] = struct{}{} - } - } - - a = append(a, d) - p.wanted[d] = struct{}{} - } - sort.Slice(a, func(i, j int) bool { - return a[i].NameTok().Seq() < a[j].NameTok().Seq() - }) - for _, d := range a { - switch d.Type().Kind() { - case cc.Struct, cc.Union: - p.checkAttributes(d.Type()) - } - nm := d.Name() - name := nm.String() - - switch d.Linkage { - case cc.External: - if ex := p.externs[nm]; ex != nil { - if _, ok := p.task.hide[name]; ok { - break - } - - if d.Type().Kind() != cc.Function { - break - } - - p.err(d, "redeclared: %s", d.Name()) - break - } - - isMain := p.isMain && nm == idMain - switch exportExtern { - case doNotExport: - name = unCapitalize(name) - case doNotChange: - // nop - case exportCapitalize: - name = capitalize(name) - case exportPrefix: - name = p.task.exportExterns + name - } - name = p.scope.take(cc.String(name)) - if isMain { - p.mainName = name - d.Read++ - } - tld := &tld{name: name} - p.externs[nm] = tld - for _, v := range ast.Scope[nm] { - if d, ok := v.(*cc.Declarator); ok { - p.tlds[d] = tld - } - } - if !isMain { - p.capi = append(p.capi, d.Name().String()) - } - case cc.Internal: - if token.IsExported(name) && !p.isMain && p.task.exportExternsValid { - name = "s" + name - } - tld := &tld{name: p.scope.take(cc.String(name))} - for _, v := range ast.Scope[nm] { - if d, ok := v.(*cc.Declarator); ok { - p.tlds[d] = tld - } - } - case cc.None: - if d.IsTypedefName { - if d.Type().IsIncomplete() { - break - } - - if exportTypedef == doNotChange && strings.HasPrefix(name, "__") { - break - } - - ex, ok := p.typedefTypes[d.Name()] - if ok { - sig := p.typeSignature(d, d.Type()) - if ex.sig == sig { - tld := ex.tld - for _, v := range ast.Scope[nm] { - if d, ok := v.(*cc.Declarator); ok { - p.tlds[d] = tld - } - } - break - } - } - - switch exportTypedef { - case doNotExport: - name = unCapitalize(name) - case doNotChange: - // nop - case exportCapitalize: - name = capitalize(name) - case exportPrefix: - name = p.task.exportTypedefs + name - } - - tld := &tld{name: p.scope.take(cc.String(name))} - p.typedefTypes[d.Name()] = &typedef{p.typeSignature(d, d.Type()), tld} - for _, v := range ast.Scope[nm] { - if d, ok := v.(*cc.Declarator); ok { - p.tlds[d] = tld - } - } - } - default: - panic(todo("", p.pos(d), nm, d.Linkage)) - } - } - } - for _, ast := range p.task.asts { - for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { - decl := list.ExternalDeclaration - switch decl.Case { - case cc.ExternalDeclarationFuncDef: // FunctionDefinition - // ok - default: - continue - } - - cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { - switch x := n.(type) { - case *cc.Declarator: - if x.IsFunctionPrototype() { - nm := x.Name() - if extern := p.externs[nm]; extern != nil { - break - } - - tld := &tld{name: nm.String()} - for _, nd := range ast.Scope[nm] { - if d, ok := nd.(*cc.Declarator); ok { - p.tlds[d] = tld - } - } - } - - } - return true - }) - } - } - return nil -} - -func (p *project) checkAttributes(t cc.Type) (r bool) { - r = true - for _, v := range t.Attributes() { - cc.Inspect(v, func(n cc.Node, entry bool) bool { - if !entry { - return true - } - - switch x := n.(type) { - case *cc.AttributeValue: - if x.Token.Value != idAligned { - break - } - - //TODO switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { - //TODO default: - //TODO panic(todo("%T(%v)", v, v)) - //TODO } - } - return true - }) - } - switch t.Kind() { - case cc.Struct, cc.Union: - for i := []int{0}; i[0] < t.NumField(); i[0]++ { - f := t.FieldByIndex(i) - if !p.checkAttributes(f.Type()) { - return false - } - - sd := f.Declarator() - if sd == nil { - continue - } - - cc.Inspect(sd.StructDeclaration().SpecifierQualifierList, func(n cc.Node, entry bool) bool { - if !entry { - return true - } - - switch x := n.(type) { - case *cc.AttributeValue: - if x.Token.Value == idPacked { - p.err(sd, "unsupported attribute: packed") - r = false - return false - } - - if x.Token.Value != idAligned { - break - } - - switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { - case cc.Int64Value: - if int(v) != t.Align() { - p.err(sd, "unsupported attribute: alignment") - r = false - return false - } - default: - panic(todo("%T(%v)", v, v)) - } - } - return true - }) - if !r { - return false - } - } - } - return r -} - -func unCapitalize(s string) string { - if strings.HasPrefix(s, "_") { - return s - } - a := []rune(s) - return strings.ToLower(string(a[0])) + string(a[1:]) -} - -func capitalize(s string) string { - if strings.HasPrefix(s, "_") { - s = "X" + s - } - a := []rune(s) - return strings.ToUpper(string(a[0])) + string(a[1:]) -} - -func (p *project) main() error { - targs := append([]string(nil), p.task.args...) - for i, v := range targs { - if v == "" { - targs[i] = `""` - } - } - p.o(`// Code generated by '%s %s', DO NOT EDIT. - -package %s - -`, - filepath.Base(p.task.args[0]), - strings.Join(targs[1:], " "), - p.task.pkgName, - ) - if len(p.defineLines) != 0 { - p.w("\nconst (") - p.w("%s", strings.Join(p.defineLines, "\n")) - p.w("\n)\n\n") - } - var a []*enumSpec - for _, es := range p.enumSpecs { - if es.spec.LexicalScope().Parent() == nil && !es.emitted { - a = append(a, es) - } - } - sort.Slice(a, func(i, j int) bool { - return a[i].decl.Position().String() < a[j].decl.Position().String() - }) - for _, es := range a { - es.emit(p) - } - for i, v := range p.task.asts { - var t0 time.Time - if p.task.traceTranslationUnits { - fmt.Printf("Go back end %v/%v: %s ... ", i+1, len(p.task.asts), filepath.Base(p.task.sources[i].Name)) - t0 = time.Now() - } - p.oneAST(v) - if p.task.traceTranslationUnits { - fmt.Println(time.Since(t0)) - } - p.task.asts[i] = nil - memGuard(i, p.task.isScripted) - } - sort.Slice(p.task.imported, func(i, j int) bool { return p.task.imported[i].path < p.task.imported[j].path }) - p.o(`import ( - "math" - "reflect" - "sync/atomic" - "unsafe" -`) - if len(p.verifyStructs) != 0 { - p.o("\t\"fmt\"\n") - } - first := true - libc := false - for _, v := range p.task.imported { - if v.used { - if v.path == p.task.crtImportPath { - libc = true - } - if first { - p.o("\n") - first = false - } - p.o("\t%q\n", v.path) - } - } - if p.task.crtImportPath != "" { - if !libc { - p.o("\t%q\n", p.task.crtImportPath) - } - p.o("\t%q\n", p.task.crtImportPath+"/sys/types") - } - p.o(`) - -var _ = math.Pi -var _ reflect.Kind -var _ atomic.Value -var _ unsafe.Pointer -`) - if p.task.crtImportPath != "" { - if libc { - p.o("var _ *libc.TLS\n") - } - p.o("var _ types.Size_t\n") - } - if p.isMain { - p.o(` -func main() { %sStart(%s) }`, p.task.crt, p.mainName) - } - p.flushStructs() - p.initPatches() - p.flushTS() - if !p.task.noCapi { - p.flushCAPI() - } - p.doVerifyStructs() - if err := p.Err(); err != nil { - return err - } - - if _, err := p.buf.WriteTo(p.task.out); err != nil { - return err - } - - return p.Err() -} - -func (p *project) doVerifyStructs() { - if len(p.verifyStructs) == 0 { - return - } - - var a []string - for k := range p.verifyStructs { - a = append(a, k) - } - sort.Strings(a) - p.w("\n\nfunc init() {") - n := 0 - for _, k := range a { - t := p.verifyStructs[k] - p.w("\nvar v%d %s", n, k) - p.w("\nif g, e := unsafe.Sizeof(v%d), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union size, got %%v, expected %%v`, g, e))}", n, t.Size()) - nf := t.NumField() - for idx := []int{0}; idx[0] < nf; idx[0]++ { - f := t.FieldByIndex(idx) - if f.IsFlexible() { - break - } - - if f.IsBitField() || f.Type().Size() == 0 { - continue - } - - nm := p.fieldName2(f.Declarator(), f) - switch { - case t.Kind() == cc.Union: - if f.Offset() != 0 { - panic(todo("")) - } - - if idx[0] != 0 { - break - } - - fallthrough - default: - p.w("\nif g, e := unsafe.Offsetof(v%d.%s), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union field offset, got %%v, expected %%v`, g, e))}", n, nm, f.Offset()) - p.w("\nif g, e := unsafe.Sizeof(v%d.%s), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union field size, got %%v, expected %%v`, g, e))}", n, nm, f.Type().Size()) - } - } - n++ - } - p.w("\n}\n") -} - -func (p *project) flushCAPI() { - if p.isMain { - return - } - - b := bytes.NewBuffer(nil) - fmt.Fprintf(b, `// Code generated by '%s %s', DO NOT EDIT. - -package %s - -`, - filepath.Base(p.task.args[0]), - strings.Join(p.task.args[1:], " "), - p.task.pkgName, - ) - fmt.Fprintf(b, "\n\nvar CAPI = map[string]struct{}{") - sort.Strings(p.capi) - for _, nm := range p.capi { - fmt.Fprintf(b, "\n%q: {},", nm) - } - fmt.Fprintf(b, "\n}\n") - if err := ioutil.WriteFile(p.task.capif, b.Bytes(), 0644); err != nil { - p.err(nil, "%v", err) - return - } - - if out, err := exec.Command("gofmt", "-r", "(x) -> x", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { - p.err(nil, "%s: %v", out, err) - } - - if out, err := exec.Command("gofmt", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { - p.err(nil, "%s: %v", out, err) - } -} - -func (p *project) initPatches() { - var tlds []*tld - for _, tld := range p.tlds { - if len(tld.patches) != 0 { - tlds = append(tlds, tld) - } - } - if len(tlds) == 0 { - return - } - - sort.Slice(tlds, func(i, j int) bool { return tlds[i].name < tlds[j].name }) - p.w("\n\nfunc init() {") - for _, tld := range tlds { - for _, patch := range tld.patches { - var fld string - if patch.fld != nil { - fld = fmt.Sprintf("/* .%s */", patch.fld.Name()) - } - init := patch.init - expr := init.AssignmentExpression - d := expr.Declarator() - switch { - case d != nil && d.Type().Kind() == cc.Function: - p.w("\n*(*") - p.functionSignature(d, nil, d.Type(), "") - p.w(")(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", tld.name, init.Offset, fld) - p.declarator(init, nil, d, d.Type(), exprFunc, 0) - default: - p.w("\n*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", p.typ(init, patch.t), tld.name, init.Offset, fld) - p.assignmentExpression(nil, expr, patch.t, exprValue, 0) - } - p.w("// %s:", p.pos(init)) - } - } - p.w("\n}\n") -} - -func (p *project) Err() error { - if len(p.errors) == 0 { - return nil - } - - var lpos token.Position - w := 0 - for _, v := range p.errors { - if lpos.Filename != "" { - if v.Pos.Filename == lpos.Filename && v.Pos.Line == lpos.Line && !strings.HasPrefix(v.Msg, tooManyErrors) { - continue - } - } - - p.errors[w] = v - w++ - lpos = v.Pos - } - p.errors = p.errors[:w] - sort.Slice(p.errors, func(i, j int) bool { - a := p.errors[i] - if a.Msg == tooManyErrors { - return false - } - - b := p.errors[j] - if b.Msg == tooManyErrors { - return true - } - - if !a.Pos.IsValid() && b.Pos.IsValid() { - return true - } - - if a.Pos.IsValid() && !b.Pos.IsValid() { - return false - } - - if a.Pos.Filename < b.Pos.Filename { - return true - } - - if a.Pos.Filename > b.Pos.Filename { - return false - } - - if a.Pos.Line < b.Pos.Line { - return true - } - - if a.Pos.Line > b.Pos.Line { - return false - } - - return a.Pos.Column < b.Pos.Column - }) - a := make([]string, 0, len(p.errors)) - for _, v := range p.errors { - a = append(a, v.Error()) - } - return fmt.Errorf("%s", strings.Join(a, "\n")) -} - -func (p *project) flushTS() { - b := p.ts.Bytes() - if len(b) != 0 { - p.w("\n\n") - //TODO add cmd line option for this - //TODO s := strings.TrimSpace(hex.Dump(b)) - //TODO a := strings.Split(s, "\n") - //TODO p.w("// %s\n", strings.Join(a, "\n// ")) - p.w("var %s = %q\n", p.tsName, b) - p.w("var %s = (*reflect.StringHeader)(unsafe.Pointer(&%s)).Data\n", p.tsNameP, p.tsName) - } - if len(p.tsW) != 0 { - p.w("var %s = [...]%s{", p.tsWName, p.typ(nil, p.ast.WideCharType)) - for _, v := range p.tsW { - p.w("%d, ", v) - } - p.w("}\n") - p.w("var %s = uintptr(unsafe.Pointer(&%s[0]))\n", p.tsWNameP, p.tsWName) - } -} - -func (p *project) flushStructs() { - var a []*taggedStruct - for _, v := range p.structs { - if !v.emitted { - a = append(a, v) - } - } - sort.Slice(a, func(i, j int) bool { return a[i].name < a[j].name }) - for _, v := range a { - v.emit(p, nil) - } -} - -func (p *project) oneAST(ast *cc.AST) { - p.ast = ast - for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { - p.externalDeclaration(list.ExternalDeclaration) - } - p.w("%s", tidyCommentString(ast.TrailingSeperator.String())) -} - -func (p *project) externalDeclaration(n *cc.ExternalDeclaration) { - switch n.Case { - case cc.ExternalDeclarationFuncDef: // FunctionDefinition - p.functionDefinition(n.FunctionDefinition) - case cc.ExternalDeclarationDecl: // Declaration - p.declaration(nil, n.Declaration, false) - case cc.ExternalDeclarationAsm: // AsmFunctionDefinition - // nop - case cc.ExternalDeclarationAsmStmt: // AsmStatement - panic(todo("", p.pos(n))) - case cc.ExternalDeclarationEmpty: // ';' - // nop - case cc.ExternalDeclarationPragma: // PragmaSTDC - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) declaration(f *function, n *cc.Declaration, topDecl bool) { - cc.Inspect(n.DeclarationSpecifiers, func(m cc.Node, entry bool) bool { - switch x := m.(type) { - case *cc.EnumSpecifier: - if f == nil { - p.enumSpecs[x].emit(p) - } - case *cc.StructOrUnionSpecifier: - if tag := x.Token.Value; tag != 0 { - switch { - case f == nil: - p.structs[tag].emit(p, n.DeclarationSpecifiers) - default: - p.localTaggedStructs = append(p.localTaggedStructs, func() { - p.structs[tag].emit(p, n.DeclarationSpecifiers) - }) - } - } - } - return true - }) - - if n.InitDeclaratorList == nil { - return - } - - // DeclarationSpecifiers InitDeclaratorList ';' - sep := tidyComment("\n", n) //TODO repeats - for list := n.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { - p.initDeclarator(f, list.InitDeclarator, sep, topDecl) - sep = "\n" - } -} - -func (p *project) initDeclarator(f *function, n *cc.InitDeclarator, sep string, topDecl bool) { - if f == nil { - p.tld(f, n, sep, false) - return - } - - d := n.Declarator - if d.IsExtern() || d.IsTypedefName { - return - } - - if tld := p.tlds[d]; tld != nil && !topDecl { // static local - if !p.pass1 { - p.staticQueue = append(p.staticQueue, n) - } - return - } - - local := f.locals[d] - if local == nil { // Dead declaration. - return - } - - block := f.block - t := d.Type() - vla := t.Kind() == cc.Array && t.IsVLA() - if vla && p.pass1 { - f.vlas[d] = struct{}{} - return - } - - switch n.Case { - case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList - if block.noDecl || block.topDecl && !topDecl { - return - } - - switch { - case vla: - p.initDeclaratorDeclVLA(f, n, sep) - default: - p.initDeclaratorDecl(f, n, sep) - } - case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer - if vla { - panic(todo("")) - } - - if f.block.topDecl { - switch { - case topDecl: - p.initDeclaratorDecl(f, n, sep) - if local.forceRead && !local.isPinned { - p.w("_ = %s;", local.name) - } - default: - sv := f.condInitPrefix - f.condInitPrefix = func() { - p.declarator(d, f, d, d.Type(), exprLValue, 0) - p.w(" = ") - } - switch { - case p.isConditionalInitializer(n.Initializer): - p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) - default: - f.condInitPrefix() - p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) - } - f.condInitPrefix = sv - p.w(";") - } - return - } - - p.w("%s", sep) - switch { - case local.isPinned: - sv := f.condInitPrefix - f.condInitPrefix = func() { - //TODO- p.declarator(d, f, d, d.Type(), exprLValue, 0) - //TODO- p.w(" = ") - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */)) = ", p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - } - switch { - case p.isConditionalInitializer(n.Initializer): - p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) - default: - f.condInitPrefix() - p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) - p.w(";") - } - f.condInitPrefix = sv - p.w(";") - default: - var semi string - switch { - case block.noDecl: - semi = "" - default: - p.w("var %s ", local.name) - if !isAggregateTypeOrUnion(d.Type()) { - p.w("%s ", p.typ(n, d.Type())) - } - semi = ";" - } - switch { - case p.isConditionalInitializer(n.Initializer): - p.w("%s", semi) - sv := f.condInitPrefix - f.condInitPrefix = func() { p.w("%s = ", local.name) } - p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) - f.condInitPrefix = sv - default: - if block.noDecl { - p.w("%s", local.name) - } - p.w(" = ") - p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) - } - p.w(";") - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - if !block.noDecl && local.forceRead && !local.isPinned { - p.w("_ = %s;", local.name) - } -} - -func (p *project) isConditionalInitializer(n *cc.Initializer) bool { - return n.Case == cc.InitializerExpr && p.isConditionalAssignmentExpr(n.AssignmentExpression) -} - -func (p *project) isConditionalAssignmentExpr(n *cc.AssignmentExpression) bool { - return n.Case == cc.AssignmentExpressionCond && - n.ConditionalExpression.Case == cc.ConditionalExpressionCond -} - -func (p *project) initDeclaratorDeclVLA(f *function, n *cc.InitDeclarator, sep string) { - d := n.Declarator - local := f.locals[d] - if strings.TrimSpace(sep) == "" { - sep = "\n" - } - if local.isPinned { - panic(todo("")) - p.w("%s// var %s %s at %s%s, %d\n", sep, local.name, p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), d.Type().Size()) - return - } - - p.w("%s%s = %sXrealloc(%s, %s, types.Size_t(", sep, local.name, p.task.crt, f.tlsName, local.name) - e := d.Type().LenExpr() - p.assignmentExpression(f, e, e.Operand.Type(), exprValue, 0) - if sz := d.Type().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - p.w("));") -} - -func (p *project) initDeclaratorDecl(f *function, n *cc.InitDeclarator, sep string) { - d := n.Declarator - local := f.locals[d] - if strings.TrimSpace(sep) == "" { - sep = "\n" - } - if local.isPinned { - p.w("%s// var %s %s at %s%s, %d\n", sep, local.name, p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), d.Type().Size()) - return - } - - p.w("%svar %s %s;", sep, local.name, p.typ(n, d.Type())) -} - -func (p *project) declarator(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprLValue: - p.declaratorLValue(n, f, d, t, mode, flags) - case exprFunc: - p.declaratorFunc(n, f, d, t, mode, flags) - case exprValue: - p.declaratorValue(n, f, d, t, mode, flags) - case exprAddrOf: - p.declaratorAddrOf(n, f, d, t, flags) - case exprSelect: - p.declaratorSelect(n, f, d) - case exprDecay: - p.declaratorDecay(n, f, d, t, mode, flags) - default: - panic(todo("", mode)) - } -} - -func (p *project) declaratorDecay(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if d.Type().Kind() != cc.Array { - panic(todo("", n.Position(), p.pos(d))) - } - - if f != nil { - if local := f.locals[d]; local != nil { - if d.Type().IsVLA() { - switch { - case local.isPinned: - panic(todo("")) - default: - p.w("%s", local.name) - return - } - } - - if d.IsParameter { - p.w("%s", local.name) - return - } - - if p.pass1 { - if !d.Type().IsVLA() { - f.pin(n, d) - } - return - } - - if !local.isPinned { - p.err(n, "%v: %v: missed pinning", n.Position(), d.Position(), d.Name()) - } - p.w("(%s%s)/* &%s[0] */", f.bpName, nonZeroUintptr(local.off), local.name) - return - } - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - case *imported: - x.used = true - p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) - default: - panic(todo("%v: %v: %q %T", n.Position(), p.pos(d), d.Name(), x)) - } -} - -func (p *project) declaratorValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - switch k := p.declaratorKind(d); k { - case opNormal: - p.declaratorValueNormal(n, f, d, t, mode, flags) - case opArray: - p.declaratorValueArray(n, f, d, t, mode, flags) - case opFunction: - p.declarator(n, f, d, t, exprAddrOf, flags) - case opUnion: - p.declaratorValueUnion(n, f, d, t, mode, flags) - case opArrayParameter: - p.declaratorValueArrayParameter(n, f, d, t, mode, flags) - default: - panic(todo("", d.Position(), k)) - } -} - -func (p *project) declaratorValueArrayParameter(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if d.Type().IsScalarType() { - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - } - local := f.locals[d] - if local.isPinned { - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(n, paramTypeDecay(d)), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) -} - -func (p *project) declaratorValueUnion(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if d.Type().IsScalarType() { - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - } - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - } - - p.declaratorDefault(n, d) -} - -func (p *project) isVolatileOrAtomic(d *cc.Declarator) bool { - if d.Type().IsVolatile() || d.Type().IsAtomic() { - return true - } - - _, ok := p.task.volatiles[d.Name()] - return ok -} - -func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { - if x := p.tlds[d]; x != nil && d.IsStatic() { - if p.isVolatileOrAtomic(d) { - p.atomicLoadNamedAddr(n, d.Type(), x.name) - return - } - - p.w("%s", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - if p.isVolatileOrAtomic(d) { - p.atomicLoadNamedAddr(n, d.Type(), x.name) - return - } - - p.w("%s", x.name) - case *imported: - x.used = true - if p.isVolatileOrAtomic(d) { - p.atomicLoadNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", x.qualifier, d.Name())) - return - } - - p.w("%sX%s", x.qualifier, d.Name()) - default: - if d.IsExtern() { - switch d.Name() { - case idEnviron: - if d.Type().String() == "pointer to pointer to char" { - p.w("%sEnviron()", p.task.crt) - return - } - } - } - - if d.Linkage == cc.External && p.task.nostdlib { - p.w("X%s", d.Name()) - return - } - - id := fmt.Sprintf("__builtin_%s", d.Name()) - switch x := p.symtab[id].(type) { - case *imported: - x.used = true - p.w("%sX%s", x.qualifier, d.Name()) - 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()) - } -} - -func (p *project) declaratorValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if t.IsIntegerType() { - defer p.w("%s", p.convertType(n, nil, t, flags)) - } - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("(%s%s)/* %s */", f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if d.Type().IsScalarType() { - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - } - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - 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 - } - - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { - p.atomicLoadNamedAddr(n, d.Type(), local.name) - return - } - - p.w("%s", local.name) - return - } - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - switch k := p.declaratorKind(d); k { - case opFunction: - p.declaratorFuncFunc(n, f, d, t, exprValue, flags) - case opNormal: - p.declaratorFuncNormal(n, f, d, t, exprValue, flags) - default: - panic(todo("", d.Position(), k)) - } -} - -func (p *project) declaratorFuncNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - u := d.Type() - if u.Kind() == cc.Ptr { - u = u.Elem() - } - switch u.Kind() { - case cc.Function: - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("(*(*") - p.functionSignature(n, f, u, "") - p.w(")(unsafe.Pointer(%s%s)))", f.bpName, nonZeroUintptr(local.off)) - return - } - - if d.IsParameter { - p.w("(*(*") - p.functionSignature(n, f, u, "") - p.w(")(unsafe.Pointer(&%s)))", local.name) - return - } - - panic(todo("", p.pos(d))) - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("(*(*") - p.functionSignature(n, f, u, "") - p.w(")(unsafe.Pointer(&%s)))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("(*(*") - p.functionSignature(n, f, u, "") - p.w(")(unsafe.Pointer(&%s)))", x.name) - case *imported: - x.used = true - p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) - default: - panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) - } - default: - panic(todo("", p.pos(d), u)) - } -} - -func (p *project) declaratorFuncFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - switch d.Type().Kind() { - case cc.Function: - // ok - default: - panic(todo("", p.pos(d), d.Type(), d.Type().Kind())) - } - - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - panic(todo("")) - } - - p.w(" %s", local.name) - return - } - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorLValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - switch k := p.declaratorKind(d); k { - case opNormal, opArrayParameter, opUnion: - p.declaratorLValueNormal(n, f, d, t, mode, flags) - case opArray: - p.declaratorLValueArray(n, f, d, t, mode, flags) - default: - panic(todo("", d.Position(), k)) - } -} - -func (p *project) declaratorLValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorLValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { - if p.isVolatileOrAtomic(d) { - panic(todo("", n.Position(), d.Position())) - } - - if d.Type().IsScalarType() { - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - } - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.dtyp(d), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - } - - p.declaratorLValueDefault(n, d) -} - -func (p *project) declaratorLValueDefault(n cc.Node, d *cc.Declarator) { - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("%s", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("%s", x.name) - case *imported: - x.used = true - p.w("%sX%s", x.qualifier, d.Name()) - default: - if d.IsExtern() { - switch d.Name() { - case idEnviron: - if d.Type().String() == "pointer to pointer to char" { - p.w("*(*uintptr)(unsafe.Pointer(%sEnvironP()))", p.task.crt) - return - } - } - } - - panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) - } -} - -func (p *project) declaratorKind(d *cc.Declarator) opKind { - switch { - case p.isArrayParameterDeclarator(d): - return opArrayParameter - case !p.pass1 && p.isArrayDeclarator(d): - return opArray - case d.Type().Kind() == cc.Function && !d.IsParameter: - return opFunction - case d.Type().Kind() == cc.Union: - return opUnion - default: - return opNormal - } -} - -func (p *project) declaratorSelect(n cc.Node, f *function, d *cc.Declarator) { - switch k := p.declaratorKind(d); k { - case opNormal: - p.declaratorSelectNormal(n, f, d) - case opArray: - p.declaratorSelectArray(n, f, d) - default: - panic(todo("", d.Position(), k)) - } -} - -func (p *project) declaratorSelectArray(n cc.Node, f *function, d *cc.Declarator) { - if local := f.locals[d]; local != nil { - if local.isPinned { - panic(todo("", p.pos(n))) - //TODO type error - p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorSelectNormal(n cc.Node, f *function, d *cc.Declarator) { - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - p.w("%s", local.name) - return - } - - p.declaratorDefault(n, d) -} - -func (p *project) declaratorAddrOf(n cc.Node, f *function, d *cc.Declarator, t cc.Type, flags flags) { - switch k := p.declaratorKind(d); k { - case opArray: - p.declaratorAddrOfArray(n, f, d) - case opNormal: - p.declaratorAddrOfNormal(n, f, d, flags) - case opUnion: - p.declaratorAddrOfUnion(n, f, d) - case opFunction: - p.declaratorAddrOfFunction(n, f, d) - case opArrayParameter: - p.declaratorAddrOfArrayParameter(n, f, d) - default: - panic(todo("", d.Position(), k)) - } -} - -func (p *project) declaratorAddrOfArrayParameter(n cc.Node, f *function, d *cc.Declarator) { - if p.pass1 { - f.pin(n, d) - return - } - - local := f.locals[d] - p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) -} - -func (p *project) declaratorAddrOfFunction(n cc.Node, f *function, d *cc.Declarator) { - if d.Type().Kind() != cc.Function { - panic(todo("", p.pos(n))) - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") - p.functionSignature(n, f, d.Type(), "") - p.w("}{%s}))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") - p.functionSignature(n, f, d.Type(), "") - p.w("}{%s}))", x.name) - case *imported: - x.used = true - p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") - p.functionSignature(n, f, d.Type(), "") - p.w("}{%sX%s}))", x.qualifier, d.Name()) - default: - p.err(d, "back-end: undefined: %s", d.Name()) - } -} - -func (p *project) declaratorAddrOfUnion(n cc.Node, f *function, d *cc.Declarator) { - if f != nil { - if local := f.locals[d]; local != nil { - if p.pass1 { - f.pin(n, d) - return - } - - if local.isPinned { - p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - panic(todo("", p.pos(n))) - } - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - case *imported: - x.used = true - p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) - default: - panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) - } -} - -func (p *project) declaratorAddrOfNormal(n cc.Node, f *function, d *cc.Declarator, flags flags) { - if f != nil { - if local := f.locals[d]; local != nil { - if p.pass1 && flags&fAddrOfFuncPtrOk == 0 { - f.pin(n, d) - return - } - - if local.isPinned { - p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - if flags&fAddrOfFuncPtrOk != 0 { - if dt := d.Type(); dt.Kind() == cc.Ptr { - if elem := dt.Elem(); elem.Kind() == cc.Function || elem.Kind() == cc.Ptr && elem.Elem().Kind() == cc.Function { - p.w("&%s", local.name) - return - } - } - } - - panic(todo("", p.pos(n), p.pos(d), d.Name(), d.Type(), d.IsParameter, d.AddressTaken, flags&fAddrOfFuncPtrOk != 0)) - } - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - case *imported: - x.used = true - p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) - default: - p.err(n, "undefined: %s", d.Name()) - } -} - -func (p *project) declaratorAddrOfArray(n cc.Node, f *function, d *cc.Declarator) { - if f != nil { - if local := f.locals[d]; local != nil { - if p.pass1 { - f.pin(n, d) - return - } - - if local.isPinned { - p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) - return - } - - panic(todo("", p.pos(d), d.Name(), d.Type(), d.IsParameter)) - } - } - - if x := p.tlds[d]; x != nil && d.IsStatic() { - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - return - } - - switch x := p.symtab[d.Name().String()].(type) { - case *tld: - p.w("uintptr(unsafe.Pointer(&%s))", x.name) - case *imported: - x.used = true - p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) - default: - panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) - } -} - -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: - return p.convertTypeFromInt128(n, to, flags) - case cc.UInt128: - return p.convertTypeFromUint128(n, to, flags) - } - } - - switch to.Kind() { - case cc.Int128: - return p.convertTypeToInt128(n, from, flags) - case cc.UInt128: - return p.convertTypeToUint128(n, from, flags) - } - - // trc("%v: %v -> %v\n%s", p.pos(n), from, to, debug.Stack()[:600]) //TODO- - force := flags&fForceConv != 0 - if from == nil { - p.w("%s(", p.typ(n, to)) - return ")" - } - - if from.IsScalarType() { - switch { - case force: - p.w("%s(", p.helperType2(n, from, to)) - return ")" - case from.Kind() == to.Kind(): - return "" - default: - p.w("%s(", p.typ(n, to)) - return ")" - } - } - - switch from.Kind() { - case cc.Function, cc.Struct, cc.Union, cc.Ptr, cc.Array: - if from.Kind() == to.Kind() { - return "" - } - - panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) - case cc.Double, cc.Float: - p.w("%s(", p.typ(n, to)) - return ")" - } - - panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) -} - -func (p *project) convertTypeFromInt128(n cc.Node, to cc.Type, flags flags) string { - switch k := to.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("(") - return fmt.Sprintf(").Float%d()", to.Size()*8) - case k == cc.Int128: - return "" - case k == cc.UInt128: - p.w("%sUint128FromInt128(", p.task.crt) - return ")" - case to.IsIntegerType() && to.IsSignedType(): - p.w("int%d((", to.Size()*8) - return ").Lo)" - case to.IsIntegerType() && !to.IsSignedType(): - p.w("uint%d((", to.Size()*8) - return ").Lo)" - default: - panic(todo("", n.Position(), to, to.Alias())) - } -} - -func (p *project) convertTypeFromUint128(n cc.Node, to cc.Type, flags flags) string { - switch k := to.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("(") - return fmt.Sprintf(").Float%d()", to.Size()*8) - case k == cc.Int128: - p.w("(") - return ").Int128()" - case k == cc.UInt128: - return "" - case to.IsIntegerType() && to.IsSignedType(): - p.w("int%d((", to.Size()*8) - return ").Lo)" - case to.IsIntegerType() && !to.IsSignedType(): - p.w("uint%d((", to.Size()*8) - return ").Lo)" - default: - panic(todo("", n.Position(), to, to.Alias())) - } -} - -func (p *project) convertTypeToInt128(n cc.Node, from cc.Type, flags flags) string { - switch k := from.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) - return ")" - case k == cc.Int128: - return "" - case k == cc.UInt128: - p.w("%sInt128FromUint128(", p.task.crt) - return ")" - case from.IsIntegerType() && from.IsSignedType(): - p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case from.IsIntegerType() && !from.IsSignedType(): - p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("", n.Position(), from, from.Alias())) - } -} - -func (p *project) convertTypeToUint128(n cc.Node, from cc.Type, flags flags) string { - switch k := from.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) - return ")" - case k == cc.Int128: - p.w("(") - return ").Uint128()" - case k == cc.UInt128: - return "" - case from.IsIntegerType() && from.IsSignedType(): - p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case from.IsIntegerType() && !from.IsSignedType(): - p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("", n.Position(), from, from.Alias())) - } -} - -func (p *project) convertFromInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - switch k := to.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("(") - return fmt.Sprintf(").Float%d()", to.Size()*8) - case k == cc.Int128: - return "" - case k == cc.UInt128: - p.w("(") - return ").Uint128()" - case to.IsIntegerType() && to.IsSignedType(): - p.w("%sInt%d(", p.task.crt, to.Size()*8) - return ")" - case to.IsIntegerType() && !to.IsSignedType(): - p.w("%sUint%d(", p.task.crt, to.Size()*8) - return ")" - default: - panic(todo("", n.Position(), to, to.Alias())) - } -} - -func (p *project) convertFromUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - switch k := to.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("%sUint128FromFloat%d(", p.task.crt, to.Size()*8) - return ")" - case k == cc.Int128: - p.w("(") - return ").Int128()" - case k == cc.UInt128: - return "" - case to.IsIntegerType() && to.IsSignedType(): - p.w("%sInt%d(", p.task.crt, to.Size()*8) - return ")" - case to.IsIntegerType() && !to.IsSignedType(): - p.w("%sUint%d(", p.task.crt, to.Size()*8) - return ")" - default: - panic(todo("", n.Position(), to, to.Alias())) - } -} - -func (p *project) convertToInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - from := op.Type() - switch k := from.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) - return ")" - case k == cc.Int128: - return "" - case k == cc.UInt128: - p.w("(") - return ").Int128()" - case from.IsIntegerType() && from.IsSignedType(): - p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case from.IsIntegerType() && !from.IsSignedType(): - p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("", n.Position(), from, from.Alias())) - } -} - -func (p *project) convertToUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - from := op.Type() - switch k := from.Kind(); { - case k == cc.Float, k == cc.Double: - p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) - return ")" - case k == cc.Int128: - p.w("(") - return ").Uint128()" - case k == cc.UInt128: - return "" - case from.IsIntegerType() && from.IsSignedType(): - p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case from.IsIntegerType() && !from.IsSignedType(): - p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("", n.Position(), from, from.Alias())) - } -} - -func (p *project) convertNil(n cc.Node, to cc.Type, flags flags) string { - switch to.Kind() { - case cc.Int128: - panic(todo("", p.pos(n))) - case cc.UInt128: - panic(todo("", p.pos(n))) - } - - p.w("%s(", p.typ(n, to)) - return ")" -} - -func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - if op == nil { - panic(todo("internal error")) - } - - from := op.Type() - switch from.Kind() { - case cc.Int128: - return p.convertFromInt128(n, op, to, flags) - case cc.UInt128: - return p.convertFromUint128(n, op, to, flags) - } - switch to.Kind() { - case cc.Int128: - return p.convertToInt128(n, op, to, flags) - case cc.UInt128: - return p.convertToUint128(n, op, to, flags) - } - - if flags&fForceRuntimeConv != 0 { - flags |= fForceConv - } - force := flags&fForceConv != 0 - if !force && from.IsScalarType() && from.Kind() == to.Kind() { - return "" - } - - if from.IsIntegerType() { - return p.convertInt(n, op, to, flags) - } - - if from == to { - return "" - } - - switch from.Kind() { - case cc.Ptr: - if !force && from.Kind() == to.Kind() { - return "" - } - - if to.IsIntegerType() { - p.w("%s(", p.typ(n, to)) - return ")" - } - - 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 "" - } - - trc("%p %p", from, to) - panic(todo("%q %v -> %q %v", from, from.Kind(), to, to.Kind())) - case cc.Double, cc.Float: - 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 "" - } - - switch to.Kind() { - case cc.Ptr: - return "" - } - - panic(todo("%q, %v -> %q, %v", from, from.Kind(), to.Kind())) - } - - panic(todo("%q -> %q", from, to)) -} - -func (p *project) convertInt(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { - from := op.Type() - switch from.Kind() { - case cc.Int128: - panic(todo("", p.pos(n))) - case cc.UInt128: - panic(todo("", p.pos(n))) - } - switch to.Kind() { - case cc.Int128: - panic(todo("", p.pos(n))) - case cc.UInt128: - panic(todo("", p.pos(n))) - } - - force := flags&fForceConv != 0 - value := op.Value() - if value == nil || !to.IsIntegerType() { - if to.IsScalarType() { - p.w("%s(", p.typ(n, to)) - return ")" - } - - panic(todo("", op.Type(), to)) - } - - if flags&fForceRuntimeConv != 0 { - p.w("%s(", p.helperType2(n, op.Type(), to)) - return ")" - } - - switch { - case from.IsSignedType(): - switch { - case to.IsSignedType(): - switch x := value.(type) { - case cc.Int64Value: - switch to.Size() { - case 1: - if x >= math.MinInt8 && x <= math.MaxInt8 { - switch { - case !force && from.Size() == to.Size(): - return "" - default: - p.w("int8(") - return ")" - } - } - - p.w("%sInt8FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 2: - if x >= math.MinInt16 && x <= math.MaxInt16 { - switch { - case !force && from.Size() == to.Size(): - return "" - default: - p.w("int16(") - return ")" - } - } - - p.w("%sInt16FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 4: - if x >= math.MinInt32 && x <= math.MaxInt32 { - switch { - case !force && from.Size() == to.Size(): - return "" - default: - p.w("int32(") - return ")" - } - } - - p.w("%sInt32FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 8: - switch { - case !force && from.Size() == to.Size(): - return "" - default: - p.w("int64(") - return ")" - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: // to is unsigned - switch x := value.(type) { - case cc.Int64Value: - switch to.Size() { - case 1: - if x >= 0 && x <= math.MaxUint8 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint8FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 2: - if x >= 0 && x <= math.MaxUint16 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint16FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 4: - if x >= 0 && x <= math.MaxUint32 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint32FromInt%d(", p.task.crt, from.Size()*8) - return ")" - case 8: - if x >= 0 { - p.w("uint64(") - return ")" - } - - p.w("%sUint64FromInt%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - case cc.Uint64Value: - switch to.Size() { - case 1: - if x <= math.MaxUint8 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 2: - if x <= math.MaxUint16 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 4: - if x <= math.MaxUint32 { - p.w("%s(", p.typ(n, to)) - return ")" - } - - p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 8: - p.w("uint64(") - return ")" - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - } - default: // from is unsigned - switch { - case to.IsSignedType(): - switch x := value.(type) { - case cc.Uint64Value: - switch to.Size() { - case 1: - if x <= math.MaxInt8 { - p.w("int8(") - return ")" - } - - p.w("%sInt8FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 2: - if x <= math.MaxInt16 { - p.w("int16(") - return ")" - } - - p.w("%sInt16FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 4: - if x <= math.MaxInt32 { - p.w("int32(") - return ")" - } - - p.w("%sInt32FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 8: - if x <= math.MaxInt64 { - p.w("int64(") - return ")" - } - - p.w("%sInt64FromUint%d(", p.task.crt, from.Size()*8) - return ")" - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: // to is unsigned - switch x := value.(type) { - case cc.Uint64Value: - switch to.Size() { - case 1: - if x <= math.MaxUint8 { - switch { - case !force && from.Size() == 1: - return "" - default: - p.w("uint8(") - return ")" - } - } - - p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 2: - if x <= math.MaxUint16 { - switch { - case !force && from.Size() == 2: - return "" - default: - p.w("uint16(") - return ")" - } - } - - p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 4: - if x <= math.MaxUint32 { - switch { - case !force && from.Size() == 4: - return "" - default: - p.w("uint32(") - return ")" - } - } - - p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) - return ")" - case 8: - switch { - case !force && from.Size() == 8: - return "" - default: - p.w("uint64(") - return ")" - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - default: - panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) - } - } - } -} - -func nonZeroUintptr(n uintptr) string { - if n == 0 { - return "" - } - - return fmt.Sprintf("%+d", n) -} - -func alias(attr []*cc.AttributeSpecifier) (r cc.StringID) { - for _, v := range attr { - cc.Inspect(v, func(n cc.Node, entry bool) bool { - if !entry { - return true - } - - if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idAlias { - switch y := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { - case cc.StringValue: - r = cc.StringID(y) - return false - } - } - return true - }) - if r != 0 { - return r - } - } - return 0 -} - -func (p *project) tld(f *function, n *cc.InitDeclarator, sep string, staticLocal bool) { - d := n.Declarator - if d.IsExtern() && d.Linkage == cc.External && !d.IsTypedefName { - if alias := alias(attrs(d.Type())); alias != 0 { - p.capi = append(p.capi, d.Name().String()) - p.w("\n\nvar %s%s = %s\t// %v:\n", p.task.exportExterns, d.Name(), p.externs[alias].name, p.pos(d)) - return - } - } - - if _, ok := p.wanted[d]; !ok && !staticLocal { - isFn := d.Type().Kind() == cc.Function - if isFn && p.task.header && p.task.funcSig { - if nm := d.Name().String(); !strings.HasPrefix(nm, "__") { - p.w("\n\n") - t := p.tlds[d] - if t == nil { - t = &tld{} - t.name = p.tldScope.take(d.Name()) - } - p.functionSignature2(n, nil, d.Type(), t.name) - } - } - return - } - - tld := p.tlds[d] - if tld == nil { // Dead declaration. - return - } - - t := d.Type() - if d.IsTypedefName { - p.checkAttributes(t) - if _, ok := p.typedefsEmited[tld.name]; ok { - return - } - - p.typedefsEmited[tld.name] = struct{}{} - if t.Kind() != cc.Void { - p.w("%stype %s = %s; /* %v */", sep, tld.name, p.typ(n, t), p.pos(d)) - } - return - } - - switch n.Case { - case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList - p.w("%svar %s %s\t/* %v: */", sep, tld.name, p.typ(n, t), p.pos(n)) - switch t.Kind() { - case cc.Struct, cc.Union: - p.structs[t.Tag()].emit(p, nil) - } - case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer - if d.IsStatic() && d.Read == 0 && d.Write == 1 && n.Initializer.IsConst() { // Initialized with no side effects and unused. - break - } - - p.w("%svar %s ", sep, tld.name) - if !isAggregateTypeOrUnion(d.Type()) { - p.w("%s ", p.typ(n, d.Type())) - } - p.w("= ") - p.initializer(f, n.Initializer, d.Type(), d.StorageClass, tld) - p.w("; /* %v */", p.pos(d)) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) functionDefinition(n *cc.FunctionDefinition) { - // DeclarationSpecifiers Declarator DeclarationList CompoundStatement - if p.task.header && !p.task.funcSig { - return - } - - if _, ok := p.sharedFns[n]; ok { - if _, ok := p.sharedFnsEmitted[n]; ok { - return - } - - p.sharedFnsEmitted[n] = struct{}{} - } - - d := n.Declarator - if d.IsExtern() && d.Type().Inline() { - // https://gcc.gnu.org/onlinedocs/gcc/Inline.html - // - // If you specify both inline and extern in the function definition, then the - // definition is used only for inlining. In no case is the function compiled on - // its own, not even if you refer to its address explicitly. Such an address - // becomes an external reference, as if you had only declared the function, and - // had not defined it. - // - // This combination of inline and extern has almost the effect of a macro. The - // way to use it is to put a function definition in a header file with these - // keywords, and put another copy of the definition (lacking inline and extern) - // in a library file. The definition in the header file causes most calls to - // the function to be inlined. If any uses of the function remain, they refer - // to the single copy in the library. - return - } - - name := d.Name().String() - if _, ok := p.task.hide[name]; ok { - return - } - - if p.isMain && d.Linkage == cc.External && d.Read == 0 && !d.AddressTaken && len(p.task.asts) == 1 { - return - } - - if d.Linkage == cc.Internal && d.Read == 0 && !d.AddressTaken /*TODO- && strings.HasPrefix(name, "__") */ { - return - } - - tld := p.tlds[d] - if tld == nil { - return - } - - p.fn = name - - defer func() { p.fn = "" }() - - f := newFunction(p, n) - p.pass1 = true - p.compoundStatement(f, n.CompoundStatement, "", false, false, 0) - p.pass1 = false - p.w("\n\n") - p.functionDefinitionSignature(n, f, tld) - if p.task.header && p.task.funcSig { - return - } - - p.w(" ") - comment := fmt.Sprintf("/* %v: */", p.pos(d)) - if p.task.panicStubs { - p.w("%s{ panic(%q) }", comment, tld.name) - return - } - - brace := "{" - if need := f.off; need != 0 { - scope := f.blocks[n.CompoundStatement].scope - f.bpName = scope.take(idBp) - p.w("{%s\n%s := %s.Alloc(%d)\n", comment, f.bpName, f.tlsName, need) - p.w("defer %s.Free(%d)\n", f.tlsName, need) - for _, v := range d.Type().Parameters() { - if local := f.locals[v.Declarator()]; local != nil && local.isPinned { // Pin it. - p.w("*(*%s)(unsafe.Pointer(%s%s)) = %s\n", p.typ(v.Declarator(), paramTypeDecay(v.Declarator())), f.bpName, nonZeroUintptr(local.off), local.name) - } - } - comment = "" - brace = "" - } - if len(f.vlas) != 0 { - p.w("%s%s\n", brace, comment) - var vlas []*cc.Declarator - for k := range f.vlas { - vlas = append(vlas, k) - } - sort.Slice(vlas, func(i, j int) bool { - return vlas[i].NameTok().Seq() < vlas[j].NameTok().Seq() - }) - for _, v := range vlas { - local := f.locals[v] - switch { - case local.isPinned: - panic(todo("", v.Position())) - default: - p.w("var %s uintptr // %v: %v\n", local.name, p.pos(v), v.Type()) - } - } - switch { - case len(vlas) == 1: - p.w("defer %sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[vlas[0]].name) - default: - p.w("defer func() {\n") - for _, v := range vlas { - p.w("%sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[v].name) - } - p.w("\n}()\n") - } - } - p.compoundStatement(f, n.CompoundStatement, comment, false, true, 0) - p.w(";") - p.flushLocalTaggesStructs() - p.flushStaticTLDs() -} - -func (p *project) flushLocalTaggesStructs() { - for _, v := range p.localTaggedStructs { - v() - } - p.localTaggedStructs = nil -} - -func (p *project) flushStaticTLDs() { - for _, v := range p.staticQueue { - p.tld(nil, v, "\n", true) - } - p.staticQueue = nil -} - -func (p *project) compoundStatement(f *function, n *cc.CompoundStatement, scomment string, forceNoBraces, fnBody bool, mode exprMode) { - if p.task.panicStubs { - return - } - - // '{' BlockItemList '}' - brace := (!n.IsJumpTarget() || n.Parent() == nil) && !forceNoBraces - if brace && len(f.vlas) == 0 && (n.Parent() != nil || f.off == 0) { - p.w("{%s", scomment) - } - if fnBody { - p.instrument(n) - } - sv := f.block - f.block = f.blocks[n] - if f.block.topDecl { - for _, v := range f.block.decls { - p.declaration(f, v, true) - } - } - var r *cc.JumpStatement - for list := n.BlockItemList; list != nil; list = list.BlockItemList { - m := mode - if list.BlockItemList != nil { - m = 0 - } - r = p.blockItem(f, list.BlockItem, m) - } - if n.Parent() == nil && r == nil && f.rt.Kind() != cc.Void { - p.w("\nreturn ") - p.zeroValue(n, f.rt) - } - s := tidyComment("\n", &n.Token2) - p.w("%s", s) - if brace { - if !strings.HasSuffix(s, "\n") { - p.w("\n") - } - p.w("}") - } - f.block = sv -} - -func (p *project) zeroValue(n cc.Node, t cc.Type) { - if t.IsScalarType() { - p.w("%s(0)", p.typ(n, t)) - return - } - - switch t.Kind() { - case cc.Struct, cc.Union: - p.w("%s{}", p.typ(n, t)) - default: - panic(todo("", t, t.Kind())) - } -} - -func (p *project) blockItem(f *function, n *cc.BlockItem, mode exprMode) (r *cc.JumpStatement) { - switch n.Case { - case cc.BlockItemDecl: // Declaration - p.declaration(f, n.Declaration, false) - case cc.BlockItemStmt: // Statement - r = p.statement(f, n.Statement, false, false, false, mode) - p.w(";") - if r == nil { - p.instrument(n) - } - case cc.BlockItemLabel: // LabelDeclaration - panic(todo("", p.pos(n))) - p.w(";") - case cc.BlockItemFuncDef: // DeclarationSpecifiers Declarator CompoundStatement - p.err(n, "nested functions not supported") - p.w(";") - case cc.BlockItemPragma: // PragmaSTDC - panic(todo("", p.pos(n))) - p.w(";") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - return r -} - -func (p *project) instrument(n cc.Node) { - if p.task.cover { - p.w("%sCover();", p.task.crt) - } - if p.task.coverC { - p.w("%sCoverC(%q);", p.task.crt, p.pos(n).String()+" "+p.fn) - } - if p.task.watch { - p.w("%sWatch();", p.task.crt) - } -} - -var dummyJumpStatement = &cc.JumpStatement{} - -func (p *project) statement(f *function, n *cc.Statement, forceCompoundStmtBrace, forceNoBraces, switchBlock bool, mode exprMode) (r *cc.JumpStatement) { - if forceCompoundStmtBrace { - if f.switchCtx == inSwitchFirst && p.pauseCodegen { - p.pauseCodegen = false - p.w(" {") - p.pauseCodegen = true - } - p.w(" {") - if !switchBlock { - p.instrument(n) - } - } - switch n.Case { - case cc.StatementLabeled: // LabeledStatement - r = p.labeledStatement(f, n.LabeledStatement) - case cc.StatementCompound: // CompoundStatement - if !forceCompoundStmtBrace { - p.w("%s", n.CompoundStatement.Token.Sep) - } - if f.hasJumps { - forceNoBraces = true - } - p.compoundStatement(f, n.CompoundStatement, "", forceCompoundStmtBrace || forceNoBraces, false, 0) - case cc.StatementExpr: // ExpressionStatement - if mode != 0 { - p.w("return ") - e := n.ExpressionStatement.Expression - p.expression(f, e, e.Operand.Type(), exprValue, 0) - r = dummyJumpStatement - break - } - - p.expressionStatement(f, n.ExpressionStatement) - case cc.StatementSelection: // SelectionStatement - p.selectionStatement(f, n.SelectionStatement) - case cc.StatementIteration: // IterationStatement - p.iterationStatement(f, n.IterationStatement) - case cc.StatementJump: // JumpStatement - r = p.jumpStatement(f, n.JumpStatement) - case cc.StatementAsm: // AsmStatement - // AsmStatement: - // Asm AttributeSpecifierList ';' - // Asm: - // "__asm__" AsmQualifierList '(' STRINGLITERAL AsmArgList ')' - if n.AsmStatement.Asm.Token3.Value == 0 && n.AsmStatement.Asm.AsmArgList == nil { - break - } - - p.w("panic(`%s: assembler statements not supported`)", n.Position()) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - if forceCompoundStmtBrace { - // We need to do this, to guarantee that we always close the brace is we opened it - if f.switchCtx == inSwitchFirst && p.pauseCodegen { - p.pauseCodegen = false - p.w("}") - p.pauseCodegen = true - } - p.w("}") - } - return r -} - -func (p *project) jumpStatement(f *function, n *cc.JumpStatement) (r *cc.JumpStatement) { - p.w("%s", tidyComment("\n", n)) - if _, ok := n.Context().(*cc.SelectionStatement); ok && f.ifCtx == nil { - switch f.switchCtx { - case inSwitchCase: - f.switchCtx = inSwitchSeenBreak - case inSwitchSeenBreak: - // nop but TODO - case inSwitchFlat: - // ok - default: - panic(todo("", n.Position(), f.switchCtx)) - } - } - - switch n.Case { - case cc.JumpStatementGoto: // "goto" IDENTIFIER ';' - p.w("goto %s", f.labelNames[n.Token2.Value]) - case cc.JumpStatementGotoExpr: // "goto" '*' Expression ';' - panic(todo("", p.pos(n))) - case cc.JumpStatementContinue: // "continue" ';' - switch { - case f.continueCtx != 0: - p.w("goto __%d", f.continueCtx) - default: - p.w("continue") - } - case cc.JumpStatementBreak: // "break" ';' - switch { - case f.breakCtx != 0: - p.w("goto __%d", f.breakCtx) - default: - p.w("break") - } - case cc.JumpStatementReturn: // "return" Expression ';' - r = n - switch { - case f.rt != nil && f.rt.Kind() == cc.Void: - if n.Expression != nil { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) - p.w(";") - } - p.w("return") - case f.rt != nil && f.rt.Kind() != cc.Void: - if n.Expression != nil { - p.expression(f, n.Expression, f.rt, exprCondReturn, 0) - break - } - - p.w("return ") - p.zeroValue(n, f.rt) - default: - if n.Expression != nil { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) - p.w(";") - } - p.w("return") - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - return r -} - -func (p *project) expression(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprVoid: - p.expressionVoid(f, n, t, mode, flags) - case exprValue, exprCondReturn, exprCondInit: - p.expressionValue(f, n, t, mode, flags) - case exprBool: - p.expressionBool(f, n, t, mode, flags) - case exprAddrOf: - p.expressionAddrOf(f, n, t, mode, flags) - case exprPSelect: - p.expressionPSelect(f, n, t, mode, flags) - case exprLValue: - p.expressionLValue(f, n, t, mode, flags) - case exprFunc: - p.expressionFunc(f, n, t, mode, flags) - case exprSelect: - p.expressionSelect(f, n, t, mode, flags) - case exprDecay: - p.expressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) expressionDecay(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - p.w("func() uintptr {") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) - p.w("; return ") - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionFunc(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionLValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionPSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionAddrOf(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - p.w(" func() uintptr {") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) - p.w("; return ") - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionBool(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - p.w("func() bool {") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) - p.w("; return ") - p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), mode, flags) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - if mode == exprCondReturn { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) - p.w("; return ") - p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) - return - } - - switch { - case n.AssignmentExpression.Operand.Type().Kind() == cc.Array: - p.expressionDecay(f, n, t, exprDecay, flags) - default: - defer p.w("%s", p.convertType(n, n.Operand.Type(), t, flags)) - p.w("func() %v {", p.typ(n, n.AssignmentExpression.Operand.Type())) - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) - p.w("; return ") - p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) - p.w("}()") - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) expressionVoid(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExpressionAssign: // AssignmentExpression - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - case cc.ExpressionComma: // Expression ',' AssignmentExpression - p.expression(f, n.Expression, t, mode, flags) - p.w(";") - p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) opKind(f *function, d declarator, t cc.Type) opKind { - switch { - case p.isArrayParameter(d, t): - return opArrayParameter - case !p.pass1 && p.isArray(f, d, t): - return opArray - case t.Kind() == cc.Union: - return opUnion - case t.Kind() == cc.Struct: - return opStruct - case t.IsBitFieldType(): - return opBitfield - case t.Kind() == cc.Function: - return opFunction - default: - return opNormal - } -} - -func (p *project) assignmentExpression(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprVoid: - p.assignmentExpressionVoid(f, n, t, mode, flags) - case exprValue, exprCondReturn, exprCondInit: - p.assignmentExpressionValue(f, n, t, mode, flags) - case exprAddrOf: - p.assignmentExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.assignmentExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.assignmentExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.assignmentExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.assignmentExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.assignmentExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.assignmentExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) assignmentExpressionDecay(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<= AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionFunc(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionPSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.AssignmentExpression.Operand.Type().Elem())) - p.assignmentExpression(f, n, t, exprValue, flags) - p.w("))") - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionLValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionBool(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - default: - // case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - // case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - // case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - // case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - // case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - // case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - // case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - // case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - // case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - // case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - // case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - p.w("(") - defer p.w(")") - defer p.w(" != 0 ") - p.assignmentExpression(f, n, t, exprValue, flags) - } -} - -func (p *project) assignmentExpressionAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - p.assignmentExpressionValueAddrOf(f, n, t, mode, flags) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - panic(todo("", p.pos(n))) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionValueAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - // UnaryExpression '=' AssignmentExpression - if mode == exprCondReturn { - panic(todo("", p.pos(n))) - } - - lhs := n.UnaryExpression - switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { - case opStruct, opUnion: - p.assignmentExpressionValueAssignStructAddrof(f, n, n.Operand.Type(), mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) assignmentExpressionValueAssignStructAddrof(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - // UnaryExpression '=' AssignmentExpression - lhs := n.UnaryExpression.Operand.Type() - rhs := n.AssignmentExpression.Operand.Type() - if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { - panic(todo("", p.pos(n))) - } - - if d := n.UnaryExpression.Declarator(); d != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - if !p.pass1 { - p.w("%sXmemmove(tls, ", p.task.crt) - p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) - p.w(", %d)", lhs.Size()) - return - } - } - - if !p.pass1 { - panic(todo("", p.pos(n))) - } - } - } - - p.w("%sXmemmove(tls, ", p.task.crt) - p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) - p.w(", %d)", lhs.Size()) -} - -func (p *project) assignmentExpressionValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - p.assignmentExpressionValueAssign(f, n, t, mode, flags) - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - p.assignOp(f, n, t, mode, "*", "Mul", flags) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - p.assignOp(f, n, t, mode, "/", "Div", flags) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - p.assignOp(f, n, t, mode, "%", "Rem", flags) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - p.assignOp(f, n, t, mode, "+", "Add", flags) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - p.assignOp(f, n, t, mode, "-", "Sub", flags) - case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= - p.assignOp(f, n, t, mode, "<<", "Shl", flags) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - p.assignOp(f, n, t, mode, ">>", "Shr", flags) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - p.assignOp(f, n, t, mode, "&", "And", flags) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - p.assignOp(f, n, t, mode, "^", "Xor", flags) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - p.assignOp(f, n, t, mode, "|", "Or", flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) assignmentExpressionValueAssign(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - // UnaryExpression '=' AssignmentExpression - if mode == exprCondReturn { - p.w("return ") - } - lhs := n.UnaryExpression - switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { - case opNormal: - p.assignmentExpressionValueAssignNormal(f, n, t, mode, flags) - case opBitfield: - p.assignmentExpressionValueAssignBitfield(f, n, t, mode, flags) - case opStruct, opUnion: - p.assignmentExpressionValueAssignStruct(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) assignmentExpressionValueAssignStruct(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - // UnaryExpression '=' AssignmentExpression - lhs := n.UnaryExpression.Operand.Type() - rhs := n.AssignmentExpression.Operand.Type() - if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { - panic(todo("", p.pos(n))) - } - - p.w(" func() %s { __v := ", p.typ(n, lhs)) - p.assignmentExpression(f, n.AssignmentExpression, rhs, exprValue, flags) - p.w(";") - p.unaryExpression(f, n.UnaryExpression, lhs, exprLValue, flags) - p.w(" = __v; return __v}()") -} - -func (p *project) assignmentExpressionValueAssignBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - if d := n.UnaryExpression.Declarator(); d != nil { - panic(todo("", p.pos(n))) - } - - lhs := n.UnaryExpression - lt := lhs.Operand.Type() - bf := lt.BitField() - defer p.w("%s", p.convertType(n, lt, t, flags)) - 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) - 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) { - if d := n.UnaryExpression.Declarator(); d != nil { - if !d.Type().IsScalarType() { - panic(todo("", p.pos(n))) - } - - if local := f.locals[d]; local != nil { - if local.isPinned { - defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) - p.w("%sAssignPtr%s(", p.task.crt, p.helperType(d, d.Type())) - p.w("%s%s /* %s */", f.bpName, nonZeroUintptr(local.off), local.name) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) - return - } - - defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) - p.w("%sAssign%s(&%s, ", p.task.crt, p.helperType(n, d.Type()), local.name) - p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) - return - } - } - - defer p.w(")%s", p.convertType(n, n.UnaryExpression.Operand.Type(), t, flags)) - p.w("%sAssignPtr%s(", p.task.crt, p.helperType(n, n.UnaryExpression.Operand.Type())) - p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprAddrOf, flags) - p.w(", ") - p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) -} - -func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AssignmentExpressionCond: // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression - d := n.UnaryExpression.Declarator() - lhs := n.UnaryExpression - lt := lhs.Operand.Type() - sv := f.condInitPrefix - switch k := p.opKind(f, lhs, lt); k { - case opArrayParameter: - lt = lt.Decay() - fallthrough - case opNormal, opStruct: - mode = exprValue - if p.isArrayOrPinnedArray(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type()) { - mode = exprDecay - } - switch { - case flags&fNoCondAssignment == 0 && mode == exprValue && n.UnaryExpression.Declarator() != nil && p.isConditionalAssignmentExpr(n.AssignmentExpression): - f.condInitPrefix = func() { - p.unaryExpression(f, lhs, lt, exprLValue, flags) - p.w(" = ") - } - p.assignmentExpression(f, n.AssignmentExpression, lt, exprCondInit, flags) - p.w(";") - default: - if d != nil && p.isVolatileOrAtomic(d) { - p.setVolatileDeclarator(d, f, n.AssignmentExpression, lt, mode, flags) - return - } - - p.unaryExpression(f, lhs, lt, exprLValue, flags) - p.w(" = ") - p.assignmentExpression(f, n.AssignmentExpression, lt, mode, flags) - } - case opBitfield: - bf := lt.BitField() - p.w("%sSetBitFieldPtr%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) - p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) - case opUnion: - p.unaryExpression(f, lhs, lt, exprLValue, flags) - p.w(" = ") - p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) - default: - panic(todo("", n.Position(), k)) - } - f.condInitPrefix = sv - case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression - p.assignOp(f, n, t, mode, "*", "Mul", flags) - case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression - p.assignOp(f, n, t, mode, "/", "Div", flags) - case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression - p.assignOp(f, n, t, mode, "%", "Mod", flags) - case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression - p.assignOp(f, n, t, mode, "+", "Add", flags) - case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression - p.assignOp(f, n, t, mode, "-", "Sub", flags) - case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression - p.assignShiftOp(f, n, t, mode, "<<", "Shl", flags) - case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression - p.assignShiftOp(f, n, t, mode, ">>", "Shr", flags) - case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression - p.assignOp(f, n, t, mode, "&", "And", flags) - case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression - p.assignOp(f, n, t, mode, "^", "Xor", flags) - case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression - p.assignOp(f, n, t, mode, "|", "Or", flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) setVolatileDeclarator(d *cc.Declarator, f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { - sz := d.Type().Size() - switch sz { - case 4, 8: - // ok - default: - p.err(d, "unsupported volatile declarator size: %v", sz) - return - } - - if local := f.locals[d]; local != nil { - if local.isPinned { - p.w("%sAtomicStoreP%s(%s%s /* %s */, ", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) - p.assignmentExpression(f, n, t, mode, flags) - p.w(")") - return - } - - p.atomicStoreNamedAddr(n, d.Type(), local.name, n, f, mode, flags) - return - } - - if tld := p.tlds[d]; tld != nil { - p.atomicStoreNamedAddr(n, d.Type(), tld.name, n, f, mode, flags) - return - } - - if imp := p.imports[d.Name().String()]; imp != nil { - p.atomicStoreNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", imp.qualifier, d.Name()), n, f, mode, flags) - return - } - - panic(todo("", n.Position(), d.Position(), d.Name())) -} - -func (p *project) atomicStoreNamedAddr(n cc.Node, t cc.Type, nm string, expr *cc.AssignmentExpression, f *function, mode exprMode, flags flags) { - sz := t.Size() - switch sz { - case 4, 8: - // ok - default: - p.err(n, "unsupported volatile declarator size: %v", sz) - return - } - - var ht string - switch { - case t.IsScalarType(): - ht = p.helperType(n, t) - default: - p.err(n, "unsupported volatile declarator type: %v", t) - return - } - - p.w("%sAtomicStore%s(&%s, %s(", p.task.crt, ht, nm, p.typ(n, t)) - p.assignmentExpression(f, expr, t, mode, flags) - p.w("))") -} - -func (p *project) atomicLoadNamedAddr(n cc.Node, t cc.Type, nm string) { - sz := t.Size() - switch sz { - case 4, 8: - // ok - default: - p.err(n, "unsupported volatile declarator size: %v", sz) - return - } - - var ht string - switch { - case t.IsScalarType(): - ht = p.helperType(n, t) - default: - p.err(n, "unsupported volatile declarator type: %v", t) - return - } - - p.w("%sAtomicLoad%s(&%s)", p.task.crt, ht, nm) -} - -func isRealType(op cc.Operand) bool { - switch op.Type().Kind() { - case cc.Float, cc.Double: - return true - default: - return false - } -} - -func (p *project) bfHelperType(t cc.Type) string { - switch { - case t.IsSignedType(): - return fmt.Sprintf("Int%d", t.Size()*8) - default: - return fmt.Sprintf("Uint%d", t.Size()*8) - } -} - -func (p *project) helperType(n cc.Node, t cc.Type) string { - for t.IsAliasType() { - if t2 := t.Alias(); t2 != t { //TODO HDF5 H5O.c - t = t2 - continue - } - - break - } - switch t.Kind() { - case cc.Int128: - return "Int128" - case cc.UInt128: - return "Uint128" - } - - s := p.typ(n, t) - return strings.ToUpper(s[:1]) + s[1:] -} - -func (p *project) helperType2(n cc.Node, from, to cc.Type) string { - if from.Kind() == to.Kind() { - return fmt.Sprintf("%s%s", p.task.crt, p.helperType(n, from)) - } - - return fmt.Sprintf("%s%sFrom%s", p.task.crt, p.helperType(n, to), p.helperType(n, from)) -} - -func (p *project) conditionalExpression(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.conditionalExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.conditionalExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.conditionalExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.conditionalExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.conditionalExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.conditionalExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.conditionalExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.conditionalExpressionSelect(f, n, t, mode, flags) - case exprCondReturn: - p.conditionalExpressionReturn(f, n, t, mode, flags) - case exprCondInit: - p.conditionalExpressionInit(f, n, t, mode, flags) - case exprDecay: - p.conditionalExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) conditionalExpressionDecay(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - t = t.Decay() - p.w(" func() %s { if ", p.typ(n, t)) - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" { return ") - switch n.Expression.Operand.Type().Kind() { - case cc.Array: - p.expression(f, n.Expression, t, exprDecay, flags) - case cc.Ptr: - panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) - default: - panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) - } - p.w("}; return ") - switch n.ConditionalExpression.Operand.Type().Kind() { - case cc.Array: - p.conditionalExpression(f, n.ConditionalExpression, t, exprDecay, flags) - default: - p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) - } - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionInit(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - f.condInitPrefix() - p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - t = t.Decay() - p.w("if ") - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" {") - p.expression(f, n.Expression, t, mode, flags) - p.w("} else { ") - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - p.w("}") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionReturn(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.w("return ") - p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - t = t.Decay() - p.w("if ") - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" {") - p.expression(f, n.Expression, t, mode, flags) - p.w("}; ") - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionFunc(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - 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(n, f, t, "") - p.w("{ if ") - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - 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)) - } -} - -func (p *project) conditionalExpressionPSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - p.conditionalExpression(f, n, t, exprValue, flags) - p.w("))") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionLValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionBool(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - p.w("(") - defer p.w(")") - defer p.w(" != 0 ") - p.conditionalExpression(f, n, t, exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionAddrOf(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - t = t.Decay() - p.w(" func() %s { if ", p.typ(n, t)) - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" { return ") - p.expression(f, n.Expression, t, exprValue, flags) - p.w("}; return ") - p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionVoid(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - switch { - case n.Expression.IsSideEffectsFree: - p.w("if !(") - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(") {") - p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) - p.w("}") - default: - p.w("if ") - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" {") - p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) - p.w("} else {") - p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) - p.w("}") - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) conditionalExpressionValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ConditionalExpressionLOr: // LogicalOrExpression - p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) - case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression - t = t.Decay() - p.w(" func() %s { if ", p.typ(n, t)) - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" { return ") - p.expression(f, n.Expression, t, exprValue, flags) - p.w("}; return ") - p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.logicalOrExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.logicalOrExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.logicalOrExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.logicalOrExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.logicalOrExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.logicalOrExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.logicalOrExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.logicalOrExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.logicalOrExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) logicalOrExpressionDecay(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionFunc(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionPSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionLValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - p.binaryLogicalOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionAddrOf(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionVoid(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - p.w("_ = ") - p.logicalOrExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalOrExpressionLAnd: // LogicalAndExpression - p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) - case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression - p.binaryLogicalOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryLogicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.binaryLogicalOrExpressionValue(f, n, t, mode, flags) - case exprBool: - p.binaryLogicalOrExpressionBool(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryLogicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" ||%s", tidyComment(" ", &n.Token)) - p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) -} - -func (p *project) binaryLogicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) - p.w(" ||%s", tidyComment(" ", &n.Token)) - p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) -} - -func (p *project) booleanBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { - p.w("(") - r = ")" - switch *mode { - case exprBool: - *mode = exprValue - default: - r = p.convert(n, from, to, flags) + r - p.w("%sBool32(", p.task.crt) - r = ")" + r - } - return r -} - -func (p *project) logicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.logicalAndExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.logicalAndExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.logicalAndExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.logicalAndExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.logicalAndExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.logicalAndExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.logicalAndExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.logicalAndExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.logicalAndExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) logicalAndExpressionDecay(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionFunc(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionPSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionLValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - p.binaryLogicalAndExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionAddrOf(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionVoid(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) logicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.LogicalAndExpressionOr: // InclusiveOrExpression - p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) - case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression - p.binaryLogicalAndExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryLogicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprBool: - p.binaryLogicalAndExpressionBool(f, n, t, mode, flags) - case exprValue: - p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryLogicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) - p.w(" &&%s", tidyComment(" ", &n.Token)) - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) -} - -func (p *project) binaryLogicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) - p.w(" &&%s", tidyComment(" ", &n.Token)) - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) -} - -func (p *project) inclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.inclusiveOrExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.inclusiveOrExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.inclusiveOrExpressionAddrof(f, n, t, mode, flags) - case exprBool: - p.inclusiveOrExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.inclusiveOrExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.inclusiveOrExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.inclusiveOrExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.inclusiveOrExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.inclusiveOrExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) inclusiveOrExpressionDecay(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionFunc(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionPSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionLValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - p.binaryInclusiveOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionAddrof(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionVoid(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - p.w("_ = ") - p.inclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) inclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) - case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression - p.binaryInclusiveOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryInclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // InclusiveOrExpression '|' ExclusiveOrExpression - switch mode { - case exprBool: - p.binaryInclusiveOrExpressionBool(f, n, t, mode, flags) - case exprValue: - p.binaryInclusiveOrExpressionValue(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryInclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // InclusiveOrExpression '|' ExclusiveOrExpression - - lt := n.InclusiveOrExpression.Operand.Type() - rt := n.ExclusiveOrExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryOrExpressionUint128(f, n, t, mode, flags) - return - } - - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch { - case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" |%s", tidyComment(" ", &n.Token)) - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" |%s", tidyComment(" ", &n.Token)) - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - } -} - -func (p *project) binaryOrExpressionUint128(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // InclusiveOrExpression '|' ExclusiveOrExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(".Or(") - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(")") -} - -func (p *project) binaryInclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch { - case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" |%s", tidyComment(" ", &n.Token)) - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" |%s", tidyComment(" ", &n.Token)) - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - } -} - -func orOverflows(lo, ro cc.Operand, promote cc.Type) bool { - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - return overflows(a.Or(a, b), promote) -} - -func (p *project) artithmeticBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { - p.w("(") - r = ")" - switch *mode { - case exprBool: - p.w("(") - r = ") != 0" + r - *mode = exprValue - default: - switch fk, tk := from.Type().Kind(), to.Kind(); { - case fk != tk && fk == cc.Int128: - return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) - case fk != tk && fk == cc.UInt128: - return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) - default: - r = p.convert(n, from, to, flags) + r - } - } - return r -} - -func (p *project) exclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.exclusiveOrExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.exclusiveOrExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.exclusiveOrExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.exclusiveOrExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.exclusiveOrExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.exclusiveOrExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.exclusiveOrExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.exclusiveOrExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.exclusiveOrExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) exclusiveOrExpressionDecay(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionFunc(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionPSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionLValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionBool(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - p.binaryExclusiveOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionAddrOf(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionVoid(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - p.w("_ = ") - p.exclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) exclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ExclusiveOrExpressionAnd: // AndExpression - p.andExpression(f, n.AndExpression, t, mode, flags) - case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression - p.binaryExclusiveOrExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryExclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // ExclusiveOrExpression '^' AndExpression - switch mode { - case exprValue, exprBool: - p.binaryExclusiveOrExpressionValue(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryExclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // ExclusiveOrExpression '^' AndExpression - - lt := n.ExclusiveOrExpression.Operand.Type() - rt := n.AndExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryExclusiveOrExpressionUint128(f, n, t, mode, flags) - return - } - - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch { - case xorOverflows(n.ExclusiveOrExpression.Operand, n.AndExpression.Operand, n.Promote()): - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" ^%s", tidyComment(" ", &n.Token)) - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(" ^%s", tidyComment(" ", &n.Token)) - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - } -} - -func (p *project) binaryExclusiveOrExpressionUint128(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { - // ExclusiveOrExpression '^' AndExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) - p.w(".Xor(") - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(")") -} - -func xorOverflows(lo, ro cc.Operand, promote cc.Type) bool { - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - return !lo.Type().IsSignedType() && a.Sign() == 0 || - !ro.Type().IsSignedType() && b.Sign() == 0 || - overflows(a.Xor(a, b), promote) -} - -func (p *project) andExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.andExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.andExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.andExpressionAddrof(f, n, t, mode, flags) - case exprBool: - p.andExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.andExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.andExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.andExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.andExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.andExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) andExpressionDecay(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionFunc(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionPSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionLValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - p.binaryAndExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionAddrof(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionVoid(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - p.w("_ = ") - p.andExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) andExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AndExpressionEq: // EqualityExpression - p.equalityExpression(f, n.EqualityExpression, t, mode, flags) - case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression - p.binaryAndExpression(f, n, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryAndExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - // AndExpression '&' EqualityExpression - switch mode { - case exprValue: - p.binaryAndExpressionValue(f, n, t, mode, flags) - case exprBool: - p.binaryAndExpressionBool(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryAndExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) - switch { - case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(" &%s", tidyComment(" ", &n.Token)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(" &%s", tidyComment(" ", &n.Token)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) - } -} - -func (p *project) binaryAndExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - // AndExpression '&' EqualityExpression - - lt := n.AndExpression.Operand.Type() - rt := n.EqualityExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryAndExpressionUint128(f, n, t, mode, flags) - return - } - - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch { - case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(" &%s", tidyComment(" ", &n.Token)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(" &%s", tidyComment(" ", &n.Token)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) - } -} - -func (p *project) binaryAndExpressionUint128(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { - // AndExpression '&' EqualityExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) - p.w(".And(") - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) - p.w(")") -} - -func andOverflows(lo, ro cc.Operand, promote cc.Type) bool { - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - return overflows(a.And(a, b), promote) -} - -func (p *project) equalityExpression(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.equalityExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.equalityExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.equalityExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.equalityExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.equalityExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.equalityExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.equalityExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.equalityExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.equalityExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) equalityExpressionDecay(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionFunc(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionPSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionLValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionBool(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - p.binaryEqualityExpression(f, n, " == ", t, mode, flags) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - p.binaryEqualityExpression(f, n, " != ", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionAddrOf(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - panic(todo("", p.pos(n))) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) equalityExpressionVoid(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - default: - // case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - // case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - p.w("_ = ") - p.equalityExpression(f, n, n.Operand.Type(), exprValue, flags) - } -} - -func (p *project) equalityExpressionValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.EqualityExpressionRel: // RelationalExpression - p.relationalExpression(f, n.RelationalExpression, t, mode, flags) - case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression - p.binaryEqualityExpression(f, n, " == ", t, mode, flags) - case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression - p.binaryEqualityExpression(f, n, " != ", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryEqualityExpression(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.binaryEqualityExpressionValue(f, n, oper, t, mode, flags) - case exprBool: - p.binaryEqualityExpressionBool(f, n, oper, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryEqualityExpressionBool(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) -} - -func (p *project) binaryEqualityExpressionValue(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) -} - -func (p *project) relationalExpression(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.relationalExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.relationalExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.relationalExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.relationalExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.relationalExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.relationalExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.relationalExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.relationalExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.relationalExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) relationalExpressionDecay(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionFunc(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionPSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionLValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionBool(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - p.binaryRelationalExpression(f, n, " < ", t, mode, flags) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - p.binaryRelationalExpression(f, n, " > ", t, mode, flags) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionAddrOf(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - panic(todo("", p.pos(n))) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) relationalExpressionVoid(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - default: - // case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - // case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - // case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - // case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - p.w("_ = ") - p.relationalExpression(f, n, n.Operand.Type(), exprValue, flags) - } -} - -func (p *project) relationalExpressionValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.RelationalExpressionShift: // ShiftExpression - p.shiftExpression(f, n.ShiftExpression, t, mode, flags) - case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression - p.binaryRelationalExpression(f, n, " < ", t, mode, flags) - case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression - p.binaryRelationalExpression(f, n, " > ", t, mode, flags) - case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression - p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) - case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression - p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryRelationalExpression(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // RelationalExpression "<=" ShiftExpression - lt := n.RelationalExpression.Operand.Type() - rt := n.ShiftExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryRelationalExpressionInt128(f, n, oper, t, mode, flags) - return - } - - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) -} - -func (p *project) binaryRelationalExpressionInt128(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // RelationalExpression "<=" ShiftExpression - defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) - p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) - p.w(".Cmp(") - p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) - p.w(") %s 0", oper) -} - -func (p *project) shiftExpression(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.shiftExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.shiftExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.shiftExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.shiftExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.shiftExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.shiftExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.shiftExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.shiftExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.shiftExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) shiftExpressionDecay(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionFunc(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionPSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionLValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionBool(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - p.binaryShiftExpression(f, n, "<<", t, mode, flags) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - p.binaryShiftExpression(f, n, ">>", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionAddrOf(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionVoid(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - panic(todo("", p.pos(n))) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) shiftExpressionValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.ShiftExpressionAdd: // AdditiveExpression - p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) - case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression - p.binaryShiftExpression(f, n, "<<", t, mode, flags) - case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression - p.binaryShiftExpression(f, n, ">>", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryShiftExpression(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // ShiftExpression "<<" AdditiveExpression - switch mode { - case exprValue: - p.binaryShiftExpressionValue(f, n, oper, t, mode, flags) - case exprBool: - p.binaryShiftExpressionBool(f, n, oper, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) todo(n cc.Node, t cc.Type) { - p.w("func() %s { panic(`%v: TODO (%v)`)}()", p.typ(n, t), n.Position(), origin(2)) -} - -func (p *project) binaryShiftExpressionBool(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) - switch { - case n.ShiftExpression.Operand.Type().IsBitFieldType(): - 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", 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)) - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - case isConstInteger(n.ShiftExpression.Operand): - s := p.convertNil(n, n.Operand.Type(), 0) - p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) - p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - default: - 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) - } -} - -func shiftOp(s string) string { - switch s { - case "<<": - return "Shl" - case ">>": - return "Shr" - default: - panic(todo("%q", s)) - } -} - -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 - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch k := n.ShiftExpression.Operand.Type().Kind(); { - case k == cc.Int128, k == cc.UInt128: - p.w("(") - p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) - p.w(").%s(", shiftOp(oper)) - p.additiveExpression(f, n.AdditiveExpression, p.intType, exprValue, flags) - p.w(")") - case n.ShiftExpression.Operand.Type().IsBitFieldType(): - 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", 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)) - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - case isConstInteger(n.ShiftExpression.Operand): - s := p.convertNil(n, n.Operand.Type(), 0) - p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) - p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - default: - 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) - } -} - -func shiftOverflows(n cc.Node, lo, ro cc.Operand, oper string, result cc.Type) bool { - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - if !b.IsUint64() { - return true - } - - bits := b.Uint64() - if bits > mathutil.MaxUint { - return true - } - - switch oper { - case "<<": - return overflows(a.Lsh(a, uint(bits)), result) - case ">>": - return overflows(a.Rsh(a, uint(bits)), result) - default: - panic(todo("", pos(n))) - } -} - -func (p *project) additiveExpression(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.additiveExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.additiveExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.additiveExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.additiveExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.additiveExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.additiveExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.additiveExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.additiveExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.additiveExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) additiveExpressionDecay(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - panic(todo("", p.pos(n))) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - panic(todo("", p.pos(n))) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionFunc(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - panic(todo("", p.pos(n))) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionPSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) - p.additiveExpression(f, n, t, exprValue, flags) - p.w("))") - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) - p.additiveExpression(f, n, t, exprValue, flags) - - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionLValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - panic(todo("", p.pos(n))) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionBool(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - p.binaryAdditiveExpression(f, n, "+", t, mode, flags) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - p.binaryAdditiveExpression(f, n, "-", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionAddrOf(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - panic(todo("", p.pos(n))) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionVoid(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case - cc.AdditiveExpressionAdd, // AdditiveExpression '+' MultiplicativeExpression - cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - - p.w("_ = ") - p.additiveExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) additiveExpressionValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.AdditiveExpressionMul: // MultiplicativeExpression - p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) - case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression - p.binaryAdditiveExpression(f, n, "+", t, mode, flags) - case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression - p.binaryAdditiveExpression(f, n, "-", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryAdditiveExpression(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // AdditiveExpression '+' MultiplicativeExpression - switch mode { - case exprValue: - p.binaryAdditiveExpressionValue(f, n, oper, t, mode, flags) - case exprBool: - p.binaryAdditiveExpressionBool(f, n, oper, t, mode, flags) - default: - panic(todo("", mode)) - } -} - -func (p *project) binaryAdditiveExpressionBool(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // AdditiveExpression '+' MultiplicativeExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) - lo := n.AdditiveExpression.Operand - ro := n.MultiplicativeExpression.Operand - lt := lo.Type() - rt := ro.Type() - switch { - case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y - defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian - switch { - case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - var s string - if isRealType(n.Operand) && n.Operand.Value() != nil { - s = p.convertNil(n, n.Promote(), flags) - } - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - } - default: - panic(todo("", n.Position(), lt, rt, oper)) - } -} - -func (p *project) binaryAdditiveExpressionValue(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // AdditiveExpression '+' MultiplicativeExpression - - lt := n.AdditiveExpression.Operand.Type() - rt := n.MultiplicativeExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryAdditiveExpressionUint128(f, n, oper, t, mode, flags) - return - } - - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - lo := n.AdditiveExpression.Operand - ro := n.MultiplicativeExpression.Operand - switch { - case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y - defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian - switch { - case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - var s string - if isRealType(n.Operand) && n.Operand.Value() != nil { - s = p.convertNil(n, n.Promote(), flags) - } - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - } - case lt.Kind() == cc.Ptr && rt.IsIntegerType(): // p +- i - p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) - p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) - p.w(")") - if sz := lt.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - case lt.Kind() == cc.Array && rt.IsIntegerType(): // p +- i - p.additiveExpression(f, n.AdditiveExpression, lt, exprDecay, flags) - p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) - p.w(")") - if sz := lt.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - case lt.IsIntegerType() && rt.Kind() == cc.Ptr: // i +- p - p.w("uintptr(") - p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) - p.w(")") - if sz := rt.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - p.w(" %s%s ", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) - case lt.IsIntegerType() && rt.Kind() == cc.Array: // i +- p - panic(todo("", p.pos(n))) - case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": // p - q - p.w("(") - p.additiveExpression(f, n.AdditiveExpression, n.Operand.Type(), exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Operand.Type(), exprValue, flags) - p.w(")/%d", lt.Elem().Size()) - case lt.Kind() == cc.Ptr && rt.Kind() == cc.Array && oper == "-": // p - q - defer p.w("%s", p.convertType(n, nil, n.Operand.Type(), 0)) - p.w("(") - p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, rt.Decay(), exprDecay, flags) - p.w(")/%d", lt.Elem().Size()) - case lt.Kind() == cc.Array && rt.Kind() == cc.Ptr && oper == "-": // p - q - panic(todo("", p.pos(n))) - case lt.Kind() == cc.Array && rt.Kind() == cc.Array && oper == "-": // p - q - panic(todo("", p.pos(n))) - default: - panic(todo("", n.Position(), lt, rt, oper)) - } -} - -func (p *project) binaryAdditiveExpressionUint128(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // AdditiveExpression '+' MultiplicativeExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) - switch oper { - case "+": - p.w(".Add(") - case "-": - p.w(".Sub(") - default: - panic(todo("%q", oper)) - } - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - p.w(")") -} - -func (p *project) bitFieldPatch2(n cc.Node, a, b cc.Operand, promote cc.Type) string { - //TODO bit field big endian - var m uint64 - var w int - switch { - case a.Type().IsBitFieldType(): - bf := a.Type().BitField() - w = bf.BitFieldWidth() - m = bf.Mask() >> bf.BitFieldOffset() - if b.Type().IsBitFieldType() { - bf = b.Type().BitField() - w2 := bf.BitFieldWidth() - if w2 != w { - panic(todo("", p.pos(n))) - } - } - case b.Type().IsBitFieldType(): - bf := b.Type().BitField() - w = bf.BitFieldWidth() - m = bf.Mask() >> bf.BitFieldOffset() - default: - return "" - } - - p.w("((") - switch { - case promote.IsSignedType(): - n := int(promote.Size())*8 - w - var s string - switch promote.Size() { - case 4: - s = fmt.Sprintf(")&%#x", int32(m)) - default: - s = fmt.Sprintf(")&%#x", m) - } - if n != 0 { - s += fmt.Sprintf("<<%d>>%[1]d", n) - } - return ")" + s - default: - return fmt.Sprintf(")&%#x)", m) - } -} - -func intAddOverflows(n cc.Node, lo, ro cc.Operand, oper string, promote cc.Type) bool { - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - switch oper { - case "+": - return overflows(a.Add(a, b), promote) - case "-": - return overflows(a.Sub(a, b), promote) - default: - panic(todo("", pos(n))) - } -} - -func getIntOperands(a, b cc.Operand) (x, y *big.Int, ok bool) { - switch n := a.Value().(type) { - case cc.Int64Value: - x = big.NewInt(int64(n)) - case cc.Uint64Value: - x = big.NewInt(0).SetUint64(uint64(n)) - default: - return nil, nil, false - } - - switch n := b.Value().(type) { - case cc.Int64Value: - return x, big.NewInt(int64(n)), true - case cc.Uint64Value: - return x, big.NewInt(0).SetUint64(uint64(n)), true - default: - return nil, nil, false - } -} - -func overflows(n *big.Int, promote cc.Type) bool { - switch k := promote.Kind(); { - case k == cc.Int128, k == cc.UInt128: - return false - case isSigned(promote): - switch promote.Size() { - case 4: - return n.Cmp(minInt32) < 0 || n.Cmp(maxInt32) > 0 - case 8: - return n.Cmp(minInt64) < 0 || n.Cmp(maxInt64) > 0 - } - default: - switch promote.Size() { - case 4: - return n.Sign() < 0 || n.Cmp(maxUint32) > 0 - case 8: - return n.Sign() < 0 || n.Cmp(maxUint64) > 0 - } - } - panic(todo("", promote.Size(), promote)) -} - -func (p *project) multiplicativeExpression(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprValue: - p.multiplicativeExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.multiplicativeExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.multiplicativeExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.multiplicativeExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.multiplicativeExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.multiplicativeExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.multiplicativeExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.multiplicativeExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.multiplicativeExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) multiplicativeExpressionDecay(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionFunc(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionPSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionLValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionBool(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case - cc.MultiplicativeExpressionMul, // MultiplicativeExpression '*' CastExpression - cc.MultiplicativeExpressionDiv, // MultiplicativeExpression '/' CastExpression - cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - - p.w("(") - defer p.w(")") - defer p.w(" != 0 ") - p.multiplicativeExpression(f, n, t, exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionAddrOf(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionVoid(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - panic(todo("", p.pos(n))) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) multiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.MultiplicativeExpressionCast: // CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression - p.binaryMultiplicativeExpression(f, n, "*", t, mode, flags) - case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression - p.binaryMultiplicativeExpression(f, n, "/", t, mode, flags) - case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression - p.binaryMultiplicativeExpression(f, n, "%", t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) binaryMultiplicativeExpression(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // MultiplicativeExpression '*' CastExpression - switch mode { - case exprValue: - p.binaryMultiplicativeExpressionValue(f, n, oper, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) binaryMultiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // MultiplicativeExpression '*' CastExpression - - lt := n.MultiplicativeExpression.Operand.Type() - rt := n.CastExpression.Operand.Type() - switch lk, rk := lt.Kind(), rt.Kind(); { - case - lk == cc.UInt128 || rk == cc.UInt128, - lk == cc.Int128 || rk == cc.Int128: - - p.binaryMultiplicativeExpressionUint128(f, n, oper, t, mode, flags) - return - } - - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - switch { - case intMulOverflows(n, n.Operand, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, oper, n.Promote()): - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - p.w(" %s%s", oper, tidyComment(" ", &n.Token)) - p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) - default: - defer p.w("%s", p.bitFieldPatch2(n, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, n.Promote())) //TODO bit field big endian - var s string - if isRealType(n.Operand) && n.Operand.Value() != nil { - s = p.convertNil(n, n.Promote(), flags) - } - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) - if (oper == "/" || oper == "%") && (isZeroReal(n.MultiplicativeExpression.Operand) || isZeroReal(n.CastExpression.Operand)) { - p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.Promote())) - defer p.w(")") - } - p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) - } -} - -func (p *project) binaryMultiplicativeExpressionUint128(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { - // MultiplicativeExpression '*' CastExpression - defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) - p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) - switch oper { - case "*": - p.w(".Mul(") - case "/": - p.w(".Div(") - case "%": - p.w(".Mod(") - default: - panic(todo("%q", oper)) - } - p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) - p.w(")") -} - -func isZeroReal(op cc.Operand) bool { - switch x := op.Value().(type) { - case cc.Float32Value: - return x == 0 - case cc.Float64Value: - return x == 0 - default: - return false - } -} - -func intMulOverflows(n cc.Node, r, lo, ro cc.Operand, oper string, promote cc.Type) bool { - if (isReal(lo) && !isInf(lo) || isReal(ro) && !isInf(ro)) && isInf(r) { - return true - } - - a, b, ok := getIntOperands(lo, ro) - if !ok { - return false - } - - switch oper { - case "*": - return overflows(a.Mul(a, b), promote) - case "/": - if b.Sign() == 0 { - return true - } - - return overflows(a.Div(a, b), promote) - case "%": - if b.Sign() == 0 { - return true - } - - return overflows(a.Mod(a, b), promote) - default: - panic(todo("", pos(n))) - } -} - -func isReal(op cc.Operand) bool { - switch op.Value().(type) { - case cc.Float32Value, cc.Float64Value: - return true - default: - return false - } -} - -func isInf(op cc.Operand) bool { - switch x := op.Value().(type) { - case cc.Float32Value: - return math.IsInf(float64(x), 0) - case cc.Float64Value: - return math.IsInf(float64(x), 0) - default: - return false - } -} - -func (p *project) castExpression(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - if n.Case == cc.CastExpressionCast { - if f != nil && n.CastExpression.Operand.Type().Kind() == cc.Ptr { // void *__ccgo_va_arg(__builtin_va_list ap); - sv := f.vaType - f.vaType = n.TypeName.Type() - defer func() { f.vaType = sv }() - } - } - switch mode { - case exprValue: - p.castExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.castExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.castExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.castExpressionBool(f, n, t, mode, flags) - case exprLValue: - p.castExpressionLValue(f, n, t, mode, flags) - case exprPSelect: - p.castExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.castExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.castExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.castExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) castExpressionDecay(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionFunc(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - ot := n.CastExpression.Operand.Type() - tn := n.TypeName.Type() - var ft cc.Type - switch tn.Kind() { - case cc.Ptr: - switch et := ot.Elem(); et.Kind() { - case cc.Function, cc.Void: - // ok - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) - } - switch t.Kind() { - case cc.Ptr: - switch et := t.Elem(); et.Kind() { - case cc.Function: - ft = et - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) - } - switch ot.Kind() { - case cc.Ptr: - switch et := ot.Elem(); et.Kind() { - case cc.Function, cc.Void: - p.w("(*(*") - p.functionSignature(n, f, ft, "") - p.w(")(unsafe.Pointer(") - p.castExpression(f, n.CastExpression, ot, exprAddrOf, flags) - p.w(")))") - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionPSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionLValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionBool(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - p.w("(") - defer p.w(")") - defer p.w(" != 0 ") - p.castExpression(f, n, n.Operand.Type(), exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionAddrOf(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - p.castExpressionAddrOf(f, n.CastExpression, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionVoid(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - p.castExpression(f, n.CastExpression, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.CastExpressionUnary: // UnaryExpression - p.unaryExpression(f, n.UnaryExpression, t, mode, flags) - case cc.CastExpressionCast: // '(' TypeName ')' CastExpression - if f != nil && p.pass1 && n.TypeName.Type().IsIntegerType() && n.CastExpression.Operand.Type().Kind() == cc.Array { - if d := n.CastExpression.Declarator(); d != nil { - f.pin(n, d) - } - } - switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { - case opNormal, opBitfield: - p.castExpressionValueNormal(f, n, t, mode, flags) - case opArray: - p.castExpressionValueArray(f, n, t, mode, flags) - case opFunction: - p.castExpressionValueFunction(f, n, t, mode, flags) - case opArrayParameter: - p.castExpressionValueNormal(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) castExpressionValueArrayParameter(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - // '(' TypeName ')' CastExpression - tn := n.TypeName.Type() - defer p.w("%s", p.convertType(n, tn, t, flags)) - p.castExpression(f, n.CastExpression, tn, mode, flags) -} - -func (p *project) castExpressionValueFunction(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - // '(' TypeName ')' CastExpression - op := n.CastExpression.Operand - tn := n.TypeName.Type() - switch { - case op.Type().Kind() == cc.Function: - switch { - case tn.Kind() == cc.Ptr && t.Kind() == cc.Ptr: - p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) - case tn.IsIntegerType(): - p.w("%s(", p.typ(n, tn)) - p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) - p.w(")") - default: - panic(todo("%v: tn %v expr %v", n.Position(), tn, op.Type())) - } - default: - panic(todo("%v: %v -> %v -> %v", p.pos(n), op.Type(), tn, t)) - } -} - -func (p *project) castExpressionValueArray(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - // '(' TypeName ')' CastExpression - tn := n.TypeName.Type() - switch { - case tn.IsScalarType(): - defer p.w("%s", p.convertType(n, nil, t, flags)) - p.castExpression(f, n.CastExpression, tn, exprDecay, flags) - default: - panic(todo("", p.pos(n))) - } -} - -func (p *project) castExpressionValueNormal(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { - // '(' TypeName ')' CastExpression - op := n.CastExpression.Operand - tn := n.TypeName.Type() - switch { - case op.Type().Kind() == cc.Ptr && tn.IsArithmeticType(): - defer p.w("%s", p.convertType(n, nil, t, flags|fForceConv)) - p.castExpression(f, n.CastExpression, op.Type(), mode, flags) - case tn.IsArithmeticType(): - switch { - case (tn.Kind() == cc.Float || tn.Kind() == cc.Double) && op.Type().IsIntegerType() && op.Value() != nil && t.IsIntegerType(): - panic(todo("", p.pos(n))) - case isNegativeInt(op) && isUnsigned(t): - defer p.w("%s", p.convertType(n, tn, t, flags|fForceConv)) - p.castExpression(f, n.CastExpression, tn, exprValue, flags) - default: - defer p.w("%s", p.convertType(n, tn, t, flags)) - p.castExpression(f, n.CastExpression, tn, exprValue, flags) - } - default: - switch tn.Kind() { - case cc.Ptr: - switch { - case t.Kind() == cc.Ptr && isNegativeInt(op): - p.w("%s(", p.helperType2(n, op.Type(), tn)) - defer p.w(")") - p.castExpression(f, n.CastExpression, op.Type(), mode, flags) - default: - defer p.w("%s", p.convertType(n, tn, t, flags)) - p.castExpression(f, n.CastExpression, tn, mode, flags) - } - case cc.Void: - p.castExpression(f, n.CastExpression, tn, exprVoid, flags) - default: - panic(todo("%s: %s %s -> %s %s -> %s %s", n.Position(), op.Type(), op.Type().Kind(), tn, tn.Kind(), t, t.Kind())) - } - } -} - -func (p *project) unaryExpression(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprLValue: - p.unaryExpressionLValue(f, n, t, mode, flags) - case exprValue: - p.unaryExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.unaryExpressionVoid(f, n, t, mode, flags) - case exprAddrOf: - p.unaryExpressionAddrOf(f, n, t, mode, flags) - case exprBool: - p.unaryExpressionBool(f, n, t, mode, flags) - case exprPSelect: - p.unaryExpressionPSelect(f, n, t, mode, flags) - case exprFunc: - p.unaryExpressionFunc(f, n, t, mode, flags) - case exprSelect: - p.unaryExpressionSelect(f, n, t, mode, flags) - case exprDecay: - p.unaryExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) unaryExpressionDecay(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDeref: // '*' CastExpression - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDeref: // '*' CastExpression - ot := n.CastExpression.Operand.Type() - switch ot.Kind() { - case cc.Ptr: - switch et := ot.Elem(); et.Kind() { - case - cc.Struct, - cc.Union: - - p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w(")))") - 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())) - } - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionFunc(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDeref: // '*' CastExpression - ot := n.CastExpression.Operand.Type() - switch ot.Kind() { - case cc.Ptr: - switch et := ot.Elem(); et.Kind() { - case cc.Function: - p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) - case cc.Ptr: - switch et2 := et.Elem(); et2.Kind() { - case cc.Function: - // 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())) - } - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - case cc.Function: - p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) - default: - panic(todo("", p.pos(n), ot, ot.Kind(), mode)) - } - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionPSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", n.Position())) - //TODO- p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - //TODO- p.unaryExpression(f, n, t, exprValue, flags) - //TODO- p.w("))") - case cc.UnaryExpressionDeref: // '*' CastExpression - panic(todo("", n.Position())) - //TODO- ot := n.CastExpression.Operand.Type() - //TODO- switch ot.Kind() { - //TODO- case cc.Ptr: - //TODO- switch et := ot.Elem(); { - //TODO- case et.Kind() == cc.Ptr: - //TODO- switch et2 := et.Elem(); et2.Kind() { - //TODO- case cc.Struct: - //TODO- if et2.IsIncomplete() { - //TODO- p.w("(*(**uintptr)(unsafe.Pointer(") - //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) - //TODO- p.w(")))") - //TODO- break - //TODO- } - - //TODO- p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) - //TODO- p.w(")))") - //TODO- default: - //TODO- panic(todo("", p.pos(n), et2, et2.Kind())) - //TODO- } - //TODO- default: - //TODO- panic(todo("", p.pos(n), et, et.Kind())) - //TODO- } - //TODO- default: - //TODO- panic(todo("", p.pos(n), ot, ot.Kind())) - //TODO- } - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", p.pos(n))) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionNot: // '!' CastExpression - p.w("!(") - p.castExpression(f, n.CastExpression, t, mode, flags) - p.w(")") - default: - p.w("(") - defer p.w(")") - defer p.w(" != 0 ") - p.unaryExpression(f, n, t, exprValue, flags) - } -} - -func (p *project) unaryExpressionAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionDeref: // '*' CastExpression - ot := n.CastExpression.Operand.Type() - switch ot.Kind() { - case cc.Ptr: - switch et := ot.Elem(); { - case - et.IsScalarType(), - et.Kind() == cc.Struct, - et.Kind() == cc.Union, - et.Kind() == cc.Array: - - p.unaryExpressionDeref(f, n, t, mode, flags) - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("", p.pos(n), ot, ot.Kind())) - } - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", n.Position())) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", n.Position())) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", n.Position())) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionVoid(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) - case cc.UnaryExpressionDec: // "--" UnaryExpression - p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) - case cc.UnaryExpressionAddrof: // '&' CastExpression - p.w("_ = ") - switch { - case n.CastExpression.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) - } - case cc.UnaryExpressionDeref: // '*' CastExpression - p.w("_ = *(*byte)(unsafe.Pointer(") - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w("))") - case - cc.UnaryExpressionPlus, // '+' CastExpression - cc.UnaryExpressionMinus, // '-' CastExpression - cc.UnaryExpressionNot, // '!' CastExpression - cc.UnaryExpressionCpl: // '~' CastExpression - - p.w("_ = ") - defer p.w("%s", p.convert(n, n.CastExpression.Operand, p.intType, flags)) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - // nop - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - // nop - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", n.Position())) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", n.Position())) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) unaryExpressionValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) - case cc.UnaryExpressionDec: // "--" UnaryExpression - p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) - case cc.UnaryExpressionAddrof: // '&' CastExpression - if t.Kind() != cc.Ptr { - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - } - switch { - case n.CastExpression.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) - } - case cc.UnaryExpressionDeref: // '*' CastExpression - ot := n.CastExpression.Operand.Type() - switch ot.Kind() { - case cc.Ptr, cc.Array: - switch et := ot.Elem(); { - case - et.IsScalarType(), - et.Kind() == cc.Array, - et.Kind() == cc.Struct, - 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())) - } - default: - panic(todo("", p.pos(n), ot, ot.Kind())) - } - case cc.UnaryExpressionPlus: // '+' CastExpression - p.w(" +") - p.castExpression(f, n.CastExpression, t, mode, flags) - case cc.UnaryExpressionMinus: // '-' CastExpression - switch { - case isNonNegativeInt(n.CastExpression.Operand) && t.Kind() == cc.Ptr: - p.w(" -%sUintptr(", p.task.crt) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w(")") - case isZeroReal(n.CastExpression.Operand): - p.w(" -") - defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) - p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w(")") - case isNonNegativeInt(n.CastExpression.Operand) && isUnsigned(n.Operand.Type()): - defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) - p.w("%sNeg%s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w(")") - default: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w(" -") - p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) - } - case cc.UnaryExpressionCpl: // '~' CastExpression - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - switch { - case n.CastExpression.Operand.Value() != nil: - switch { - case !t.IsIntegerType(): - p.w(" ^") - p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) - default: - p.w("%sCpl%s(", p.task.crt, p.helperType(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) - p.w(")") - } - default: - p.w(" ^") - p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) - } - case cc.UnaryExpressionNot: // '!' CastExpression - p.w("%sBool%s(!(", p.task.crt, p.helperType(n, t)) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprBool, flags) - p.w("))") - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - p.checkSizeof(n.UnaryExpression, n.UnaryExpression.Operand.Type()) - defer p.w("%s", p.convertNil(n, t, flags)) - if d := n.UnaryExpression.Declarator(); d != nil { - var isLocal bool - if f != nil { - if local := f.locals[d]; local != nil { - isLocal = true - if !local.isPinned { - p.w("unsafe.Sizeof(%s)", local.name) - return - } - } - } - - if !isLocal { - if tld := p.tlds[d]; tld != nil { - p.w("unsafe.Sizeof(%s)", tld.name) - break - } - - nm := d.Name().String() - if imp := p.imports[nm]; imp != nil { - imp.used = true - p.w("unsafe.Sizeof(%sX%s)", imp.qualifier, nm) - break - } - } - } - - t := n.UnaryExpression.Operand.Type() - if p.isArray(f, n.UnaryExpression, t) { - p.w("%d", t.Len()*t.Elem().Size()) - break - } - - s := "(0)" - if !t.IsArithmeticType() { - switch t.Kind() { - case cc.Ptr: - // ok - case cc.Struct, cc.Union, cc.Array: - s = "{}" - default: - panic(todo("", t.Kind())) - } - } - switch t.Kind() { - case cc.Int128, cc.UInt128: - s = "{}" - } - p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - defer p.w("%s", p.convertNil(n, t, flags)) - t := n.TypeName.Type() - p.checkSizeof(n.TypeName, t) - if t.Kind() == cc.Array { - p.w("%d", t.Len()*t.Elem().Size()) - break - } - - s := "(0)" - if !t.IsArithmeticType() { - switch t.Kind() { - case cc.Ptr: - // ok - case cc.Struct, cc.Union: - s = "{}" - default: - panic(todo("", t.Kind())) - } - } - switch t.Kind() { - case cc.Int128, cc.UInt128: - s = "{}" - } - p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - if n.TypeName.Type().Kind() == cc.Void { - p.intConst(n, "", n.Operand, t, flags) - break - } - - defer p.w("%s", p.convertNil(n, t, flags)) - t := n.UnaryExpression.Operand.Type() - if p.isArray(f, n.UnaryExpression, t) { - p.w("%d", t.Len()*t.Elem().Size()) - break - } - - s := "(0)" - if !t.IsArithmeticType() { - switch t.Kind() { - case cc.Ptr: - // ok - case cc.Struct, cc.Union: - s = "{}" - default: - panic(todo("", t.Kind())) - } - } - p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - if n.TypeName.Type().Kind() == cc.Void { - p.intConst(n, "", n.Operand, t, flags) - break - } - - defer p.w("%s", p.convertNil(n, t, flags)) - t := n.TypeName.Type() - if t.Kind() == cc.Array { - p.w("%d", t.Len()*t.Elem().Size()) - break - } - - s := "(0)" - if !t.IsArithmeticType() { - switch t.Kind() { - case cc.Ptr: - // ok - case cc.Struct, cc.Union: - s = "{}" - default: - panic(todo("", t.Kind())) - } - } - p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", n.Position())) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) checkSizeof(n cc.Node, t cc.Type) { - if !p.checkSizeof0(n, t) { - p.err(n, "sizeof type %s: not supported", t.Alias()) - } -} - -func (p *project) checkSizeof0(n cc.Node, t cc.Type) (ok bool) { - switch t.Kind() { - case cc.Array: - return !t.IsVLA() - case cc.Struct, cc.Union: - nf := t.NumField() - for i := []int{0}; i[0] < nf; i[0]++ { - if !p.checkSizeof0(n, t.FieldByIndex(i).Type()) { - return false - } - } - } - return true -} - -func (p *project) unaryExpressionLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - p.postfixExpression(f, n.PostfixExpression, t, mode, flags) - case cc.UnaryExpressionInc: // "++" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionDec: // "--" UnaryExpression - panic(todo("", p.pos(n))) - case cc.UnaryExpressionAddrof: // '&' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionDeref: // '*' CastExpression - ot := n.CastExpression.Operand.Type() - switch ot.Kind() { - case cc.Ptr, cc.Array: - switch et := ot.Elem(); { - case - et.IsScalarType(), - et.Kind() == cc.Struct, - et.Kind() == cc.Union: - - p.unaryExpressionDeref(f, n, t, mode, flags) - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("", p.pos(n), ot, ot.Kind())) - } - case cc.UnaryExpressionPlus: // '+' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionMinus: // '-' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionCpl: // '~' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionNot: // '!' CastExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' - panic(todo("", n.Position())) - case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' - panic(todo("", n.Position())) - case cc.UnaryExpressionImag: // "__imag__" UnaryExpression - panic(todo("", n.Position())) - case cc.UnaryExpressionReal: // "__real__" UnaryExpression - panic(todo("", n.Position())) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func isSigned(t cc.Type) bool { return t.IsIntegerType() && t.IsSignedType() } -func isUnsigned(t cc.Type) bool { return t.IsIntegerType() && !t.IsSignedType() } - -func isConstInteger(op cc.Operand) bool { - switch op.Value().(type) { - case cc.Int64Value, cc.Uint64Value: - return true - default: - return false - } -} - -func isNegativeInt(op cc.Operand) bool { - switch x := op.Value().(type) { - case cc.Int64Value: - return x < 0 - default: - return false - } -} - -func isNonNegativeInt(op cc.Operand) bool { - switch x := op.Value().(type) { - case cc.Int64Value: - return x >= 0 - case cc.Uint64Value: - return true - default: - return false - } -} - -func (p *project) unaryExpressionPreIncDec(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // "++" UnaryExpression etc. - switch mode { - case exprValue: - p.unaryExpressionPreIncDecValue(f, n, oper, oper2, t, mode, flags) - case exprVoid: - p.unaryExpressionPreIncDecVoid(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", p.pos(n), mode)) - } -} - -func (p *project) unaryExpressionPreIncDecVoid(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // "++" UnaryExpression etc. - switch n.UnaryExpression.Operand.Type().Kind() { - case cc.Int128, cc.UInt128: - p.unaryExpressionLValue(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, 0) - switch oper { - case "++": - p.w(".LValueInc()") - case "--": - p.w(".LValueDec()") - default: - panic(todo("internal error: %q", oper)) - } - return - } - - // "++" UnaryExpression etc. - switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { - case opNormal: - p.unaryExpressionPreIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) - case opArrayParameter: - p.unaryExpressionPreIncDecVoidArrayParameter(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) unaryExpressionPreIncDecVoidArrayParameter(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // "++" UnaryExpression etc. - ut := n.UnaryExpression.Operand.Type() - p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) - switch d := p.incDelta(n, ut); d { - case 1: - p.w("%s", oper) - default: - p.w("%s %d", oper2, d) - } -} - -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.isVolatileOrAtomic(d) { - x := "Dec" - if oper == "++" { - x = "Inc" - } - p.w("%sPre%sAtomic%s(&", p.task.crt, x, p.helperType(n, d.Type())) - switch local, tld := f.locals[d], p.tlds[d]; { - case local != nil: - p.w("%s", local.name) - case tld != nil: - p.w("%s", tld.name) - default: - panic(todo("")) - } - p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) - return - } - - p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) - if ut.IsIntegerType() || ut.Kind() == cc.Ptr && p.incDelta(n, ut) == 1 { - p.w("%s", oper) - return - } - - switch ut.Kind() { - case cc.Ptr, cc.Double, cc.Float: - p.w("%s %d", oper2, p.incDelta(n, ut)) - return - } - - panic(todo("", p.pos(n))) -} - -func (p *project) unaryExpressionPreIncDecValue(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // "++" UnaryExpression etc. - switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { - case opNormal: - p.unaryExpressionPreIncDecValueNormal(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) unaryExpressionPreIncDecValueNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // "++" UnaryExpression etc. - defer p.w("%s", p.convert(n, n.UnaryExpression.Operand, t, flags)) - x := "Dec" - if oper == "++" { - x = "Inc" - } - ut := n.UnaryExpression.Operand.Type() - p.w("%sPre%s%s(&", p.task.crt, x, p.helperType(n, ut)) - p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) - p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) -} - -func (p *project) unaryExpressionDeref(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - switch mode { - case exprValue: - p.unaryExpressionDerefValue(f, n, t, mode, flags) - case exprLValue: - p.unaryExpressionDerefLValue(f, n, t, mode, flags) - case exprAddrOf: - p.unaryExpressionDerefAddrOf(f, n, t, mode, flags) - case exprBool: - p.unaryExpressionDerefBool(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) unaryExpressionDerefBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - p.w("(") - defer p.w(")") - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w(")) != 0") -} - -func (p *project) unaryExpressionDerefAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) -} - -func (p *project) unaryExpressionDerefLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { - case opNormal: - p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) - case opArray: - panic(todo("", p.pos(n))) - p.unaryExpressionDerefLValueArray(f, n, t, mode, flags) - case opArrayParameter: - p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) unaryExpressionDerefLValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) -} - -func (p *project) unaryExpressionDerefLValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) -} - -func (p *project) unaryExpressionDerefValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { - case opNormal, opArrayParameter: - p.unaryExpressionDerefValueNormal(f, n, t, mode, flags) - case opArray: - p.unaryExpressionDerefValueArray(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) unaryExpressionDerefValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) - p.w("[0]") -} - -func (p *project) unaryExpressionDerefValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { - // '*' CastExpression - switch op := n.Operand.Type(); { - case op.Kind() == cc.Array: - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) - default: - defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) - } -} - -func (p *project) postfixExpression(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprLValue: - p.postfixExpressionLValue(f, n, t, mode, flags) - case exprValue: - p.postfixExpressionValue(f, n, t, mode, flags) - case exprVoid: - p.postfixExpressionVoid(f, n, t, mode, flags) - case exprFunc: - p.postfixExpressionFunc(f, n, t, mode, flags) - case exprAddrOf: - p.postfixExpressionAddrOf(f, n, t, mode, flags) - case exprSelect: - p.postfixExpressionSelect(f, n, t, mode, flags) - case exprPSelect: - p.postfixExpressionPSelect(f, n, t, mode, flags) - case exprBool: - p.postfixExpressionBool(f, n, t, mode, flags) - case exprDecay: - p.postfixExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) postfixExpressionDecay(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - pe := n.PostfixExpression.Operand.Type() - p.w("(") - switch { - case pe.Kind() == cc.Array: - p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) - case pe.Kind() == cc.Ptr: - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - default: - panic(todo("", p.pos(n))) - } - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w(")") - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.postfixExpression(f, n, t, exprAddrOf, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.postfixExpression(f, n, t, exprAddrOf, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionDec: // PostfixExpression "--" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - p.postfixExpressionCall(f, n, t, mode, flags) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionDec: // PostfixExpression "--" - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - p.w("(") - defer p.w(")") - defer p.w(" != 0") - p.postfixExpression(f, n, t, exprValue, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -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) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.postfixExpressionPSelectIndex(f, n, t, mode, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - p.postfixExpressionPSelectCall(f, n, t, mode, flags) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.postfixExpressionPSelectSelect(f, n, t, mode, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.postfixExpressionPSelectPSelect(f, n, t, mode, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionDec: // PostfixExpression "--" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionPSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - case opStruct: - p.postfixExpressionPSelectSelectStruct(f, n, t, mode, flags) - case opUnion: - p.postfixExpressionPSelectSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionPSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - 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(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) - p.w(")))") - } -} - -func (p *project) postfixExpressionPSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) - p.w(".%s", p.fieldName(n, n.Token2.Value)) - p.w("))") - - } -} - -func (p *project) postfixExpressionPSelectCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - p.postfixExpressionCall(f, n, t, exprValue, flags) - p.w("))") -} - -func (p *project) postfixExpressionPSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - // case opArray: - // p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) - case opNormal: - p.postfixExpressionPSelectIndexNormal(f, n, t, mode, flags) - case opArrayParameter: - p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionPSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - pe := n.PostfixExpression.Operand.Type() - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - case pe.Kind() == cc.Array: - p.w("(") - defer p.w(")") - p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w(")))") - default: - p.w("(") - defer p.w(")") - p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w(")))") - } -} - -func (p *project) postfixExpressionSelect(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) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.postfixExpressionSelectIndex(f, n, t, mode, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - p.postfixExpression(f, n, t, exprValue, flags) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.postfixExpressionSelectSelect(f, n, t, mode, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.postfixExpressionSelectPSelect(f, n, t, mode, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionDec: // PostfixExpression "--" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionPSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { - case opStruct: - p.postfixExpressionPSelectPSelectStruct(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionPSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprPSelect, flags) - p.w(".%s", p.fieldName(n, n.Token2.Value)) - p.w("))") - } -} - -func (p *project) postfixExpressionSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { - case opStruct: - p.postfixExpressionSelectPSelectStruct(f, n, t, mode, flags) - case opUnion: - p.postfixExpressionSelectPSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionSelectPSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - 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(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w("))") - } -} - -func (p *project) postfixExpressionSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - 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)) - } - } -} - -func (p *project) postfixExpressionSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - switch k := p.structOrUnion(n); k { - case opUnion: - p.postfixExpressionSelectSelectUnion(f, n, t, mode, flags) - case opStruct: - p.postfixExpressionSelectSelectStruct(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) structOrUnion(n *cc.PostfixExpression) opKind { - t := n.PostfixExpression.Operand.Type() - switch n.Case { - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - // ok - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - if t.Kind() == cc.Ptr { - t = t.Elem() - break - } - - p.err(n, "expected pointer type: %s", t) - return opStruct - } - f, path, ok := t.FieldByName2(n.Token2.Src) - if !ok { - p.err(&n.Token, "unknown field: %s", n.Token2) - return opStruct - } - - for len(path) > 1 { - f = t.FieldByIndex(path[:1]) - path = path[1:] - t = f.Type() - } - if t.Kind() == cc.Union { - // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opUnion) - return opUnion - } - - // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opStruct) - return opStruct -} - -func (p *project) postfixExpressionSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) - p.w(".%s", p.fieldName(n, n.Token2.Value)) - } -} - -func (p *project) postfixExpressionSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - 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(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.w("))") - } -} - -func (p *project) postfixExpressionSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - case opArray: - p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) - case opNormal: - p.postfixExpressionSelectIndexNormal(f, n, t, mode, flags) - case opArrayParameter: - p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionSelectIndexArrayParamater(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - pe := n.PostfixExpression.Operand.Type() - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - } -} - -func (p *project) postfixExpressionSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - pe := n.PostfixExpression.Operand.Type() - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - case pe.Kind() != cc.Ptr: - p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - default: - p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - } -} - -func (p *project) postfixExpressionSelectIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) - p.w("[") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) - p.w("]") - } -} - -func (p *project) postfixExpressionAddrOf(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.postfixExpressionAddrOfIndex(f, n, t, mode, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - 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 "++" - p.postfixExpressionIncDec(f, n, "++", "+=", t, exprLValue, flags) - case cc.PostfixExpressionDec: // PostfixExpression "--" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - 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(" func() uintptr { *(*%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) - p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) - } - default: - panic(todo("%v: %v", n.Position(), tn)) - } - default: - switch { - case p.pass1: - off := roundup(f.off, uintptr(tn.Align())) - f.complits[n] = off - f.off += tn.Size() - default: - off := f.complits[n] - p.w(" func() uintptr { *(*%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) - p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) - } - } - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionAddrOfPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - p.w("(") - defer p.w(")") - pe := n.PostfixExpression.Operand.Type() - switch { - case n.Operand.Type().IsBitFieldType(): - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.bitFldOff(pe.Elem(), n.Token2) - case pe.Kind() == cc.Array: - p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) - p.fldOff(pe.Elem(), n.Token2) - default: - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.fldOff(pe.Elem(), n.Token2) - } -} - -func (p *project) postfixExpressionAddrOfIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - p.w("(") - defer p.w(")") - switch { - case n.Operand.Type().Kind() == cc.Array: - fallthrough - default: - pe := n.PostfixExpression.Operand.Type() - d := n.PostfixExpression.Declarator() - switch { - case pe.Kind() == cc.Ptr: - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - case pe.Kind() == cc.Array && d != nil && d.IsParameter: - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - default: - p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) - } - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Decay().Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - } -} - -func (p *project) postfixExpressionAddrOfSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - p.w("(") - defer p.w(")") - switch { - case n.Operand.Type().IsBitFieldType(): - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) - p.bitFldOff(pe, n.Token2) - case n.Operand.Type().Kind() == cc.Array: - fallthrough - default: - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) - p.fldOff(pe, n.Token2) - } -} - -func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - switch n.Operand.Type().Kind() { - case cc.Ptr: - switch et := n.Operand.Type().Elem(); et.Kind() { - case cc.Function: - p.fnVal(n, f, func() { - p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) - }, nil, n.Operand.Type(), 0, mode, flags) - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("", n.Position(), n.Operand.Type())) - } - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - switch n.Operand.Type().Kind() { - case cc.Ptr: - switch et := n.Operand.Type().Elem(); et.Kind() { - case cc.Function: - p.fnVal(n, f, func() { - p.postfixExpressionCall(f, n, t, exprValue, flags) - }, nil, n.Operand.Type(), 0, mode, flags) - default: - panic(todo("", p.pos(n), et, et.Kind())) - } - default: - panic(todo("", n.Position(), n.Operand.Type())) - } - case cc.PostfixExpressionSelect: // 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.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())) - } - default: - panic(todo("", p.pos(n), n.Operand.Type(), n.Operand.Type().Kind())) - } - default: - panic(todo("", n.Position(), n.Operand.Type())) - } - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - 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 "--" - panic(todo("", p.pos(n))) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.w("_ = ") - p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - p.postfixExpressionCall(f, n, n.Operand.Type(), mode, flags) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.w("_ = ") - p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.w("_ = ") - p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) - case cc.PostfixExpressionDec: // PostfixExpression "--" - p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - 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: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - if p.isArray(f, n.PrimaryExpression, n.Operand.Type()) && t.Kind() == cc.Ptr { - mode = exprDecay - } - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.postfixExpressionValueIndex(f, n, t, mode, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - p.postfixExpressionCall(f, n, t, mode, flags) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.postfixExpressionValueSelect(f, n, t, mode, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.postfixExpressionValuePSelect(f, n, t, mode, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) - case cc.PostfixExpressionDec: // PostfixExpression "--" - p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - 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(" func() uintptr { *(*%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) - p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) - } - return - default: - panic(todo("%v: %v", n.Position(), tn)) - } - } - - defer p.w("%s", p.convertType(n, tn, t, flags)) - p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - // Built-in Function: int __builtin_types_compatible_p (type1, type2) You can - // use the built-in function __builtin_types_compatible_p to determine whether - // two types are the same. - // - // This built-in function returns 1 if the unqualified versions of the types - // type1 and type2 (which are types, not expressions) are compatible, 0 - // otherwise. The result of this built-in function can be used in integer - // constant expressions. - // - // This built-in function ignores top level qualifiers (e.g., const, volatile). - // For example, int is equivalent to const int. - // - // The type int[] and int[5] are compatible. On the other hand, int and char * - // are not compatible, even if the size of their types, on the particular - // architecture are the same. Also, the amount of pointer indirection is taken - // into account when determining similarity. Consequently, short * is not - // similar to short **. Furthermore, two types that are typedefed are - // considered compatible if their underlying types are compatible. - // - // An enum type is not considered to be compatible with another enum type even - // if both are compatible with the same integer type; this is what the C - // standard specifies. For example, enum {foo, bar} is not similar to enum - // {hot, dog}. - // - // You typically use this function in code whose execution varies depending on - // the arguments’ types. For example: - // - // #define foo(x) \ - // ({ \ - // typeof (x) tmp = (x); \ - // if (__builtin_types_compatible_p (typeof (x), long double)) \ - // tmp = foo_long_double (tmp); \ - // else if (__builtin_types_compatible_p (typeof (x), double)) \ - // tmp = foo_double (tmp); \ - // else if (__builtin_types_compatible_p (typeof (x), float)) \ - // tmp = foo_float (tmp); \ - // else \ - // abort (); \ - // tmp; \ - // }) - // - // 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) - case op.IsZero(): - p.assignmentExpression(f, n.AssignmentExpression3, t, mode, flags) - default: - panic(todo("")) - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { - case opStruct: - p.postfixExpressionValuePSelectStruct(f, n, t, mode, flags) - case opUnion: - p.postfixExpressionValuePSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - 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()) - } - pe := n.PostfixExpression.Operand.Type() - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - 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, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) - p.w("))") - } -} - -func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - fld := n.Field - pe := n.PostfixExpression.Operand.Type() - k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) - switch { - case n.Operand.Type().IsBitFieldType(): - p.w("(") - defer p.w(")") - fld := n.Field - defer p.w("%s", p.convertType(n, fld.Promote(), t, flags)) - switch pe.Kind() { - case cc.Array: - x := p.convertType(n, nil, fld.Promote(), flags) - p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) - p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) - p.bitFldOff(pe.Elem(), n.Token2) - p.w("))") - p.w("&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) - if fld.Type().IsSignedType() { - panic(todo("")) - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - default: - 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("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) - if fld.Type().IsSignedType() { - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - } - case n.Operand.Type().Kind() == cc.Array: - defer p.w("%s", p.convertType(n, n.Operand.Type().Decay(), t.Decay(), flags)) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.fldOff(n.PostfixExpression.Operand.Type().Elem(), n.Token2) - case k == opArray: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w("[0].%s", p.fieldName(n, n.Token2.Value)) - default: - if fld.IsBitField() { - 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)) - 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) { - // PostfixExpression '[' Expression ']' - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - case opArray: - p.postfixExpressionValueIndexArray(f, n, t, mode, flags) - case opNormal: - p.postfixExpressionValueIndexNormal(f, n, t, mode, flags) - case opArrayParameter: - p.postfixExpressionValueIndexArrayParameter(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} -func (p *project) postfixExpressionValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - pe := n.PostfixExpression.Operand.Type() - switch { - case n.Operand.Type().Kind() == cc.Array: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(") - defer p.w(")") - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - default: - 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) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - } -} - -func (p *project) postfixExpressionValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().Kind() == cc.Array: - p.w("(") - defer p.w(")") - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - default: - switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { - case cc.Ptr: - 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) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - case cc.Array: - 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, exprDecay, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - default: - panic(todo("", p.pos(n), pe, pe.Kind())) - } - } -} - -func (p *project) postfixExpressionValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - pe := n.PostfixExpression.Operand.Type() - switch n.Operand.Type().Kind() { - case cc.Array: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(") - defer p.w(")") - p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - default: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) - p.w("[") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) - p.w("]") - } -} - -func (p *project) postfixExpressionValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - case opStruct: - p.postfixExpressionValueSelectStruct(f, n, t, mode, flags) - case opUnion: - p.postfixExpressionValueSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - pe := n.PostfixExpression.Operand.Type() - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - 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("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) - if fld.Type().IsSignedType() { - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - case n.Operand.Type().Kind() == cc.Array: - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - default: - if fld.IsBitField() { - 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, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.w("))") - } -} - -func (p *project) postfixExpressionValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - pe := n.PostfixExpression.Operand.Type() - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - 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("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) - if fld.Type().IsSignedType() { - p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) - } - case n.Operand.Type().Kind() == cc.Array: - p.postfixExpression(f, n, t, exprDecay, flags) - case fld.InUnion(): - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, fld.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.fldOff(pe, n.Token2) - p.w("))") - default: - if fld.IsBitField() { - 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.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) - p.w(".%s", p.fieldName(n, n.Token2.Value)) - } -} - -func (p *project) postfixExpressionLValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PostfixExpressionPrimary: // PrimaryExpression - p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) - case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' - p.postfixExpressionLValueIndex(f, n, t, mode, flags) - case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.postfixExpressionLValueSelect(f, n, t, mode, flags) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - p.postfixExpressionLValuePSelect(f, n, t, mode, flags) - case cc.PostfixExpressionInc: // PostfixExpression "++" - p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) - case cc.PostfixExpressionDec: // PostfixExpression "--" - p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) - case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' - panic(todo("", p.pos(n))) - case cc.PostfixExpressionChooseExpr: - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) postfixExpressionLValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - pe := n.PostfixExpression - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { - case opStruct: - if !p.inUnion(n, pe.Operand.Type().Elem(), n.Token2.Value) { - p.postfixExpressionLValuePSelectStruct(f, n, t, mode, flags) - break - } - - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, pe, pe.Operand.Type(), exprValue, flags) - p.fldOff(pe.Operand.Type().Elem(), n.Token2) - p.w("))") - case opUnion: - p.postfixExpressionLValuePSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionLValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - 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(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) - p.w(")))") - } -} - -func (p *project) postfixExpressionLValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "->" IDENTIFIER - fld := n.Field - pe := n.PostfixExpression.Operand.Type() - k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - case k == opArray: - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - p.w("[0].%s", p.fieldName(n, n.Token2.Value)) - default: - if fld.IsBitField() { - 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)) - } -} - -func (p *project) postfixExpressionLValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { - case opArray: - p.postfixExpressionLValueIndexArray(f, n, t, mode, flags) - case opNormal: - p.postfixExpressionLValueIndexNormal(f, n, t, mode, flags) - case opArrayParameter: - p.postfixExpressionLValueIndexArrayParameter(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionLValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - pe := n.PostfixExpression.Operand.Type() - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) - p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") -} - -func (p *project) postfixExpressionLValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - switch { - case n.Operand.Type().Kind() == cc.Array: - panic(todo("", p.pos(n))) - default: - switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { - case cc.Ptr: - 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) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - case cc.Array: - 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, exprDecay, flags) - if !n.Expression.Operand.IsZero() { - p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) - if sz := pe.Elem().Size(); sz != 1 { - p.w("*%d", sz) - } - } - p.w("))") - default: - panic(todo("", p.pos(n), pe)) - } - } -} - -func (p *project) postfixExpressionLValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '[' Expression ']' - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) - p.w("[") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) - p.w("]") -} - -func (p *project) postfixExpressionLValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - pe := n.PostfixExpression - switch k := p.opKind(f, pe, pe.Operand.Type()); k { - case opStruct: - if !p.inUnion(n, pe.Operand.Type(), n.Token2.Value) { - p.postfixExpressionLValueSelectStruct(f, n, t, mode, flags) - break - } - - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) - p.fldOff(pe.Operand.Type(), n.Token2) - p.w("))") - case opUnion: - p.postfixExpressionLValueSelectUnion(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) inUnion(n cc.Node, t cc.Type, fname cc.StringID) bool { - f, ok := t.FieldByName(fname) - if !ok { - p.err(n, "unknown field: %s", fname) - return false - } - - return f.InUnion() -} - -func (p *project) postfixExpressionLValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - fld := n.Field - pe := n.PostfixExpression.Operand.Type() - switch { - case pe.Kind() == cc.Array: - panic(todo("", p.pos(n))) - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - nonZeroUintptr(fld.Offset()) - p.w("))") - } -} - -func (p *project) postfixExpressionLValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '.' IDENTIFIER - fld := n.Field - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if fld.IsBitField() { - p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) - } - pe := n.PostfixExpression.Operand.Type() - p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) - p.w(".%s", p.fieldName(n, n.Token2.Value)) - } -} - -func (p *project) postfixExpressionIncDec(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprVoid: - p.postfixExpressionIncDecVoid(f, n, oper, oper2, t, mode, flags) - case exprLValue: - p.postfixExpressionIncDecLValue(f, n, oper, oper2, t, mode, flags) - case exprValue: - p.postfixExpressionIncDecValue(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", mode)) - } -} - -func (p *project) postfixExpressionIncDecValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "++" - pe := n.PostfixExpression.Operand.Type() - switch k := p.opKind(f, n.PostfixExpression, pe); k { - case opNormal: - p.postfixExpressionIncDecValueNormal(f, n, oper, oper2, t, mode, flags) - case opBitfield: - p.postfixExpressionIncDecValueBitfield(f, n, oper, oper2, t, mode, flags) - case opArrayParameter: - p.postfixExpressionIncDecValueArrayParameter(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", n.Position(), pe, pe.Kind(), k)) - } -} - -func (p *project) postfixExpressionIncDecValueArrayParameter(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "++" - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) - x := "Dec" - if oper == "++" { - x = "Inc" - } - p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe.Decay())) - p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) - p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) -} - -func (p *project) postfixExpressionIncDecValueBitfield(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "++" - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) - x := "Dec" - if oper == "++" { - x = "Inc" - } - bf := pe.BitField() - p.w("%sPost%sBitFieldPtr%d%s(", p.task.crt, x, bf.BitFieldBlockWidth(), p.bfHelperType(pe)) - p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) - p.w(", %d, %d, %d, %#x)", p.incDelta(n.PostfixExpression, pe), bf.BitFieldBlockWidth(), bf.BitFieldOffset(), bf.Mask()) -} - -func (p *project) postfixExpressionIncDecValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression "++" - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) - x := "Dec" - if oper == "++" { - x = "Inc" - } - 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 - if f != nil { - local = f.locals[d] - } - if local == nil { - tld = p.tlds[d] - } - switch { - case local != nil: - p.w("%s", local.name) - case tld != nil: - p.w("%s", tld.name) - default: - panic(todo("")) - } - p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) - return - } - - p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) - p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) - p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) -} - -func (p *project) postfixExpressionIncDecLValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - switch k := p.opKind(f, n, n.Operand.Type()); k { - case opNormal: - p.postfixExpressionIncDecLValueNormal(f, n, oper, oper2, t, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) postfixExpressionIncDecLValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - pe := n.PostfixExpression.Operand.Type() - defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) - x := "Dec" - if oper == "++" { - x = "Inc" - } - p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) - p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) - p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) -} - -func (p *project) postfixExpressionIncDecVoid(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { - switch k := p.opKind(f, n, n.Operand.Type()); k { - case opNormal: - p.postfixExpressionIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) - case opBitfield: - p.postfixExpressionIncDec(f, n, oper, oper2, t, exprValue, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -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.isVolatileOrAtomic(d) { - switch d.Type().Size() { - case 4, 8: - if !d.Type().IsIntegerType() { - p.err(n, "unsupported volatile declarator type: %v", d.Type()) - return - } - - if f != nil { - if local := f.locals[d]; local != nil { - if local.isPinned { - panic(todo("")) - } - - p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), local.name) - switch oper { - case "++": - // ok - case "--": - p.w("-") - default: - p.err(n, "unsupported volatile declarator operation: %v", oper) - } - p.w("%d)", p.incDelta(n, d.Type())) - return - } - } - - if tld := p.tlds[d]; tld != nil { - p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), tld.name) - switch oper { - case "++": - // ok - case "--": - p.w("-") - default: - p.err(n, "unsupported volatile declarator operation: %v", oper) - } - p.w("%d)", p.incDelta(n, d.Type())) - return - } - - panic(todo("", n.Position(), d.Position())) - default: - p.err(n, "unsupported volatile declarator size: %v", d.Type().Size()) - return - } - } - - pe := n.PostfixExpression.Operand.Type().Decay() - p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) - if pe.IsIntegerType() || pe.Kind() == cc.Ptr && p.incDelta(n, pe) == 1 { - p.w("%s", oper) - return - } - - switch pe.Kind() { - case cc.Ptr, cc.Float, cc.Double: - p.w("%s %d", oper2, p.incDelta(n, pe)) - return - } - - panic(todo("", n.Position(), pe, pe.Kind())) -} - -func (p *project) incDelta(n cc.Node, t cc.Type) uintptr { - if t.IsArithmeticType() { - return 1 - } - - if t.Kind() == cc.Ptr || t.Kind() == cc.Array { - return t.Elem().Size() - } - - panic(todo("", n.Position(), t.Kind())) -} - -func (p *project) bitFldOff(t cc.Type, tok cc.Token) { - var off uintptr - fld, ok := t.FieldByName(tok.Value) - switch { - case ok && !fld.IsBitField(): - panic(todo("%v: internal error: bitFdlOff must not be used with non bit fields", origin(2))) - case !ok: - p.err(&tok, "uknown field: %s", tok.Value) - default: - off = fld.BitFieldBlockFirst().Offset() - } - if off != 0 { - p.w("+%d", off) - } - p.w("/* &.%s */", tok.Value) -} - -func (p *project) fldOff(t cc.Type, tok cc.Token) { - if t.Kind() == cc.Ptr { - t = t.Elem() - } - var off uintptr - fld, ok := t.FieldByName(tok.Value) - switch { - case ok && fld.IsBitField(): - panic(todo("%v: internal error: fdlOff must not be used with bit fields", origin(2))) - case !ok: - p.err(&tok, "uknown field: %s", tok.Value) - default: - off = fld.Offset() - } - if off != 0 { - p.w("+%d", off) - } - p.w("/* &.%s */", tok.Value) -} - -func (p *project) postfixExpressionCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '(' ArgumentExpressionList ')' - switch mode { - case exprVoid: - p.postfixExpressionCallVoid(f, n, t, mode, flags) - case exprValue: - p.postfixExpressionCallValue(f, n, t, mode, flags) - case exprBool: - p.postfixExpressionCallBool(f, n, t, mode, flags) - default: - panic(todo("", mode)) - } -} - -func (p *project) postfixExpressionCallBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '(' ArgumentExpressionList ')' - p.w("(") - defer p.w(")") - defer p.w(" != 0") - if d := n.PostfixExpression.Declarator(); d != nil { - switch d.Name() { - case idVaArg: - if !f.vaType.IsScalarType() { - panic(todo("", f.vaType)) - } - - lhs := n.ArgumentExpressionList.AssignmentExpression - p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) - p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) - p.w(")") - return - case idAtomicLoadN: - p.atomicLoadN(f, n, t, mode, flags) - return - case idBuiltinConstantPImpl: - p.w("%v", n.Operand.Value()) - return - } - } - - var va uintptr - if f != nil { - va = f.vaLists[n] - } - p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) -} - -func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '(' ArgumentExpressionList ')' - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - if d := n.PostfixExpression.Declarator(); d != nil { - switch d.Name() { - case idVaEnd: - p.w("_ = ") - arg := n.ArgumentExpressionList.AssignmentExpression - p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) - return - case idVaStart: - lhs := n.ArgumentExpressionList.AssignmentExpression - p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) - p.w(" = %s", f.vaName) - return - case idVaArg: - if !f.vaType.IsScalarType() { - panic(todo("", f.vaType)) - } - - lhs := n.ArgumentExpressionList.AssignmentExpression - p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) - p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) - p.w(")") - return - case idAtomicLoadN: - p.atomicLoadN(f, n, t, mode, flags) - return - case idAddOverflow: - p.addOverflow(f, n, t, mode, flags) - return - case idSubOverflow: - p.subOverflow(f, n, t, mode, flags) - return - case idMulOverflow: - p.mulOverflow(f, n, t, mode, flags) - return - case idBuiltinConstantPImpl: - p.w("%v", n.Operand.Value()) - return - } - } - var va uintptr - if f != nil { - va = f.vaLists[n] - } - p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) -} - -// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) -func (p *project) mulOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - args := p.argList(n.ArgumentExpressionList) - if len(args) != 3 { - p.err(n, "expected 3 arguments in call to __builtin_mul_overflow") - return - } - - pt := args[2].Operand.Type() - if pt.Kind() != cc.Ptr { - p.err(n, "invalid argument of __builtin_mul_overflow (expected pointer): %s", pt) - return - } - - vt := pt.Elem() - switch { - case vt.IsIntegerType(): - switch vt.Size() { - case 1, 2, 4, 8, 16: - p.w("%sX__builtin_mul_overflow%s", p.task.crt, p.helperType(n, vt)) - default: - p.err(n, "invalid argument of __builtin_mul_overflow: %v, elem kind %v", pt, vt.Kind()) - return - } - p.w("(%s", f.tlsName) - types := []cc.Type{vt, vt, pt} - for i, v := range args[:3] { - p.w(", ") - p.assignmentExpression(f, v, types[i], exprValue, flags) - } - p.w(")") - return - } - - p.err(n, "invalid arguments of __builtin_mul_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) -} - -// bool __builtin_sub_overflow (type1 a, type2 b, type3 *res) -func (p *project) subOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - args := p.argList(n.ArgumentExpressionList) - if len(args) != 3 { - p.err(n, "expected 3 arguments in call to __builtin_sub_overflow") - return - } - - pt := args[2].Operand.Type() - if pt.Kind() != cc.Ptr { - p.err(n, "invalid argument of __builtin_sub_overflow (expected pointer): %s", pt) - return - } - - vt := pt.Elem() - switch { - case vt.IsIntegerType(): - switch vt.Size() { - case 1, 2, 4, 8: - p.w("%sX__builtin_sub_overflow%s", p.task.crt, p.helperType(n, vt)) - default: - p.err(n, "invalid argument of __builtin_sub_overflow: %v, elem kind %v", pt, vt.Kind()) - return - } - p.w("(%s", f.tlsName) - types := []cc.Type{vt, vt, pt} - for i, v := range args[:3] { - p.w(", ") - p.assignmentExpression(f, v, types[i], exprValue, flags) - } - p.w(")") - return - } - - p.err(n, "invalid arguments of __builtin_sub_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) -} - -// bool __builtin_add_overflow (type1 a, type2 b, type3 *res) -func (p *project) addOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - args := p.argList(n.ArgumentExpressionList) - if len(args) != 3 { - p.err(n, "expected 3 arguments in call to __builtin_add_overflow") - return - } - - pt := args[2].Operand.Type() - if pt.Kind() != cc.Ptr { - p.err(n, "invalid argument of __builtin_add_overflow (expected pointer): %s", pt) - return - } - - vt := pt.Elem() - switch { - case vt.IsIntegerType(): - switch vt.Size() { - case 1, 2, 4, 8: - p.w("%sX__builtin_add_overflow%s", p.task.crt, p.helperType(n, vt)) - default: - p.err(n, "invalid argument of __builtin_add_overflow: %v, elem kind %v", pt, vt.Kind()) - return - } - p.w("(%s", f.tlsName) - types := []cc.Type{vt, vt, pt} - for i, v := range args[:3] { - p.w(", ") - p.assignmentExpression(f, v, types[i], exprValue, flags) - } - p.w(")") - return - } - - p.err(n, "invalid arguments of __builtin_add_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) -} - -// type __atomic_load_n (type *ptr, int memorder) -func (p *project) atomicLoadN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - args := p.argList(n.ArgumentExpressionList) - if len(args) != 2 { - p.err(n, "expected 2 arguments in call to __atomic_load_n") - return - } - - pt := args[0].Operand.Type() - if pt.Kind() != cc.Ptr { - p.err(n, "invalid argument of __atomic_load_n (expected pointer): %s", pt) - return - } - - vt := pt.Elem() - switch { - case vt.IsIntegerType(): - var s string - switch { - case vt.IsSignedType(): - s = "Int" - default: - s = "Uint" - } - switch vt.Size() { - case 2, 4, 8: - p.w("%sAtomicLoadN%s%d", p.task.crt, s, 8*vt.Size()) - default: - p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) - return - } - types := []cc.Type{pt, p.intType} - p.w("(") - for i, v := range args[:2] { - if i != 0 { - p.w(", ") - } - p.assignmentExpression(f, v, types[i], exprValue, flags) - } - p.w(")") - return - case vt.Kind() == cc.Ptr: - panic(todo("", pt, vt)) - } - - p.err(n, "invalid first argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) -} - -func (p *project) postfixExpressionCallVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - // PostfixExpression '(' ArgumentExpressionList ')' - if d := n.PostfixExpression.Declarator(); d != nil { - switch d.Name() { - case idVaEnd: - p.w("_ = ") - arg := n.ArgumentExpressionList.AssignmentExpression - p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) - return - case idVaStart: - lhs := n.ArgumentExpressionList.AssignmentExpression - p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) - p.w(" = %s", f.vaName) - return - case idVaArg: - if !f.vaType.IsScalarType() { - panic(todo("", f.vaType)) - } - - lhs := n.ArgumentExpressionList.AssignmentExpression - p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) - p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) - p.w(")") - return - case idAtomicStoreN: - p.atomicStoreN(f, n, t, mode, flags) - return - case idMulOverflow: - p.mulOverflow(f, n, t, mode, flags) - return - } - } - var va uintptr - if f != nil { - va = f.vaLists[n] - } - p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) - p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) -} - -// void __atomic_store_n (type *ptr, type val, int memorder) -func (p *project) atomicStoreN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { - args := p.argList(n.ArgumentExpressionList) - if len(args) != 3 { - p.err(n, "expected 3 arguments in call to __atomic_store_n") - return - } - - pt := args[0].Operand.Type() - if pt.Kind() != cc.Ptr { - p.err(n, "invalid first argument of __atomic_store_n (expected pointer): %s", pt) - return - } - - vt := args[1].Operand.Type() - switch { - case vt.IsIntegerType(): - var s string - switch { - case vt.IsSignedType(): - s = "Int" - default: - s = "Uint" - } - switch vt.Size() { - case 2, 4, 8: - p.w("%sAtomicStoreN%s%d", p.task.crt, s, 8*vt.Size()) - default: - p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) - return - } - p.w("(") - types := []cc.Type{pt, vt, p.intType} - for i, v := range args[:3] { - if i != 0 { - p.w(", ") - } - if i == 1 { - p.w("%s(", strings.ToLower(p.helperType(n, vt))) - } - p.assignmentExpression(f, v, types[i], exprValue, flags) - if i == 1 { - p.w(")") - } - } - p.w(")") - return - case vt.Kind() == cc.Ptr: - panic(todo("", pt, vt)) - } - - p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) -} - -func (p *project) argList(n *cc.ArgumentExpressionList) (r []*cc.AssignmentExpression) { - for ; n != nil; n = n.ArgumentExpressionList { - r = append(r, n.AssignmentExpression) - } - return r -} - -func (p *project) argumentExpressionList(f *function, pe *cc.PostfixExpression, n *cc.ArgumentExpressionList, bpOff uintptr) { - switch { - case f == nil: - p.w("(nil") - default: - p.w("(%s", f.tlsName) - } - ft := funcType(pe.Operand.Type()) - isVariadic := ft.IsVariadic() - params := ft.Parameters() - if len(params) == 1 && params[0].Type().Kind() == cc.Void { - params = nil - } - var args []*cc.AssignmentExpression - for ; n != nil; n = n.ArgumentExpressionList { - args = append(args, n.AssignmentExpression) - } - if len(args) < len(params) { - panic(todo("", p.pos(n))) - } - - va := true - if len(args) > len(params) && !isVariadic { - var a []string - for _, v := range args { - a = append(a, v.Operand.Type().String()) - } - sargs := strings.Join(a, ",") - switch d := pe.Declarator(); { - case d == nil: - p.err(pe, "too many arguments (%s) in call to %s", sargs, ft) - default: - p.err(pe, "too many arguments (%s) in call to %s of type %s", sargs, d.Name(), ft) - } - va = false - } - - paren := "" - for i, arg := range args { - p.w(",%s", tidyComment(" ", arg)) - mode := exprValue - if at := arg.Operand.Type(); at.Kind() == cc.Array { - mode = exprDecay - } - switch { - case i < len(params): - switch pt := params[i].Type(); { - case isTransparentUnion(params[i].Type()): - p.callArgTransparentUnion(f, arg, pt) - default: - p.assignmentExpression(f, arg, arg.Promote(), mode, 0) - } - case va && i == len(params): - p.w("%sVaList(%s%s, ", p.task.crt, f.bpName, nonZeroUintptr(bpOff)) - paren = ")" - fallthrough - default: - var flags flags - if arg.Promote().IsIntegerType() { - switch x := arg.Operand.Value().(type) { - case cc.Int64Value: - if x < mathutil.MinInt || x > mathutil.MaxInt { - flags |= fForceConv - } - case cc.Uint64Value: - if x > mathutil.MaxInt { - flags |= fForceConv - } - } - } - p.assignmentExpression(f, arg, arg.Promote(), mode, flags) - } - } - if isVariadic && len(args) == len(params) { - p.w(", 0") - } - p.w("%s)", paren) -} - -// https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html -// -// transparent_union -// -// This attribute, attached to a union type definition, indicates that any -// function parameter having that union type causes calls to that function to -// be treated in a special way. -// -// First, the argument corresponding to a transparent union type can be of any -// type in the union; no cast is required. Also, if the union contains a -// pointer type, the corresponding argument can be a null pointer constant or a -// void pointer expression; and if the union contains a void pointer type, the -// corresponding argument can be any pointer expression. If the union member -// type is a pointer, qualifiers like const on the referenced type must be -// respected, just as with normal pointer conversions. -// -// Second, the argument is passed to the function using the calling conventions -// of first member of the transparent union, not the calling conventions of the -// union itself. All members of the union must have the same machine -// representation; this is necessary for this argument passing to work -// properly. -// -// Transparent unions are designed for library functions that have multiple -// interfaces for compatibility reasons. For example, suppose the wait function -// must accept either a value of type int * to comply with Posix, or a value of -// type union wait * to comply with the 4.1BSD interface. If wait's parameter -// were void *, wait would accept both kinds of arguments, but it would also -// accept any other pointer type and this would make argument type checking -// less useful. Instead, <sys/wait.h> might define the interface as follows: -// -// typedef union -// { -// int *__ip; -// union wait *__up; -// } wait_status_ptr_t __attribute__ ((__transparent_union__)); -// -// pid_t wait (wait_status_ptr_t); -// -// This interface allows either int * or union wait * arguments to be passed, -// using the int * calling convention. The program can call wait with arguments -// of either type: -// -// int w1 () { int w; return wait (&w); } -// int w2 () { union wait w; return wait (&w); } -// -// With this interface, wait's implementation might look like this: -// -// pid_t wait (wait_status_ptr_t p) -// { -// return waitpid (-1, p.__ip, 0); -// } -func (p *project) callArgTransparentUnion(f *function, n *cc.AssignmentExpression, pt cc.Type) { - if pt.Kind() != cc.Union { - panic(todo("internal error")) - } - - ot := n.Operand.Type() - switch k := pt.UnionCommon(); k { - case cc.Ptr: - if ot.Kind() != k { - panic(todo("", n.Position(), k, pt)) - } - - p.assignmentExpression(f, n, ot, exprValue, 0) - default: - panic(todo("", n.Position(), k, pt)) - } -} - -func isTransparentUnion(t cc.Type) (r bool) { - for _, v := range attrs(t) { - cc.Inspect(v, func(n cc.Node, _ bool) bool { - if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idTransparentUnion { - r = true - return false - } - - return true - }) - } - return r -} - -func attrs(t cc.Type) []*cc.AttributeSpecifier { - if a := t.Attributes(); len(a) != 0 { - return a - } - - if t.IsAliasType() { - if a := t.Alias().Attributes(); len(a) != 0 { - return a - } - - return t.AliasDeclarator().Type().Attributes() - } - - return nil -} - -func (p *project) nzUintptr(n cc.Node, f func(), op cc.Operand) { - if op.Type().IsIntegerType() { - switch { - case op.IsZero(): - return - case op.Value() != nil: - switch x := op.Value().(type) { - case cc.Int64Value: - if x > 0 && uint64(x) <= 1<<(8*p.ptrSize)-1 { - p.w("+%d", x) - return - } - case cc.Uint64Value: - if uint64(x) <= 1<<(8*p.ptrSize)-1 { - p.w("+%d", x) - return - } - } - - p.w(" +%sUintptrFrom%s(", p.task.crt, p.helperType(n, op.Type())) - default: - p.w(" +uintptr(") - } - - f() - p.w(")") - return - } - - panic(todo("", p.pos(n))) -} - -func (p *project) primaryExpression(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { - switch mode { - case exprLValue: - p.primaryExpressionLValue(f, n, t, mode, flags) - case exprValue: - p.primaryExpressionValue(f, n, t, mode, flags) - case exprFunc: - p.primaryExpressionFunc(f, n, t, mode, flags) - case exprAddrOf: - p.primaryExpressionAddrOf(f, n, t, mode, flags) - case exprSelect: - p.primaryExpressionSelect(f, n, t, mode, flags) - case exprPSelect: - p.primaryExpressionPSelect(f, n, t, mode, flags) - case exprBool: - p.primaryExpressionBool(f, n, t, mode, flags) - case exprVoid: - p.primaryExpressionVoid(f, n, t, mode, flags) - case exprDecay: - p.primaryExpressionDecay(f, n, t, mode, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) primaryExpressionDecay(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: - p.declarator(n, f, d, t, mode, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - p.w("%s", p.stringLiteral(n.Operand.Value())) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - 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 ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionVoid(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { - - switch n.Case { - case cc.PrimaryExpressionIdent: // IDENTIFIER - p.w("_ = ") - p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) - case cc.PrimaryExpressionInt, // INTCONST - cc.PrimaryExpressionFloat, // FLOATCONST - cc.PrimaryExpressionEnum, // ENUMCONST - cc.PrimaryExpressionChar, // CHARCONST - cc.PrimaryExpressionLChar, // LONGCHARCONST - cc.PrimaryExpressionString, // STRINGLITERAL - cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - - // nop - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.compoundStatement(f, n.CompoundStatement, "", true, false, 0) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionBool(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { - if n.Case != cc.PrimaryExpressionExpr { - p.w("(") - defer p.w(")") - } - - if n.Case != cc.PrimaryExpressionExpr { - defer p.w(" != 0") - } - switch n.Case { - case cc.PrimaryExpressionIdent: // IDENTIFIER - switch d := n.Declarator(); { - case d != nil: - p.declarator(n, f, d, d.Type(), exprValue, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - p.intConst(n, n.Token.Src.String(), n.Operand, n.Operand.Type(), flags) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionString: // STRINGLITERAL - p.w(" 1 ") - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.w("(") - defer p.w(")") - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.w("func() %v {", p.typ(n, n.CompoundStatement.Operand.Type())) - p.compoundStatement(f, n.CompoundStatement, "", true, false, exprValue) - p.w("}()") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionPSelect(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 k := p.declaratorKind(d); k { - case opArray: - panic(todo("", p.pos(n))) - p.primaryExpression(f, n, t, exprDecay, flags) - default: - p.declarator(n, f, d, t, mode, flags) - } - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionSelect(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: - p.declarator(n, f, d, t, mode, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionAddrOf(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: - p.declarator(n, f, d, t, mode, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - p.w("%s", p.stringLiteral(n.Operand.Value())) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - 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 ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) primaryExpressionFunc(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { - switch n.Case { - case cc.PrimaryExpressionIdent: // IDENTIFIER - 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 - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func cmpNormalizeValue(v cc.Value) cc.Value { - switch x := v.(type) { - case cc.Int64Value: - if x >= 0 { - return cc.Uint64Value(x) - } - } - return v -} - -func (p *project) primaryExpressionValue(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: - p.declarator(n, f, d, t, mode, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - if m := n.Token.Macro(); m != 0 { - if d := p.defines[m]; d.name != "" { - if cmpNormalizeValue(n.Operand.Value()) == cmpNormalizeValue(d.value) { - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w(" %s ", d.name) - break - } - - p.w("/* %s */", m) - } - } - - p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionFloat: // FLOATCONST - //TODO use #define - p.floatConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionEnum: // ENUMCONST - en := n.ResolvedTo().(*cc.Enumerator) - if n.ResolvedIn().Parent() == nil { - if nm := p.enumConsts[en.Token.Value]; nm != "" { - p.w(" %s ", nm) - break - } - } - - p.intConst(n, "", n.Operand, t, flags) - p.w("/* %s */", en.Token.Value) - case cc.PrimaryExpressionChar: // CHARCONST - p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) - case cc.PrimaryExpressionString: // STRINGLITERAL - p.w("%s", p.stringLiteral(n.Operand.Value())) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.w("(") - defer p.w(")") - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.statementExpression(f, n.CompoundStatement, t, mode, flags) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) statementExpression(f *function, n *cc.CompoundStatement, t cc.Type, mode exprMode, flags flags) { - defer p.w("%s", p.convert(n, n.Operand, t, flags)) - p.w(" func() %v {", p.typ(n, n.Operand.Type())) - p.compoundStatement(f, n, "", true, false, mode) - p.w("}()") -} - -func (p *project) primaryExpressionLValue(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: - p.declarator(n, f, d, t, mode, flags) - default: - panic(todo("", p.pos(n))) - } - case cc.PrimaryExpressionInt: // INTCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionFloat: // FLOATCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionEnum: // ENUMCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionChar: // CHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLChar: // LONGCHARCONST - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionString: // STRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL - panic(todo("", p.pos(n))) - case cc.PrimaryExpressionExpr: // '(' Expression ')' - p.w("(") - defer p.w(")") - p.expression(f, n.Expression, t, mode, flags) - case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' - p.err(n, "statement expressions not supported") - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) stringLiteralString(s string) string { - if p.pass1 { - return "" - } - - id := cc.String(s) - off, ok := p.tsOffs[id] - if !ok { - off = uintptr(p.ts.Len()) - p.ts.WriteString(s) - p.ts.WriteByte(0) - p.tsOffs[id] = off - } - return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) -} - -func (p *project) stringLiteral(v cc.Value) string { - if p.pass1 { - return "" - } - - switch x := v.(type) { - case cc.StringValue: - id := cc.StringID(x) - off, ok := p.tsOffs[id] - s := id.String() - if !ok { - off = uintptr(p.ts.Len()) - p.ts.WriteString(s) - p.ts.WriteByte(0) - p.tsOffs[id] = off - } - return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) - default: - panic(todo("%T", x)) - } -} - -func (p *project) stringSnippet(s string) string { - s = strings.ReplaceAll(s, "*/", "*\\/") - const max = 16 - switch { - case len(s) <= max: - return fmt.Sprintf("/* %q */", s) - default: - return fmt.Sprintf("/* %q */", s[:16]+"...") - } -} - -func (p *project) wideStringLiteral(v cc.Value, pad int) string { - if p.pass1 { - return "" - } - - switch x := v.(type) { - case cc.WideStringValue: - id := cc.StringID(x) - off, ok := p.tsWOffs[id] - if !ok { - off = p.wcharSize * uintptr(len(p.tsW)) - s := []rune(id.String()) - if pad != 0 { - s = append(s, make([]rune, pad)...) - } - p.tsW = append(p.tsW, s...) - p.tsW = append(p.tsW, 0) - p.tsWOffs[id] = off - } - return fmt.Sprintf("(%s%s)", p.tsWNameP, nonZeroUintptr(off)) - default: - panic(todo("%T", x)) - } -} - -func (p *project) charConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { - switch { - case to.IsArithmeticType(): - 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())) - } - - r, mb, _, err := strconv.UnquoteChar(src[1:len(src)-1], '\'') - rValid := !mb && err == nil - var on uint64 - switch x := op.Value().(type) { - case cc.Int64Value: - on = uint64(x) - case cc.Uint64Value: - on = uint64(x) - default: - panic(todo("%T(%v)", x, x)) - } - var mask uint64 - switch { - case !to.IsIntegerType(): - // ok - if rValid { // Prefer original form - p.w("%s", src) - return - } - - p.w("%d", on) - return - case to.IsSignedType(): - var in int64 - var ok bool - switch to.Size() { - case 1: - in = int64(int8(on)) - ok = int8(on) >= 0 - case 2: - in = int64(int16(on)) - ok = int16(on) >= 0 - case 4: - in = int64(int32(on)) - ok = int32(on) >= 0 - case 8: - in = int64(int64(on)) - ok = in >= 0 - default: - panic(todo("", op.Type().Size())) - } - if ok && rValid && uint64(in) == on { // Prefer original form - p.w("%s", src) - return - } - - p.w("%d", in) - default: - switch to.Size() { - case 1: - mask = 0xff - case 2: - mask = 0xffff - case 4: - mask = 0xffffffff - case 8: - mask = 0xffffffffffffffff - default: - panic(todo("", op.Type().Size())) - } - if rValid && uint64(r)&mask == on { // Prefer original form - p.w("%s", src) - return - } - - p.w("%d", on&mask) - } -} - -func (p *project) floatConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { - if flags&fForceRuntimeConv != 0 { - p.w("%s(", p.helperType2(n, op.Type(), to)) - defer p.w(")") - } - - bits := 64 - switch to.Kind() { - case cc.Float: - bits = 32 - } - src = strings.TrimRight(src, "flFL") - sn, err := strconv.ParseFloat(src, bits) - snValid := err == nil - switch x := op.Value().(type) { - case cc.Float64Value: - switch to.Kind() { - case cc.Double: - if snValid && sn == float64(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) - case cc.Float: - if snValid && float32(sn) == float32(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) - default: - defer p.w("%s", p.convert(n, op, to, 0)) - if snValid && sn == float64(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) - } - case cc.Float32Value: - switch to.Kind() { - case cc.Double: - if snValid && float32(sn) == float32(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) - case cc.Float: - if snValid && float32(sn) == float32(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) - default: - if to.IsIntegerType() { - if s := p.float2Int(n, x, to); s != "" { - defer p.w("%s%s", s, p.convertType(n, op.Type(), to, 0)) - break - } - } - - defer p.w("%s", p.convert(n, op, to, 0)) - if snValid && float32(sn) == float32(x) { // Prefer original form. - p.w("%s", src) - return - } - - p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) - } - default: - panic(todo("%T(%v)", x, x)) - } -} - -func (p *project) float2Int(n cc.Node, x cc.Float32Value, to cc.Type) string { - switch { - case to.IsSignedType(): - limits := &signedSaturationLimits[to.Size()] - v := float64(x) - switch { - case math.IsNaN(v): - panic(todo("", p.pos(n))) - case math.IsInf(v, -1): - panic(todo("", p.pos(n))) - case math.IsInf(v, 1): - panic(todo("", p.pos(n))) - case v < limits.fmin: - return fmt.Sprint(limits.min) - case v > limits.fmax: - return fmt.Sprint(limits.max) - } - default: - limits := &unsignedSaturationLimits[to.Size()] - v := float64(x) - switch { - case math.IsNaN(v): - panic(todo("", p.pos(n))) - case math.IsInf(v, -1): - panic(todo("", p.pos(n))) - case math.IsInf(v, 1): - panic(todo("", p.pos(n))) - case v < 0: - return "0" - case v > limits.fmax: - return fmt.Sprint(limits.max) - } - } - return "" -} - -type signedSaturationLimit struct { - fmin, fmax float64 - min, max int64 -} - -type unsignedSaturationLimit struct { - fmax float64 - max uint64 -} - -var ( - signedSaturationLimits = [...]signedSaturationLimit{ - 1: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, - 2: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, - 4: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, - 8: {math.Nextafter(math.MinInt64, 0), math.Nextafter(math.MaxInt64, 0), math.MinInt64, math.MaxInt64}, - } - - unsignedSaturationLimits = [...]unsignedSaturationLimit{ - 1: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, - 2: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, - 4: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, - 8: {math.Nextafter(math.MaxUint64, 0), math.MaxUint64}, - } -) - -func (p *project) intConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { - ptr := to.Kind() == cc.Ptr - switch { - case to.IsArithmeticType(): - // p.w("/*10568 %T(%#[1]x) %v -> %v */", op.Value(), op.Type(), to) //TODO- - if flags&fForceNoConv != 0 { - break - } - - if !op.Type().IsSignedType() && op.Type().Size() == 8 && op.Value().(cc.Uint64Value) > math.MaxInt64 { - flags |= fForceRuntimeConv - } - defer p.w("%s", p.convert(n, op, to, flags)) - case ptr: - p.w(" uintptr(") - defer p.w(")") - // ok - default: - panic(todo("%v: %v -> %v", p.pos(n), op.Type(), to)) - } - - src = strings.TrimRight(src, "luLU") - sn, err := strconv.ParseUint(src, 0, 64) - snValid := err == nil - var on uint64 - switch x := op.Value().(type) { - case cc.Int64Value: - if x < 0 { - sn, err := strconv.ParseInt(src, 0, 64) - snValid := err == nil - if snValid && sn == int64(x) { // Prefer original form - p.w("%s", src) - return - } - - p.w("%d", x) - return - } - - on = uint64(x) - case cc.Uint64Value: - on = uint64(x) - default: - panic(todo("%T(%v)", x, x)) - } - - if snValid && sn == on { // Prefer original form - p.w("%s", src) - return - } - - p.w("%d", on) -} - -func (p *project) assignShiftOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - // UnaryExpression "<<=" AssignmentExpression etc. - switch mode { - case exprVoid: - p.assignShiftOpVoid(f, n, t, mode, oper, oper2, flags) - default: - panic(todo("", mode)) - } -} - -func (p *project) assignShiftOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - // UnaryExpression "<<=" AssignmentExpression etc. - switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { - case opNormal: - p.assignShiftOpVoidNormal(f, n, t, mode, oper, oper2, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) assignShiftOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - switch { - case n.Operand.Type().IsBitFieldType(): - panic(todo("", p.pos(n))) - default: - if d := n.UnaryExpression.Declarator(); d != nil { - switch d.Type().Kind() { - case cc.Int128, cc.UInt128: - p.declarator(n, f, d, d.Type(), exprLValue, flags) - p.w(".LValue%s(", oper2) - p.assignmentExpression(f, n.AssignmentExpression, p.intType, exprValue, flags) - p.w(")") - return - default: - p.declarator(n, f, d, d.Type(), exprLValue, flags) - p.w(" %s= ", oper) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - return - } - } - - lhs := n.UnaryExpression - switch { - case lhs.Operand.Type().IsArithmeticType(): - p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) - p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) - p.w(", int(") - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w("))") - default: - panic(todo("", p.pos(n), lhs.Operand.Type())) - } - } -} - -func (p *project) assignOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - switch mode { - case exprVoid: - p.assignOpVoid(f, n, t, mode, oper, oper2, flags) - case exprValue, exprCondReturn: - p.assignOpValue(f, n, t, mode, oper, oper2, flags) - default: - panic(todo("", n.Position(), mode)) - } -} - -func (p *project) assignOpValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { - case opNormal: - p.assignOpValueNormal(f, n, t, oper, oper2, mode, flags) - case opBitfield: - p.assignOpValueBitfield(f, n, t, oper, oper2, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - - asInt := oper2 == "Shl" || oper2 == "Shr" - if asInt { - panic(todo("")) - } - - ot := n.Operand.Type() - lhs := n.UnaryExpression - bf := lhs.Operand.Type().BitField() - defer p.w("%s", p.convertType(n, ot, t, flags)) - p.w(" func() %v {", p.typ(n, ot)) - switch lhs.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - pe := n.UnaryExpression.PostfixExpression - switch pe.Case { - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - p.w("__p := ") - p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) - p.w("; __v := ") - p.readBitfield(lhs, "__p", bf, ot) - p.w(" %s (", oper) - p.assignmentExpression(f, n.AssignmentExpression, ot, exprValue, flags) - p.w("); return %sAssignBitFieldPtr%d%s(__p, __v, %d, %d, %#x)", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(ot), bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - panic(todo("", p.pos(n))) - default: - panic(todo("", n.Position(), pe.Case)) - } - default: - panic(todo("", n.Position(), lhs.Case)) - } - p.w("}()") -} - -func (p *project) readBitfield(n cc.Node, ptr string, bf cc.Field, promote cc.Type) { - bw := bf.BitFieldBlockWidth() - m := bf.Mask() - o := bf.BitFieldOffset() - w := bf.BitFieldWidth() - p.w("(%s(*(*uint%d)(unsafe.Pointer(%s))&%#x)", p.typ(n, promote), bw, ptr, m) - switch { - case bf.Type().IsSignedType(): - bits := int(promote.Size()) * 8 - p.w("<<%d>>%d)", bits-w-o, bits-w) - default: - p.w(">>%d)", o) - } -} - -func (p *project) assignOpValueNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - if mode == exprCondReturn { - p.w("return ") - } - asInt := oper2 == "Shl" || oper2 == "Shr" - lhs := n.UnaryExpression - // UnaryExpression "*=" AssignmentExpression etc. - if d := lhs.Declarator(); d != nil { - if local := f.locals[d]; local != nil && local.isPinned { - switch { - case lhs.Operand.Type().IsArithmeticType(): - defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) - p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) - p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) - p.w(", ") - if asInt { - p.w("int(") - } - p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) - if asInt { - p.w(")") - } - p.w(")") - default: - panic(todo("", lhs.Operand.Type())) - } - return - } - - switch { - case d.Type().Kind() == cc.Ptr: - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) - p.declarator(n, f, d, d.Type(), exprLValue, flags) - p.w(", ") - if dd := p.incDelta(d, d.Type()); dd != 1 { - p.w("%d*(", dd) - defer p.w(")") - } - p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) - p.w(")") - case d.Type().IsArithmeticType(): - defer p.w("%s", p.convertType(n, d.Type(), t, flags)) - p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) - p.declarator(n, f, d, d.Type(), exprLValue, flags) - p.w(", ") - if asInt { - p.w("int(") - } - p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) - p.w(")") - if asInt { - p.w(")") - } - default: - panic(todo("", p.pos(n), p.pos(d), d.Name())) - } - return - } - - switch { - case lhs.Operand.Type().IsArithmeticType(): - defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) - p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) - p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) - p.w(", ") - if asInt { - p.w("int(") - } - p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) - if asInt { - p.w(")") - } - p.w(")") - default: - panic(todo("", lhs.Operand.Type())) - } -} - -func (p *project) assignOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { - case opNormal: - p.assignOpVoidNormal(f, n, t, oper, oper2, mode, flags) - case opBitfield: - p.assignOpVoidBitfield(f, n, t, oper, oper2, mode, flags) - case opArrayParameter: - p.assignOpVoidArrayParameter(f, n, t, oper, oper2, mode, flags) - default: - panic(todo("", n.Position(), k)) - } -} - -func (p *project) assignOpVoidArrayParameter(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - if oper != "+" && oper != "-" { - panic(todo("", p.pos(n))) - } - - d := n.UnaryExpression.Declarator() - switch local := f.locals[d]; { - case local != nil && local.isPinned: - p.w("*(*uintptr)(unsafe.Pointer(%s%s))", f.bpName, nonZeroUintptr(local.off)) - default: - p.declarator(n, f, d, d.Type(), exprLValue, flags) - } - - p.w(" %s= ", oper) - if dd := p.incDelta(d, d.Type()); dd != 1 { - p.w("%d*", dd) - } - p.w("uintptr(") - p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) - p.w(")") -} - -func (p *project) assignOpVoidBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - lhs := n.UnaryExpression - lt := lhs.Operand.Type() - switch lhs.Case { - case cc.UnaryExpressionPostfix: // PostfixExpression - pe := n.UnaryExpression.PostfixExpression - switch pe.Case { - case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER - bf := lt.BitField() - p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(n.Promote())) - p.unaryExpression(f, lhs, lt, exprAddrOf, flags) - p.w(", (") - s := p.convertType(n, lt, n.Promote(), flags) - p.unaryExpression(f, lhs, lt, exprValue, flags) - p.w(")%s %s ", s, oper) - s = p.convertType(n, lt, n.Promote(), flags) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w("%s", s) - p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) - case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER - switch d := pe.PostfixExpression.Declarator(); { - case d != nil: - panic(todo("", p.pos(n))) - default: - panic(todo("", p.pos(n))) - } - default: - panic(todo("", n.Position(), pe.Case)) - } - default: - panic(todo("", n.Position(), lhs.Case)) - } -} - -func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { - // UnaryExpression "*=" AssignmentExpression etc. - rop := n.AssignmentExpression.Operand - if d := n.UnaryExpression.Declarator(); d != nil { - if local := f.locals[d]; local != nil && local.isPinned { - if p.isVolatileOrAtomic(d) { - panic(todo("")) - } - - p.declarator(n, f, d, d.Type(), exprLValue, flags) - switch { - case d.Type().Kind() == cc.Ptr: - p.w(" %s= ", oper) - if dd := p.incDelta(d, d.Type()); dd != 1 { - p.w("%d*(", dd) - defer p.w(")") - } - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - case d.Type().IsArithmeticType(): - p.w(" %s= ", oper) - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - default: - panic(todo("", n.Position(), d.Type().Kind())) - } - return - } - - if p.isVolatileOrAtomic(d) { - var local *local - var tld *tld - var nm string - if f != nil { - if local = f.locals[d]; local != nil { - nm = local.name - } - } - - if local == nil { - if tld = p.tlds[d]; tld == nil { - p.err(n, "%v: internal error (%v: %v)", n.Position(), d.Position(), d.Name()) - return - } - - nm = tld.name - } - var sign string - switch oper { - case "-": - sign = oper - fallthrough - case "+": - sz := d.Type().Size() - var ht string - switch sz { - case 4, 8: - if !d.Type().IsScalarType() { - p.err(n, "unsupported volatile declarator type: %v", d.Type()) - break - } - - ht = p.helperType(n, d.Type()) - default: - p.err(n, "unsupported volatile declarator size: %v", sz) - return - } - - if local != nil { - if local.isPinned { - panic(todo("")) - } - } - - p.w("%sAtomicAdd%s(&%s, %s%s(", p.task.crt, ht, nm, sign, p.typ(n, d.Type())) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w("))") - return - default: - p.warn(n, "unsupported volatile declarator operation: %v", oper) - p.w("%s = ", nm) - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) - p.declarator(n, f, d, n.Promote(), exprValue, flags) - p.w(" %s (", oper) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w(")") - return - } - } - - p.declarator(n, f, d, d.Type(), exprLValue, flags) - switch d.Type().Kind() { - case cc.Ptr: - if oper != "+" && oper != "-" { - panic(todo("", p.pos(n))) - } - - p.w(" %s= ", oper) - if dd := p.incDelta(d, d.Type()); dd != 1 { - p.w("%d*(", dd) - defer p.w(")") - } - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - case cc.Int128, cc.UInt128: - p.w(" = ") - p.declarator(n, f, d, n.Promote(), exprValue, flags) - p.w(".%s(", oper2) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w(")") - default: - p.w(" = ") - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) - p.declarator(n, f, d, n.Promote(), exprValue, flags) - p.w(" %s (", oper) - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w(")") - } - return - } - - lhs := n.UnaryExpression - switch { - case lhs.Operand.Type().IsArithmeticType(): - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) - p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) - p.w(")) %s= ", oper) - defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), lhs.Operand.Type(), flags)) - p.w("(") - p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) - p.w(")") - case lhs.Operand.Type().Kind() == cc.Ptr: - p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) - p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) - p.w(")) %s= (", oper) - p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) - p.w(")") - if dd := p.incDelta(n, lhs.Operand.Type()); dd != 1 { - p.w("*%d", dd) - } - default: - panic(todo("", lhs.Operand.Type())) - } -} - -func (p *project) warn(n cc.Node, s string, args ...interface{}) { - s = fmt.Sprintf(s, args...) - s = strings.TrimRight(s, "\t\n\r") - fmt.Fprintf(os.Stderr, "%v: warning: %s\n", n.Position(), s) -} - -func (p *project) iterationStatement(f *function, n *cc.IterationStatement) { - sv := f.switchCtx - sv2 := f.continueCtx - sv3 := f.breakCtx - f.switchCtx = 0 - f.continueCtx = 0 - f.breakCtx = 0 - defer func() { - f.breakCtx = sv3 - f.continueCtx = sv2 - f.switchCtx = sv - }() - p.w("%s", tidyComment("\n", n)) - switch n.Case { - case cc.IterationStatementWhile: // "while" '(' Expression ')' Statement - if f.hasJumps { - // a: if !expr goto b - // stmt - // goto a - // b: - a := f.flatLabel() - b := f.flatLabel() - f.continueCtx = a - f.breakCtx = b - p.w("__%d: if !(", a) - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.w(") { goto __%d };", b) - p.statement(f, n.Statement, false, false, false, 0) - p.w("; goto __%d; __%d:", a, b) - break - } - - p.w("for ") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.statement(f, n.Statement, true, false, false, 0) - case cc.IterationStatementDo: // "do" Statement "while" '(' Expression ')' ';' - if f.hasJumps { - // a: stmt - // b: if expr goto a // b is the continue label - // c: - a := f.flatLabel() - b := f.flatLabel() - c := f.flatLabel() - f.continueCtx = b - f.breakCtx = c - p.w("__%d:", a) - p.statement(f, n.Statement, false, false, false, 0) - p.w(";goto __%d; __%[1]d: if ", b) - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.w("{goto __%d};goto __%d;__%[2]d:", a, c) - break - } - - v := "__ccgo" - if !p.pass1 { - v = f.scope.take(cc.String(v)) - } - p.w("for %v := true; %[1]v; %[1]v = ", v) - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.statement(f, n.Statement, true, false, false, 0) - case cc.IterationStatementFor: // "for" '(' Expression ';' Expression ';' Expression ')' Statement - if f.hasJumps || n.Expression3 != nil && n.Expression3.Case == cc.ExpressionComma { - // expr - // a: if !expr2 goto c - // stmt - // b: expr3 // label for continue - // goto a - // c: - a := f.flatLabel() - b := f.flatLabel() - f.continueCtx = b - c := f.flatLabel() - f.breakCtx = c - if n.Expression != nil { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) - } - semi := "" - if n.Expression != nil || n.Expression2 != nil || n.Expression3 != nil { - semi = ";" - } - p.w("%s__%d:", semi, a) - if n.Expression2 != nil { - p.w("if !(") - p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) - p.w(") { goto __%d }", c) - } - p.w("%s", semi) - p.statement(f, n.Statement, false, false, false, 0) - p.w(";goto __%d; __%[1]d:", b) - if n.Expression3 != nil { - p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) - } - p.w("%sgoto __%d; goto __%d;__%[3]d:", semi, a, c) - break - } - - expr := true - if n.Expression != nil && n.Expression.Case == cc.ExpressionComma { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) - p.w(";") - expr = false - } - p.w("for ") - if expr && n.Expression != nil { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) - } - p.w("; ") - if n.Expression2 != nil { - p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) - } - p.w("; ") - if n.Expression3 != nil { - p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) - } - p.statement(f, n.Statement, true, false, false, 0) - case cc.IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement - if !(f.hasJumps || n.Expression2 != nil && n.Expression2.Case == cc.ExpressionComma) { - p.w("{") - p.declaration(f, n.Declaration, false) - p.w("for ;") - if n.Expression != nil { - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - } - p.w(";") - if n.Expression2 != nil { - p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment) - } - p.w("{") - p.statement(f, n.Statement, false, true, false, 0) - p.w("}};") - break - } - - var ids []*cc.InitDeclarator - for list := n.Declaration.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { - ids = append(ids, list.InitDeclarator) - } - - // 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, 0) - p.w(") { goto __%d }", c) - } - 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, fNoCondAssignment) - } - p.w("; goto __%d; goto __%d;__%[2]d:\n}", a, c) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) selectionStatement(f *function, n *cc.SelectionStatement) { - p.w("%s", tidyComment("\n", n)) - switch n.Case { - case cc.SelectionStatementIf: // "if" '(' Expression ')' Statement - sv := f.ifCtx - f.ifCtx = n - defer func() { f.ifCtx = sv }() - if f.hasJumps { - // if !expr goto a - // stmt - // a: - f.ifCtx = n - a := f.flatLabel() - p.w("if !(") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.w(") { goto __%d };", a) - p.statement(f, n.Statement, false, false, false, 0) - p.w(";__%d: ", a) - break - } - - p.w("if ") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.statement(f, n.Statement, true, false, false, 0) - case cc.SelectionStatementIfElse: // "if" '(' Expression ')' Statement "else" Statement - sv := f.ifCtx - f.ifCtx = n - defer func() { f.ifCtx = sv }() - if f.hasJumps { - // if !expr goto a - // stmt - // goto b - // a: - // stmt2 - // b: - a := f.flatLabel() - b := f.flatLabel() - p.w("if !(") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.w(") { goto __%d };", a) - p.statement(f, n.Statement, false, false, false, 0) - p.w(";goto __%d; __%d:", b, a) - p.statement(f, n.Statement2, false, false, false, 0) - p.w(";__%d:", b) - break - } - - p.w("if ") - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) - p.statement(f, n.Statement, true, false, false, 0) - p.w(" else ") - switch { - case p.isIfStmt(n.Statement2): - p.statement(f, n.Statement2, false, true, false, 0) - default: - p.statement(f, n.Statement2, true, false, false, 0) - } - case cc.SelectionStatementSwitch: // "switch" '(' Expression ')' Statement - // just dont generate in this case - if f.switchCtx == inSwitchFirst { - break - } - sv := f.switchCtx - sb := f.block - sc := p.pauseCodegen - svBreakCtx := f.breakCtx - f.breakCtx = 0 - f.block = f.blocks[n.Statement.CompoundStatement] - - defer func() { - f.block = sb - f.switchCtx = sv - f.breakCtx = svBreakCtx - p.pauseCodegen = sc - }() - if f.hasJumps { - f.switchCtx = inSwitchFlat - p.flatSwitch(f, n) - break - } - - f.switchCtx = inSwitchFirst - // fmt.Println(f.block.decls) - if len(f.block.decls) != 0 { - f.block.topDecl = true - // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) - p.w("{") - for _, v := range f.block.decls { - // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) - p.declaration(f, v, true) - // fmt.Println("done!") - } - } - - p.w("switch ") - p.expression(f, n.Expression, n.Promote(), exprValue, 0) - p.pauseCodegen = true - p.statement(f, n.Statement, true, false, true, 0) - p.pauseCodegen = false - if len(f.block.decls) != 0 { - p.w("}") - } - - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} - -func (p *project) isIfStmt(n *cc.Statement) bool { - if n.Case != cc.StatementSelection { - return false - } - - switch n.SelectionStatement.Case { - case cc.SelectionStatementIf, cc.SelectionStatementIfElse: - return true - } - - return false -} - -func (p *project) flatSwitch(f *function, n *cc.SelectionStatement) { - if n.Statement.Case != cc.StatementCompound { - panic(todo("", p.pos(n))) - } - - sv := f.block - f.block = f.blocks[n.Statement.CompoundStatement] - defer func() { f.block = sv }() - // "switch" '(' Expression ')' Statement - cases := n.Cases() - labels := map[*cc.LabeledStatement]int{} - svBreakCtx := f.breakCtx - f.breakCtx = f.flatLabel() - p.w("switch ") - p.expression(f, n.Expression, n.Promote(), exprValue, 0) - p.w("{") - for _, ls := range cases { - switch ls.Case { - case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement - continue - case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement - p.w("%scase ", tidyComment("\n", ls)) - p.constantExpression(f, ls.ConstantExpression, ls.ConstantExpression.Operand.Type(), exprValue, 0) - p.w(":") - case cc.LabeledStatementDefault: // "default" ':' Statement - p.w("%sdefault:", tidyComment("\n", ls)) - case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement - panic(todo("", p.pos(n))) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - label := f.flatLabel() - labels[ls] = label - p.w("goto __%d;", label) - } - p.w("}; goto __%d;", f.breakCtx) - svLabels := f.flatSwitchLabels - f.flatSwitchLabels = labels - p.statement(f, n.Statement, false, true, false, 0) - f.flatSwitchLabels = svLabels - p.w("__%d:", f.breakCtx) - f.breakCtx = svBreakCtx -} - -func (p *project) expressionStatement(f *function, n *cc.ExpressionStatement) { - p.w("%s", tidyComment("\n", n)) - // Expression AttributeSpecifierList ';' - if n.Expression == nil { - return - } - - p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) -} - -func (p *project) labeledStatement(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { - if f.hasJumps { //TODO merge with ...Flat below - return p.labeledStatementFlat(f, n) - } - - switch n.Case { - case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement - if _, ok := f.unusedLabels[n.Token.Value]; ok { - p.w("goto %s;", f.labelNames[n.Token.Value]) - } - p.w("%s%s:", comment("\n", n), f.labelNames[n.Token.Value]) - r = p.statement(f, n.Statement, false, false, false, 0) - case - cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement - cc.LabeledStatementDefault: // "default" ':' Statement - - p.labeledStatementCase(f, n) - case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement - panic(todo("", n.Position(), n.Case)) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - return r -} - -func (p *project) labeledStatementFlat(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { - switch n.Case { - case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement - if _, ok := f.unusedLabels[n.Token.Value]; ok { - p.w("goto %s;", f.labelNames[n.Token.Value]) - } - p.w("%s%s:", tidyComment("\n", n), f.labelNames[n.Token.Value]) - r = p.statement(f, n.Statement, false, false, false, 0) - case - cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement - cc.LabeledStatementDefault: // "default" ':' Statement - - p.labeledStatementCase(f, n) - case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement - panic(todo("", n.Position(), n.Case)) - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - return r -} - -func (p *project) labeledStatementCase(f *function, n *cc.LabeledStatement) { - switch f.switchCtx { - case inSwitchFirst: - f.switchCtx = inSwitchCase - p.pauseCodegen = false - case inSwitchCase: - p.w("\nfallthrough;") - case inSwitchSeenBreak: - f.switchCtx = inSwitchCase - case inSwitchFlat: - // ok - default: - panic(todo("", n.Position(), f.switchCtx)) - } - switch n.Case { - case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement - switch { - case f.switchCtx == inSwitchFlat: - p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) - default: - p.w("%scase ", tidyComment("\n", n)) - p.constantExpression(f, n.ConstantExpression, n.ConstantExpression.Operand.Type(), exprValue, 0) - p.w(":") - } - case cc.LabeledStatementDefault: // "default" ':' Statement - switch { - case f.switchCtx == inSwitchFlat: - p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) - default: - p.w("%sdefault:", tidyComment("\n", n)) - } - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } - p.statement(f, n.Statement, false, false, false, 0) -} - -func (p *project) constantExpression(f *function, n *cc.ConstantExpression, t cc.Type, mode exprMode, flags flags) { - // ConditionalExpression - p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) -} - -func (p *project) functionDefinitionSignature(n cc.Node, f *function, tld *tld) { - switch { - case f.mainSignatureForced: - p.w("%sfunc %s(%s *%sTLS, _ int32, _ uintptr) int32", tidyComment("\n", f.fndef), tld.name, f.tlsName, p.task.crt) - default: - p.w("%s", tidyComment("\n", f.fndef)) - p.functionSignature(n, f, f.fndef.Declarator.Type(), tld.name) - } -} - -func (p *project) functionSignature2(n cc.Node, f *function, t cc.Type, nm string) { - p.w("func %s", nm) - p.w("(_ *%sTLS", p.task.crt) - suffix := 1 - for _, v := range t.Parameters() { - if v.Type().Kind() == cc.Void { - break - } - - pn := "_" - if d := v.Declarator(); d != nil { - pn = d.Name().String() - if _, ok := reservedNames[pn]; ok { - pn += strconv.Itoa(suffix) - suffix++ - } - } - p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) - } - if t.IsVariadic() { - p.w(", _ /* va_list */ uintptr") - } - p.w(")") - if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { - p.w(" %s", p.typ(n, rt)) - } -} - -func (p *project) functionSignature(n cc.Node, f *function, t cc.Type, nm string) { - p.w("func") - if nm != "" { - p.w(" %s", nm) - } - switch { - case f == nil || nm == "": - p.w("(*%sTLS", p.task.crt) - default: - p.w("(%s *%sTLS", f.tlsName, p.task.crt) - } - for _, v := range t.Parameters() { - if v.Type().Kind() == cc.Void { - break - } - - var pn string - if f != nil && nm != "" { - pn = "_" - if d := v.Declarator(); d != nil { - if local := f.locals[d]; local != nil { - pn = local.name - } - } - } - p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) - } - if t.IsVariadic() { - switch { - case f == nil || nm == "": - p.w(", uintptr") - default: - p.w(", %s uintptr", f.vaName) - } - } - p.w(")") - if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { - p.w(" %s", p.typ(n, rt)) - } -} - -func (p *project) paramTyp(n cc.Node, t cc.Type) string { - if t.Kind() == cc.Array { - return "uintptr" - } - - if isTransparentUnion(t) { - switch k := t.UnionCommon(); k { - case cc.Ptr: - return "uintptr" - default: - panic(todo("%v: %v %k", n, t, k)) - } - } - - return p.typ(n, t) -} - -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(n, 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(n, 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 deleted file mode 100644 index 75bdc6680..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/init.go +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "fmt" - "sort" - "strings" - - "modernc.org/cc/v3" -) - -func isAggregateTypeOrUnion(t cc.Type) bool { - switch t.Kind() { - case cc.Struct, cc.Union, cc.Array: - return true - } - - return false -} - -// 6.7.8 Initialization -func (p *project) initializer(f *function, n *cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld) { - lm := map[*cc.Initializer][]cc.StringID{} - tm := map[*cc.Initializer][]cc.StringID{} - s := p.initializerFlatten(n, lm, tm) - sort.Slice(s, func(i, j int) bool { - a := s[i] - b := s[j] - if a.Offset < b.Offset { - return true - } - - if a.Offset > b.Offset { - return false - } - - if a.Field == nil || b.Field == nil || !a.Field.IsBitField() || !b.Field.IsBitField() { - 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() - }) - p.initializerInner("", 0, f, s, t, sc, tld, nil, lm, tm) -} - -func (p *project) initializerInner(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, patchField cc.Field, lm, tm map[*cc.Initializer][]cc.StringID) { - // 11: The initializer for a scalar shall be a single expression, optionally - // enclosed in braces. The initial value of the object is that of the - // expression (after conversion); the same type constraints and conversions as - // for simple assignment apply, taking the type of the scalar to be the - // unqualified version of its declared type. - if t.IsScalarType() && len(s) == 1 { - p.w("%s%s", tidyComment("", s[0]), tag) - switch { - case tld != nil && t.Kind() == cc.Ptr && s[0].AssignmentExpression.Operand.Value() == nil: - tld.patches = append(tld.patches, initPatch{t, s[0], patchField}) - p.w(" 0 ") - default: - p.assignmentExpression(f, s[0].AssignmentExpression, t, exprValue, 0) - } - return - } - - // 12: The rest of this subclause deals with initializers for objects that have - // aggregate or union type. - - k := t.Kind() - - // 13: The initializer for a structure or union object that has automatic - // storage duration shall be either an initializer list as described below, or - // a single expression that has compatible structure or union type. In the - // latter case, the initial value of the object, including unnamed members, is - // that of the expression. - if sc == cc.Automatic && len(s) == 1 { - switch k { - case cc.Struct, cc.Union: - if compatibleStructOrUnion(t, s[0].AssignmentExpression.Operand.Type()) { - p.w("%s%s", tidyComment("", s[0]), tag) - p.assignmentExpression(f, s[0].AssignmentExpression, t, exprValue, 0) - return - } - } - } - - if k == cc.Array && len(s) == 1 { - et := t.Elem() - switch { - case isCharType(et): - // 14: An array of character type may be initialized by a character string - // literal, optionally enclosed in braces. Successive characters of the - // character string literal (including the terminating null character if there - // is room or if the array is of unknown size) initialize the elements of the - // array. - if x, ok := s[0].AssignmentExpression.Operand.Value().(cc.StringValue); ok { - p.w("%s%s", tidyComment("", s[0]), tag) - str := cc.StringID(x).String() - slen := uintptr(len(str)) + 1 - alen := t.Len() - switch { - case alen < slen-1: - p.w("*(*%s)(unsafe.Pointer(%s))", p.typ(s[0], t), p.stringLiteralString(str[:alen])) - case alen < slen: - p.w("*(*%s)(unsafe.Pointer(%s))", p.typ(s[0], t), p.stringLiteralString(str)) - default: // alen >= slen - p.w("*(*%s)(unsafe.Pointer(%s))", p.typ(s[0], t), p.stringLiteralString(str+strings.Repeat("\x00", int(alen-slen)))) - } - return - } - case p.isWCharType(et): - // 15: An array with element type compatible with wchar_t may be initialized by - // a wide string literal, optionally enclosed in braces. Successive wide - // characters of the wide string literal (including the terminating null wide - // character if there is room or if the array is of unknown size) initialize - // the elements of the array. - if x, ok := s[0].AssignmentExpression.Operand.Value().(cc.WideStringValue); ok { - p.w("%s%s", tidyComment("", s[0]), tag) - str := []rune(cc.StringID(x).String()) - slen := uintptr(len(str)) + 1 - alen := t.Len() - switch { - case alen < slen-1: - panic(todo("", p.pos(s[0]))) - case alen < slen: - p.w("*(*%s)(unsafe.Pointer(%s))", p.typ(s[0], t), p.wideStringLiteral(x, 0)) - default: // alen >= slen - p.w("*(*%s)(unsafe.Pointer(%s))", p.typ(s[0], t), p.wideStringLiteral(x, int(alen-slen))) - } - return - } - } - } - - // 16: Otherwise, the initializer for an object that has aggregate or union - // type shall be a brace-enclosed list of initializers for the elements or - // named members. - switch k { - case cc.Array: - p.initializerArray(tag, off, f, s, t, sc, tld, lm, tm) - case cc.Struct: - p.initializerStruct(tag, off, f, s, t, sc, tld, lm, tm) - case cc.Union: - p.initializerUnion(tag, off, f, s, t, sc, tld, lm, tm) - default: - 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%s{}", tag, p.typ(nil, t)) - return - } - - et := t.Elem() - esz := et.Size() - s0 := s[0] - p.w("%s%s%s{", initComment(s0, lm), tag, p.typ(s0, t)) - var a [][]*cc.Initializer - for len(s) != 0 { - s2, parts, _ := p.initializerArrayElement(off, s, esz) - s = s2 - a = append(a, parts) - } - mustIndex := uintptr(len(a)) != t.Len() - var parts []*cc.Initializer - for _, parts = range a { - var comma *cc.Token - comma = parts[len(parts)-1].TrailingComma() - elemOff := (parts[0].Offset - off) / esz * esz - tag = "" - if mustIndex { - tag = fmt.Sprintf("%d:", elemOff/esz) - } - p.initializerInner(tag, off+elemOff, f, parts, et, sc, tld, nil, lm, tm) - p.preCommaSep(comma) - p.w(",") - } - p.w("%s}", initComment(parts[len(parts)-1], tm)) -} - -func initComment(n *cc.Initializer, m map[*cc.Initializer][]cc.StringID) string { - a := m[n] - if len(a) == 0 { - return "" - } - - m[n] = a[1:] - return tidyCommentString(a[0].String()) -} - -func (p *project) initializerArrayElement(off uintptr, s []*cc.Initializer, elemSize uintptr) (r []*cc.Initializer, parts []*cc.Initializer, isZero bool) { - r = s - isZero = true - valueOff := s[0].Offset - off - elemOff := valueOff - valueOff%elemSize - nextOff := elemOff + elemSize - for len(s) != 0 { - if v := s[0]; v.Offset-off < nextOff { - s = s[1:] - parts = append(parts, v) - if !v.AssignmentExpression.Operand.IsZero() { - isZero = false - } - continue - } - - break - } - return r[len(parts):], parts, isZero -} - -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%s{}", tag, p.typ(nil, t)) - return - } - - if t.HasFlexibleMember() { - p.err(s[0], "flexible array members not supported") - return - } - - p.w("%s%s%s{", initComment(s[0], lm), tag, p.typ(s[0], t)) - var parts []*cc.Initializer - var isZero bool - var fld cc.Field - for len(s) != 0 { - var comma *cc.Token - s, fld, parts, isZero = p.structInitializerParts(off, s, t) - if isZero { - continue - } - - if fld.Type().IsIncomplete() { - panic(todo("")) - } - - comma = parts[len(parts)-1].TrailingComma() - tag = fmt.Sprintf("%s:", p.fieldName2(parts[0], fld)) - 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() { - continue - } - - if !first { - p.w("|") - } - first = false - bitFld := v.Field - p.w("%s%s", tidyComment("", v.AssignmentExpression), tag) - tag = "" - p.assignmentExpression(f, v.AssignmentExpression, bft, exprValue, 0) - p.w("&%#x", uint64(1)<<uint64(bitFld.BitFieldWidth())-1) - if o := bitFld.BitFieldOffset() + 8*int((bitFld.Offset()-off0)); o != 0 { - p.w("<<%d", o) - } - } - default: - p.initializerInner(tag, off+fld.Offset(), f, parts, ft, sc, tld, fld, lm, tm) - } - p.preCommaSep(comma) - p.w(",") - } - p.w("%s}", initComment(parts[len(parts)-1], tm)) -} - -func (p *project) preCommaSep(comma *cc.Token) { - if comma == nil { - return - } - - p.w("%s", strings.TrimSpace(comma.Sep.String())) -} - -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 - } - - 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 - } - - isZero = isZero && part.AssignmentExpression.Operand.IsZero() - parts = append(parts, part) - s = s[1:] - } - 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 - } - - 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 - } - } - - panic(todo("%v: internal error", p.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%s{}", tag, p.typ(nil, t)) - return - } - - if t.HasFlexibleMember() { - p.err(s[0], "flexible array members not supported") - return - } - - 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("%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", p.pos(part), et, x)) - } - case p.isWCharType(et): - panic(todo("")) - } - 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, 0) - 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, 0) - } - p.w("\n") - } - p.w("return r\n") - p.w("}()") -} - -func (p *project) initializerUnionField(off uintptr, s []*cc.Initializer, t cc.Type) (parts []*cc.Initializer, isZero bool) { - isZero = true - nextOff := off + t.Size() - for len(s) != 0 { - if v := s[0]; v.Offset < nextOff { - s = s[1:] - parts = append(parts, v) - isZero = isZero && v.AssignmentExpression.Operand.IsZero() - continue - } - - break - } - return parts, isZero -} - -func compatibleStructOrUnion(t1, t2 cc.Type) bool { - switch t1.Kind() { - case cc.Struct: - if t2.Kind() != cc.Struct { - return false - } - case cc.Union: - if t2.Kind() != cc.Union { - return false - } - default: - return false - } - - if tag := t1.Tag(); tag != 0 && t2.Tag() != tag { - return false - } - - nf := t1.NumField() - if t2.NumField() != nf { - return false - } - - for i := []int{0}; i[0] < nf; i[0]++ { - f1 := t1.FieldByIndex(i) - f2 := t2.FieldByIndex(i) - nm := f1.Name() - if f2.Name() != nm { - return false - } - - ft1 := f1.Type() - ft2 := f2.Type() - if ft1.Size() != ft2.Size() || - f1.IsBitField() != f2.IsBitField() || - f1.BitFieldOffset() != f2.BitFieldOffset() || - f1.BitFieldWidth() != f2.BitFieldWidth() { - return false - } - - if !compatibleType(ft1, ft2) { - return false - } - } - return true -} - -func compatibleType(t1, t2 cc.Type) bool { - if t1.Kind() != t2.Kind() { - return false - } - - switch t1.Kind() { - case cc.Array: - if t1.Len() != t2.Len() || !compatibleType(t1.Elem(), t2.Elem()) { - return false - } - case cc.Struct, cc.Union: - if !compatibleStructOrUnion(t1, t2) { - return false - } - } - return true -} - -func (p *project) bitFileType(n cc.Node, bits int) cc.Type { - switch bits { - case 8: - return p.task.cfg.ABI.Type(cc.UChar) - case 16: - return p.task.cfg.ABI.Type(cc.UShort) - case 32: - return p.task.cfg.ABI.Type(cc.UInt) - case 64: - return p.task.cfg.ABI.Type(cc.ULongLong) - default: - panic(todo("%v: internal error: %v", n.Position(), bits)) - } -} - -func (p *project) isWCharType(t cc.Type) bool { - if t.IsAliasType() { - if id := t.AliasDeclarator().Name(); id == idWcharT || - p.task.goos == "windows" && id == idWinWchar { - return true - } - } - - return false -} - -func isCharType(t cc.Type) bool { - switch t.Kind() { - case cc.Char, cc.SChar, cc.UChar: - return true - } - - return false -} - -func (p *project) initializerFlatten(n *cc.Initializer, lm, tm map[*cc.Initializer][]cc.StringID) (s []*cc.Initializer) { - switch n.Case { - case cc.InitializerExpr: // AssignmentExpression - return append(s, n) - case cc.InitializerInitList: // '{' InitializerList ',' '}' - first := true - for list := n.InitializerList; list != nil; list = list.InitializerList { - in := list.Initializer - k := in - if in.Case != cc.InitializerExpr { - k = nil - } - if first { - lm[k] = append(lm[k], append(lm[nil], n.Token.Sep)...) - if k != nil { - delete(lm, nil) - } - first = false - } - if list.InitializerList == nil { - tm[k] = append([]cc.StringID{n.Token3.Sep}, append(tm[nil], tm[k]...)...) - tm[k] = append(tm[k], append(tm[nil], n.Token3.Sep)...) - if k != nil { - delete(tm, nil) - } - } - s = append(s, p.initializerFlatten(in, lm, tm)...) - } - return s - default: - panic(todo("%v: internal error: %v", n.Position(), n.Case)) - } -} diff --git a/vendor/modernc.org/ccgo/v3/lib/mem.go b/vendor/modernc.org/ccgo/v3/lib/mem.go deleted file mode 100644 index daf6c9239..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/mem.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// 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" - -var totalRam uint64 diff --git a/vendor/modernc.org/ccgo/v3/lib/mem_linux.go b/vendor/modernc.org/ccgo/v3/lib/mem_linux.go deleted file mode 100644 index 25612c6b1..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/mem_linux.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "golang.org/x/sys/unix" -) - -var totalRam uint64 - -func init() { - var si unix.Sysinfo_t - if unix.Sysinfo(&si) != nil { - return - } - - totalRam = uint64(si.Totalram) -} diff --git a/vendor/modernc.org/ccgo/v3/lib/nodmesg.go b/vendor/modernc.org/ccgo/v3/lib/nodmesg.go deleted file mode 100644 index 8871c8ecc..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/nodmesg.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 The Libc Authors. All rights reserved. -// 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" - -const dmesgs = false - -func dmesg(s string, args ...interface{}) {} diff --git a/vendor/modernc.org/ccgo/v3/lib/stringer.go b/vendor/modernc.org/ccgo/v3/lib/stringer.go deleted file mode 100644 index dee785cad..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/stringer.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by "stringer -output stringer.go -type=exprMode,opKind"; DO NOT EDIT. - -package ccgo - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[exprAddrOf-1] - _ = x[exprBool-2] - _ = x[exprCondInit-3] - _ = x[exprCondReturn-4] - _ = x[exprDecay-5] - _ = x[exprFunc-6] - _ = x[exprLValue-7] - _ = x[exprPSelect-8] - _ = x[exprSelect-9] - _ = x[exprValue-10] - _ = x[exprVoid-11] - _ = x[exprGoPtr-12] -} - -const _exprMode_name = "exprAddrOfexprBoolexprCondInitexprCondReturnexprDecayexprFuncexprLValueexprPSelectexprSelectexprValueexprVoidexprGoPtr" - -var _exprMode_index = [...]uint8{0, 10, 18, 30, 44, 53, 61, 71, 82, 92, 101, 109, 118} - -func (i exprMode) String() string { - i -= 1 - if i < 0 || i >= exprMode(len(_exprMode_index)-1) { - return "exprMode(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _exprMode_name[_exprMode_index[i]:_exprMode_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[opNormal-0] - _ = x[opArray-1] - _ = x[opArrayParameter-2] - _ = x[opFunction-3] - _ = x[opUnion-4] - _ = x[opBitfield-5] - _ = x[opStruct-6] -} - -const _opKind_name = "opNormalopArrayopArrayParameteropFunctionopUnionopBitfieldopStruct" - -var _opKind_index = [...]uint8{0, 8, 15, 31, 41, 48, 58, 66} - -func (i opKind) String() string { - if i < 0 || i >= opKind(len(_opKind_index)-1) { - return "opKind(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _opKind_name[_opKind_index[i]:_opKind_index[i+1]] -} diff --git a/vendor/modernc.org/ccgo/v3/lib/unconvert.sh b/vendor/modernc.org/ccgo/v3/lib/unconvert.sh deleted file mode 100644 index af3b87f83..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/unconvert.sh +++ /dev/null @@ -1,4 +0,0 @@ -until unconvert -fastmath . &> /dev/null -do - unconvert -fastmath -apply . &> /dev/null -done diff --git a/vendor/modernc.org/ccgo/v3/lib/util.go b/vendor/modernc.org/ccgo/v3/lib/util.go deleted file mode 100644 index f11e439ca..000000000 --- a/vendor/modernc.org/ccgo/v3/lib/util.go +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright 2020 The CCGO Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// generator.go helpers - -package ccgo // import "modernc.org/ccgo/v3/lib" - -import ( - "archive/tar" - "bufio" - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "runtime/debug" - "strings" -) - -// CopyFile copies src to dest, preserving permissions and times where/when -// possible. If canOverwrite is not nil, it is consulted whether a destination -// file can be overwritten. If canOverwrite is nil then destination is -// overwritten if permissions allow that, otherwise the function fails. -// -// Src and dst must be in the slash form. -func CopyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (n int64, rerr error) { - dst = filepath.FromSlash(dst) - dstDir := filepath.Dir(dst) - di, err := os.Stat(dstDir) - switch { - case err != nil: - if !os.IsNotExist(err) { - return 0, err - } - - if err := os.MkdirAll(dstDir, 0770); err != nil { - return 0, err - } - case err == nil: - if !di.IsDir() { - return 0, fmt.Errorf("cannot create directory, file exists: %s", dst) - } - } - - src = filepath.FromSlash(src) - si, err := os.Stat(src) - if err != nil { - return 0, err - } - - if si.IsDir() { - return 0, fmt.Errorf("cannot copy a directory: %s", src) - } - - di, err = os.Stat(dst) - switch { - case err != nil && !os.IsNotExist(err): - return 0, err - case err == nil: - if di.IsDir() { - return 0, fmt.Errorf("cannot overwite a directory: %s", dst) - } - - if canOverwrite != nil && !canOverwrite(dst, di) { - return 0, fmt.Errorf("cannot overwite: %s", dst) - } - } - - s, err := os.Open(src) - if err != nil { - return 0, err - } - - defer s.Close() - r := bufio.NewReader(s) - - d, err := os.Create(dst) - - defer func() { - if err := d.Close(); err != nil && rerr == nil { - rerr = err - return - } - - if err := os.Chmod(dst, si.Mode()); err != nil && rerr == nil { - rerr = err - return - } - - if err := os.Chtimes(dst, si.ModTime(), si.ModTime()); err != nil && rerr == nil { - rerr = err - return - } - }() - - w := bufio.NewWriter(d) - - defer func() { - if err := w.Flush(); err != nil && rerr == nil { - rerr = err - } - }() - - return io.Copy(w, r) -} - -// MustCopyFile is like CopyFile but it executes Fatal(stackTrace, err) if it fails. -func MustCopyFile(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) int64 { - n, err := CopyFile(dst, src, canOverwrite) - if err != nil { - Fatal(stackTrace, err) - } - - return n -} - -// CopyDir recursively copies src to dest, preserving permissions and times -// where/when possible. If canOverwrite is not nil, it is consulted whether a -// destination file can be overwritten. If canOverwrite is nil then destination -// is overwritten if permissions allow that, otherwise the function fails. -// -// Src and dst must be in the slash form. -func CopyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (files int, bytes int64, rerr error) { - dst = filepath.FromSlash(dst) - src = filepath.FromSlash(src) - si, err := os.Stat(src) - if err != nil { - return 0, 0, err - } - - if !si.IsDir() { - return 0, 0, fmt.Errorf("cannot copy a file: %s", src) - } - - return files, bytes, filepath.Walk(src, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - rel, err := filepath.Rel(src, path) - if err != nil { - return err - } - - if info.IsDir() { - return os.MkdirAll(filepath.Join(dst, rel), 0770) - } - - n, err := CopyFile(filepath.Join(dst, rel), path, canOverwrite) - if err != nil { - return err - } - - files++ - bytes += n - return nil - }) -} - -// MustCopyDir is like CopyDir, but it executes Fatal(stackTrace, errĂº if it fails. -func MustCopyDir(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (files int, bytes int64) { - file, bytes, err := CopyDir(dst, src, canOverwrite) - if err != nil { - Fatal(stackTrace, err) - } - - return file, bytes -} - -// UntarFile extracts a named tar.gz archive into dst. If canOverwrite is not -// nil, it is consulted whether a destination file can be overwritten. If -// canOverwrite is nil then destination is overwritten if permissions allow -// that, otherwise the function fails. -// -// Src and dst must be in the slash form. -func UntarFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) error { - f, err := os.Open(filepath.FromSlash(src)) - if err != nil { - return err - } - - defer f.Close() - - return Untar(dst, bufio.NewReader(f), canOverwrite) -} - -// MustUntarFile is like UntarFile but it executes Fatal(stackTrace, err) if it fails. -func MustUntarFile(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) { - if err := UntarFile(dst, src, canOverwrite); err != nil { - Fatal(stackTrace, err) - } -} - -// Untar extracts a tar.gz archive into dst. If canOverwrite is not nil, it is -// consulted whether a destination file can be overwritten. If canOverwrite is -// nil then destination is overwritten if permissions allow that, otherwise the -// function fails. -// -// Dst must be in the slash form. -func Untar(dst string, r io.Reader, canOverwrite func(fn string, fi os.FileInfo) bool) error { - dst = filepath.FromSlash(dst) - gr, err := gzip.NewReader(r) - if err != nil { - return err - } - - tr := tar.NewReader(gr) - for { - hdr, err := tr.Next() - if err != nil { - if err != io.EOF { - return err - } - - return nil - } - - switch hdr.Typeflag { - case tar.TypeDir: - dir := filepath.Join(dst, hdr.Name) - if err = os.MkdirAll(dir, 0770); err != nil { - return err - } - case tar.TypeSymlink, tar.TypeXGlobalHeader: - // skip - case tar.TypeReg, tar.TypeRegA: - dir := filepath.Dir(filepath.Join(dst, hdr.Name)) - if _, err := os.Stat(dir); err != nil { - if !os.IsNotExist(err) { - return err - } - - if err = os.MkdirAll(dir, 0770); err != nil { - return err - } - } - - fn := filepath.Join(dst, hdr.Name) - f, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode)) - if err != nil { - return err - } - - w := bufio.NewWriter(f) - if _, err = io.Copy(w, tr); err != nil { - return err - } - - if err := w.Flush(); err != nil { - return err - } - - if err := f.Close(); err != nil { - return err - } - - if err := os.Chtimes(fn, hdr.AccessTime, hdr.ModTime); err != nil { - return err - } - default: - return fmt.Errorf("unexpected tar header typeflag %#02x", hdr.Typeflag) - } - } - -} - -// MustUntar is like Untar but it executes Fatal(stackTrace, err) if it fails. -func MustUntar(stackTrace bool, dst string, r io.Reader, canOverwrite func(fn string, fi os.FileInfo) bool) { - if err := Untar(dst, r, canOverwrite); err != nil { - Fatal(stackTrace, err) - } -} - -// Fatalf prints a formatted message to os.Stderr and performs os.Exit(1). A -// stack trace is added if stackTrace is true. -func Fatalf(stackTrace bool, s string, args ...interface{}) { - if stackTrace { - fmt.Fprintf(os.Stderr, "%s\n", debug.Stack()) - } - fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprintf(s, args...))) - os.Exit(1) -} - -// Fatal prints its argumenst to os.Stderr and performs os.Exit(1). A -// stack trace is added if stackTrace is true. -func Fatal(stackTrace bool, args ...interface{}) { - if stackTrace { - fmt.Fprintf(os.Stderr, "%s\n", debug.Stack()) - } - fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprint(args...))) - os.Exit(1) -} - -// Mkdirs will create all paths. Paths must be in slash form. -func Mkdirs(paths ...string) error { - for _, path := range paths { - path = filepath.FromSlash(path) - if err := os.MkdirAll(path, 0770); err != nil { - return err - } - } - - return nil -} - -// MustMkdirs is like Mkdir but if executes Fatal(stackTrace, err) if it fails. -func MustMkdirs(stackTrace bool, paths ...string) { - if err := Mkdirs(paths...); err != nil { - Fatal(stackTrace, err) - } -} - -// InDir executes f in dir. Dir must be in slash form. -func InDir(dir string, f func() error) (err error) { - var cwd string - if cwd, err = os.Getwd(); err != nil { - return err - } - - defer func() { - if err2 := os.Chdir(cwd); err2 != nil { - err = err2 - } - }() - - if err = os.Chdir(filepath.FromSlash(dir)); err != nil { - return err - } - - return f() -} - -// MustInDir is like InDir but it executes Fatal(stackTrace, err) if it fails. -func MustInDir(stackTrace bool, dir string, f func() error) { - if err := InDir(dir, f); err != nil { - Fatal(stackTrace, err) - } -} - -type echoWriter struct { - w bytes.Buffer -} - -func (w *echoWriter) Write(b []byte) (int, error) { - os.Stdout.Write(b) - return w.w.Write(b) -} - -// Shell echoes and executes cmd with args and returns the combined output if the command. -func Shell(cmd string, args ...string) ([]byte, error) { - cmd, err := exec.LookPath(cmd) - if err != nil { - return nil, err - } - - wd, err := AbsCwd() - if err != nil { - return nil, err - } - - fmt.Printf("execute %s %q in %s\n", cmd, args, wd) - var b echoWriter - c := exec.Command(cmd, args...) - c.Stdout = &b - c.Stderr = &b - err = c.Run() - return b.w.Bytes(), err -} - -// MustShell is like Shell but it executes Fatal(stackTrace, err) if it fails. -func MustShell(stackTrace bool, cmd string, args ...string) []byte { - b, err := Shell(cmd, args...) - if err != nil { - Fatalf(stackTrace, "%v %s\noutput: %s\nerr: %s", cmd, args, b, err) - } - - return b -} - -// Compile executes Shell with cmd set to "ccgo". -func Compile(args ...string) ([]byte, error) { return Shell("ccgo", args...) } - -// MustCompile is like Compile but if executes Fatal(stackTrace, err) if it fails. -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() - if err != nil { - return "", err - } - - if wd, err = filepath.Abs(wd); err != nil { - return "", err - } - - return wd, nil -} - -// MustAbsCwd is like AbsCwd but executes Fatal(stackTrace, err) if it fails. -func MustAbsCwd(stackTrace bool) string { - s, err := AbsCwd() - if err != nil { - Fatal(stackTrace, err) - } - - return s -} - -// Env returns the value of environmental variable key of dflt otherwise. -func Env(key, dflt string) string { - if s := os.Getenv(key); s != "" { - return s - } - - return dflt -} - -// MustTempDir is like ioutil.TempDir but executes Fatal(stackTrace, err) if it -// fails. The returned path is absolute. -func MustTempDir(stackTrace bool, dir, name string) string { - s, err := ioutil.TempDir(dir, name) - if err != nil { - Fatal(stackTrace, err) - } - - if s, err = filepath.Abs(s); err != nil { - Fatal(stackTrace, err) - } - - return s -} |