summaryrefslogtreecommitdiff
path: root/vendor/modernc.org/ccgo
diff options
context:
space:
mode:
authorLibravatar dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-03-04 09:42:11 +0000
committerLibravatar GitHub <noreply@github.com>2024-03-04 09:42:11 +0000
commitadb4cdcf6c9eacd369eaaf5b21774b198d57c040 (patch)
treea4f9c8fe2ce147fa952bcb795690afb9bb2affcb /vendor/modernc.org/ccgo
parent[bugfix] update postgresqlstmt to correctly use postgres err hook (#2711) (diff)
downloadgotosocial-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/LICENSE27
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/Makefile141
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/ccgo.go2148
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/cover.go39
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/design-notes.adoc91
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/dmesg.go43
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/etc.go110
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/go.go13164
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/init.go553
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/mem.go10
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/mem_linux.go20
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/nodmesg.go12
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/stringer.go58
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/unconvert.sh4
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/util.go458
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
-}